@openclaw/google-meet 2026.9.6 → 2026.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/assets/icon.png +0 -0
  2. package/dist/.setup/{chrome-create-BZRBHJp9.mjs → chrome-create-wuAK5Pnq.mjs} +14 -19
  3. package/dist/.setup/{cli-CbxqjjTC.mjs → cli-DVDq0TFu.mjs} +27 -695
  4. package/dist/.setup/cli-export-D4IM6KLJ.mjs +632 -0
  5. package/dist/.setup/config-BXGAMntj.mjs +240 -0
  6. package/dist/.setup/{create-CG9Pgwsb.mjs → create-UrHOmnWb.mjs} +4 -17
  7. package/dist/.setup/{google-meet-platform-adapter-DQZ74Kd5.mjs → google-meet-platform-adapter-gosgbMIM.mjs} +337 -228
  8. package/dist/.setup/{google-meet-platform-constants-Bs5iAg3E.mjs → google-meet-platform-constants-CnRfrYX7.mjs} +1 -4
  9. package/dist/.setup/{node-host-BUrsParx.mjs → node-host-Tr7Mx3da.mjs} +3 -3
  10. package/dist/.setup/{node-invoke-policy-hwXq9MfV.mjs → node-invoke-policy-Dd3krTYV.mjs} +2 -2
  11. package/dist/.setup/{oauth-22Ey-zCb.mjs → oauth-BoyruWcS.mjs} +2 -2
  12. package/dist/.setup/{plugin-helpers--7X3icub.mjs → plugin-helpers-CdQ_YNA7.mjs} +147 -236
  13. package/dist/.setup/{plugin-registration-B3LXKV4R.mjs → plugin-registration-aCEuCerg.mjs} +34 -10
  14. package/dist/.setup/{runtime-BuIZ5e3V.mjs → runtime-BdiF53A2.mjs} +85 -41
  15. package/dist/doctor-contract-api.js +3 -6
  16. package/dist/index.js +48 -12
  17. package/node_modules/typebox/build/compile/code.mjs +1 -2
  18. package/node_modules/typebox/build/compile/validator.mjs +5 -1
  19. package/node_modules/typebox/build/format/iri.mjs +16 -9
  20. package/node_modules/typebox/build/guard/emit.mjs +2 -2
  21. package/node_modules/typebox/build/guard/guard.d.mts +7 -5
  22. package/node_modules/typebox/build/guard/guard.mjs +14 -9
  23. package/node_modules/typebox/build/guard/index.mjs +6 -0
  24. package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
  25. package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
  26. package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
  27. package/node_modules/typebox/build/schema/build.mjs +2 -3
  28. package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
  29. package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
  30. package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
  31. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
  32. package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
  33. package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
  34. package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
  35. package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
  36. package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
  37. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
  38. package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
  39. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
  40. package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
  41. package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
  42. package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
  43. package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
  44. package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
  45. package/node_modules/typebox/build/schema/parse.mjs +3 -0
  46. package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
  47. package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
  48. package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
  49. package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
  50. package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
  51. package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
  52. package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
  53. package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
  54. package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
  55. package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
  56. package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
  57. package/node_modules/typebox/package.json +1 -1
  58. package/node_modules/typebox/readme.md +3 -1
  59. package/package.json +5 -5
  60. package/dist/.setup/config-C-6enWkx.mjs +0 -328
  61. package/dist/.setup/google-api-errors-BDYXfKRa.mjs +0 -17
  62. /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
@@ -1,28 +1,23 @@
1
- import { n as GOOGLE_MEET_NODE_COMMAND, t as GOOGLE_MEET_BROWSER_NODE_ADAPTER } from "./google-meet-platform-constants-Bs5iAg3E.mjs";
1
+ import { n as GOOGLE_MEET_NODE_COMMAND, t as GOOGLE_MEET_BROWSER_NODE_ADAPTER } from "./google-meet-platform-constants-CnRfrYX7.mjs";
2
2
  import { t as normalizeMeetUrl } from "./meet-url-BP2Jlvjs.mjs";
3
- import { c as callBrowserProxyOnNode, l as resolveChromeNode, u as resolveChromeNodeInfo } from "./chrome-create-BZRBHJp9.mjs";
4
- import { n as normalizeDialInNumber, t as GOOGLE_MEET_PLATFORM_ADAPTER } from "./google-meet-platform-adapter-DQZ74Kd5.mjs";
3
+ import { c as callBrowserProxyOnNode, l as resolveChromeNode, u as resolveChromeNodeInfo } from "./chrome-create-wuAK5Pnq.mjs";
4
+ import { n as normalizeDialInNumber, t as GOOGLE_MEET_PLATFORM_ADAPTER } from "./google-meet-platform-adapter-gosgbMIM.mjs";
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 { GatewayClient, startGatewayClientWhenEventLoopReady } from "openclaw/plugin-sdk/gateway-runtime";
8
7
  import path from "node:path";
9
8
  import { isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
10
- import { MeetingPlatformAdapter, MeetingSessionRuntime, addMeetingSetupCheck, createMeetingSession, createMeetingSetupStatus, createMeetingVoiceCallGateway, endMeetingVoiceCallGatewayCall, getMeetingVoiceCallGatewayCall, isMeetingVoiceCallMissingError, joinMeetingViaVoiceCallGateway, leaveMeetingWithBrowser, readMeetingTranscriptWithBrowser, recoverMeetingBrowserTab, resolveLocalMeetingBrowserRequest, speakMeetingViaVoiceCallGateway } from "openclaw/plugin-sdk/meeting-runtime";
9
+ import { GatewayClient, startGatewayClientWhenEventLoopReady } from "openclaw/plugin-sdk/gateway-runtime";
10
+ import { MeetingPlatformAdapter, MeetingSessionRuntime, addMeetingSetupCheck, createMeetingSession, createMeetingSetupStatus, createMeetingVoiceCallGateway, endMeetingVoiceCallGatewayCall, getMeetingVoiceCallGatewayCall, isMeetingVoiceCallMissingError, joinMeetingViaVoiceCallGateway, leaveMeetingWithBrowser, readMeetingTranscriptWithBrowser, recoverMeetingBrowserTab, resolveLocalMeetingBrowserRequest, runMeetingParticipationWithBrowser, speakMeetingViaVoiceCallGateway } from "openclaw/plugin-sdk/meeting-runtime";
11
11
  import { resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
12
12
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
13
13
  import fs from "node:fs";
14
14
  import os from "node:os";
15
15
  import { resolveTranscriptsConfig } from "openclaw/plugin-sdk/transcripts";
16
16
  //#region extensions/google-meet/src/runtime-probes.ts
17
- function resolveProbeTimeoutMs(input, fallback) {
18
- if (input === void 0) return Math.min(Math.max(fallback, 1), 12e4);
19
- if (!Number.isFinite(input) || input <= 0) throw new Error("timeoutMs must be a positive number");
20
- return Math.min(Math.trunc(input), 12e4);
21
- }
22
17
  const probes = MeetingPlatformAdapter.createRuntimeProbes({
23
18
  defaultSpeechMessage: "Say exactly: Google Meet speech test complete.",
24
19
  invalidRequest: (message) => new Error(message),
25
- resolveTimeoutMs: resolveProbeTimeoutMs,
20
+ resolveTimeoutMs: MeetingPlatformAdapter.resolveProbeTimeoutMs,
26
21
  shouldWaitForListening: (session) => Boolean((session.transport === "chrome" || session.transport === "chrome-node") && session.chrome?.launched),
27
22
  talkBackMode: MeetingPlatformAdapter.isTalkBackMode,
28
23
  normalizeUrl: normalizeMeetUrl,
@@ -200,9 +195,6 @@ function getGoogleMeetSetupStatus(config, options) {
200
195
  }
201
196
  return createMeetingSetupStatus(checks);
202
197
  }
203
- function addGoogleMeetSetupCheck(status, check) {
204
- return addMeetingSetupCheck(status, check);
205
- }
206
198
  //#endregion
207
199
  //#region extensions/google-meet/src/transports/chrome.ts
208
200
  const chromeTransport = MeetingPlatformAdapter.createChromeTransportWithExternalAudio({
@@ -218,13 +210,7 @@ const chromeTransport = MeetingPlatformAdapter.createChromeTransportWithExternal
218
210
  });
219
211
  const assertGoogleMeetAudioAvailable = chromeTransport.assertAudioDeviceAvailable;
220
212
  const launchChromeMeetOnNode = chromeTransport.launchOnNode;
221
- async function launchChromeMeet(params) {
222
- const result = await chromeTransport.launchInChrome(params);
223
- return {
224
- ...result,
225
- audioBridge: result.audioBridge
226
- };
227
- }
213
+ const launchChromeMeet = chromeTransport.launchInChrome;
228
214
  function shouldCaptureCaptions(mode, fullConfig) {
229
215
  return mode === "transcribe" || !fullConfig || resolveTranscriptsConfig(fullConfig.transcripts).enabled;
230
216
  }
@@ -329,7 +315,7 @@ async function getGoogleMeetRuntimeSetupStatus(params) {
329
315
  requestedNode: params.config.chromeNode.node
330
316
  });
331
317
  const label = node.displayName ?? node.remoteIp ?? node.nodeId ?? "connected node";
332
- status = addGoogleMeetSetupCheck(status, {
318
+ status = addMeetingSetupCheck(status, {
333
319
  id: "chrome-node-connected",
334
320
  ok: true,
335
321
  message: `Connected Google Meet node ready: ${label}`
@@ -348,14 +334,14 @@ async function getGoogleMeetRuntimeSetupStatus(params) {
348
334
  },
349
335
  timeoutMs: 12e3
350
336
  });
351
- status = addGoogleMeetSetupCheck(status, {
337
+ status = addMeetingSetupCheck(status, {
352
338
  id: "chrome-node-audio-prerequisites",
353
339
  ok: true,
354
340
  message: setup ? "Remote virtual audio backend and command-pair prerequisites are ready" : "Remote audio setup completed"
355
341
  });
356
342
  }
357
343
  } catch (error) {
358
- status = addGoogleMeetSetupCheck(status, {
344
+ status = addMeetingSetupCheck(status, {
359
345
  id: "chrome-node-connected",
360
346
  ok: false,
361
347
  message: formatErrorMessage(error)
@@ -368,13 +354,13 @@ async function getGoogleMeetRuntimeSetupStatus(params) {
368
354
  config: params.config,
369
355
  timeoutMs: Math.min(params.config.chrome.joinTimeoutMs, 1e4)
370
356
  });
371
- status = addGoogleMeetSetupCheck(status, {
357
+ status = addMeetingSetupCheck(status, {
372
358
  id: "chrome-local-audio-device",
373
359
  ok: true,
374
360
  message: "Virtual meeting audio backend is ready"
375
361
  });
376
362
  } catch (error) {
377
- status = addGoogleMeetSetupCheck(status, {
363
+ status = addMeetingSetupCheck(status, {
378
364
  id: "chrome-local-audio-device",
379
365
  ok: false,
380
366
  message: formatErrorMessage(error)
@@ -387,13 +373,51 @@ async function getGoogleMeetRuntimeSetupStatus(params) {
387
373
  } catch {
388
374
  missingCommands.push(command);
389
375
  }
390
- return addGoogleMeetSetupCheck(status, {
376
+ return addMeetingSetupCheck(status, {
391
377
  id: "chrome-local-audio-commands",
392
378
  ok: commands.length > 0 && missingCommands.length === 0,
393
379
  message: commands.length === 0 ? "Chrome talk-back audio commands are not configured" : missingCommands.length === 0 ? `Chrome audio command${commands.length === 1 ? "" : "s"} available: ${commands.join(", ")}` : `Chrome audio command${missingCommands.length === 1 ? "" : "s"} missing: ${missingCommands.join(", ")}`
394
380
  });
395
381
  }
396
382
  //#endregion
383
+ //#region extensions/google-meet/src/transports/chrome-participation.ts
384
+ async function participateInChromeMeet(params) {
385
+ const adapter = GOOGLE_MEET_PLATFORM_ADAPTER.browser.participation;
386
+ const { session } = params;
387
+ const tab = session.chrome?.browserTab;
388
+ if (!adapter || !tab || session.transport !== "chrome" && session.transport !== "chrome-node") return {
389
+ status: "unsupported",
390
+ message: "Participation requires a supported tracked browser meeting."
391
+ };
392
+ const { nodeId } = session.chrome ?? {};
393
+ const meetingSessionId = session.id;
394
+ const meetingUrl = session.url;
395
+ const targetId = tab.targetId;
396
+ if (session.transport === "chrome-node" && nodeId === void 0) return {
397
+ status: "rejected",
398
+ message: "The meeting has no pinned browser node."
399
+ };
400
+ params.assertCurrent();
401
+ const callBrowser = session.transport === "chrome-node" ? (request) => callBrowserProxyOnNode({
402
+ ...request,
403
+ runtime: params.runtime,
404
+ nodeId
405
+ }) : await resolveLocalMeetingBrowserRequest(params.runtime);
406
+ params.assertCurrent();
407
+ return await runMeetingParticipationWithBrowser({
408
+ adapter,
409
+ callBrowser,
410
+ meetingSessionId,
411
+ meetingUrl,
412
+ targetId,
413
+ requestId: params.request.requestId,
414
+ action: params.request.action,
415
+ assertCurrent: () => params.assertCurrent(),
416
+ isSameMeetingUrl: (left, right) => GOOGLE_MEET_PLATFORM_ADAPTER.urls.isSameMeeting(left, right),
417
+ timeoutMs: Math.min(1e4, params.config.chrome.joinTimeoutMs)
418
+ });
419
+ }
420
+ //#endregion
397
421
  //#region extensions/google-meet/src/voice-call-gateway.ts
398
422
  const GOOGLE_MEET_VOICE_CALL_SURFACE = {
399
423
  clientDisplayName: "Google Meet plugin",
@@ -458,7 +482,6 @@ function createVoiceCallGateway(params) {
458
482
  connectClient: createConnectedGatewayClient
459
483
  });
460
484
  }
461
- const isVoiceCallMissingError = isMeetingVoiceCallMissingError;
462
485
  async function joinMeetViaVoiceCallGateway(params) {
463
486
  return await joinMeetingViaVoiceCallGateway({
464
487
  ...params,
@@ -466,15 +489,6 @@ async function joinMeetViaVoiceCallGateway(params) {
466
489
  surface: GOOGLE_MEET_VOICE_CALL_SURFACE
467
490
  });
468
491
  }
469
- async function endMeetVoiceCallGatewayCall(params) {
470
- await endMeetingVoiceCallGatewayCall(params);
471
- }
472
- async function getMeetVoiceCallGatewayCall(params) {
473
- return await getMeetingVoiceCallGatewayCall(params);
474
- }
475
- async function speakMeetViaVoiceCallGateway(params) {
476
- await speakMeetingViaVoiceCallGateway(params);
477
- }
478
492
  //#endregion
479
493
  //#region extensions/google-meet/src/runtime.ts
480
494
  const nowIso = () => (/* @__PURE__ */ new Date()).toISOString();
@@ -491,7 +505,31 @@ var GoogleMeetRuntime = class {
491
505
  this.transcriptSourceRuntime = () => this.#sessions;
492
506
  const adapter = GOOGLE_MEET_PLATFORM_ADAPTER;
493
507
  this.#voiceCallGateway = createVoiceCallGateway(params);
508
+ let participationStore;
509
+ const getParticipationStore = () => participationStore ??= params.runtime.state.openKeyedStore({
510
+ namespace: "meeting-participation",
511
+ maxEntries: 1e4,
512
+ overflowPolicy: "reject-new"
513
+ });
494
514
  this.#sessions = new MeetingSessionRuntime({
515
+ participation: {
516
+ store: {
517
+ entries: async () => await getParticipationStore().entries(),
518
+ delete: async (key) => await getParticipationStore().delete(key),
519
+ lookup: async (key) => await getParticipationStore().lookup(key),
520
+ registerIfAbsent: async (key, attempt) => await getParticipationStore().registerIfAbsent(key, attempt),
521
+ register: async (key, attempt) => await getParticipationStore().register(key, attempt)
522
+ },
523
+ capabilities: (session) => isBrowserTransport(session.transport) && session.chrome?.launched && session.chrome.browserTab && session.chrome.health?.inCall === true && !session.chrome.health.manualAction ? adapter.browser.participation?.capabilities ?? [] : [],
524
+ validateAction: (action) => adapter.browser.participation?.validateAction(action),
525
+ execute: async (session, request, assertCurrent) => await participateInChromeMeet({
526
+ runtime: params.runtime,
527
+ config: params.config,
528
+ session,
529
+ request,
530
+ assertCurrent
531
+ })
532
+ },
495
533
  logger: params.logger,
496
534
  logScope: "[google-meet]",
497
535
  formatError: formatErrorMessage,
@@ -576,6 +614,12 @@ var GoogleMeetRuntime = class {
576
614
  async status(sessionId) {
577
615
  return await this.#sessions.status(sessionId);
578
616
  }
617
+ participationContext(sessionId) {
618
+ return this.#sessions.participationContext(sessionId);
619
+ }
620
+ participate(sessionId, request) {
621
+ return this.#sessions.participate(sessionId, request);
622
+ }
579
623
  async transcript(sessionId, options = {}) {
580
624
  return await this.#sessions.transcript(sessionId, options);
581
625
  }
@@ -713,7 +757,7 @@ var GoogleMeetRuntime = class {
713
757
  introSent: voiceCallResult?.introSent
714
758
  };
715
759
  if (voiceCallResult?.callId) context.attachRuntimeHandles(session, { stop: async () => {
716
- await endMeetVoiceCallGatewayCall({
760
+ await endMeetingVoiceCallGatewayCall({
717
761
  gateway: this.#voiceCallGateway,
718
762
  callId: voiceCallResult.callId
719
763
  });
@@ -805,7 +849,7 @@ var GoogleMeetRuntime = class {
805
849
  return;
806
850
  }
807
851
  try {
808
- const status = await getMeetVoiceCallGatewayCall({
852
+ const status = await getMeetingVoiceCallGatewayCall({
809
853
  gateway: this.#voiceCallGateway,
810
854
  callId
811
855
  });
@@ -819,13 +863,13 @@ var GoogleMeetRuntime = class {
819
863
  async #speakViaTransport(session, instructions) {
820
864
  if (session.transport !== "twilio" || !session.twilio?.voiceCallId) return;
821
865
  try {
822
- await speakMeetViaVoiceCallGateway({
866
+ await speakMeetingViaVoiceCallGateway({
823
867
  gateway: this.#voiceCallGateway,
824
868
  callId: session.twilio.voiceCallId,
825
869
  message: instructions || this.params.config.voiceCall.introMessage || this.params.config.realtime.introMessage || ""
826
870
  });
827
871
  } catch (error) {
828
- if (!isVoiceCallMissingError(error)) throw error;
872
+ if (!isMeetingVoiceCallMissingError(error)) throw error;
829
873
  this.#sessions.markSessionEnded(session, "Voice Call is no longer active.");
830
874
  return {
831
875
  handled: true,
@@ -1,12 +1,9 @@
1
1
  import { asNullableRecord, normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
2
2
  //#region extensions/google-meet/src/config-compat.ts
3
- function hasOwn(record, key) {
4
- return Object.hasOwn(record, key);
5
- }
6
3
  function hasLegacyGoogleRealtimeProvider(value) {
7
4
  const realtime = asNullableRecord(value);
8
5
  if (!realtime || normalizeOptionalLowercaseString(realtime.provider) !== "google") return false;
9
- return !hasOwn(realtime, "voiceProvider") || !hasOwn(realtime, "transcriptionProvider");
6
+ return !Object.hasOwn(realtime, "voiceProvider") || !Object.hasOwn(realtime, "transcriptionProvider");
10
7
  }
11
8
  const legacyConfigRules = [{
12
9
  path: [
@@ -36,8 +33,8 @@ function migrateGoogleMeetLegacyRealtimeProvider(config) {
36
33
  const nextRealtime = asNullableRecord(nextPluginConfig.realtime) ?? {};
37
34
  nextPluginConfig.realtime = nextRealtime;
38
35
  nextRealtime.provider = "openai";
39
- if (!hasOwn(nextRealtime, "transcriptionProvider")) nextRealtime.transcriptionProvider = "openai";
40
- if (!hasOwn(nextRealtime, "voiceProvider")) nextRealtime.voiceProvider = "google";
36
+ if (!Object.hasOwn(nextRealtime, "transcriptionProvider")) nextRealtime.transcriptionProvider = "openai";
37
+ if (!Object.hasOwn(nextRealtime, "voiceProvider")) nextRealtime.voiceProvider = "google";
41
38
  return {
42
39
  config: nextConfig,
43
40
  changes: ["Moved Google Meet legacy realtime.provider=\"google\" intent to realtime.voiceProvider=\"google\" and realtime.transcriptionProvider=\"openai\"."]
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { t as GOOGLE_MEET_CLI_DESCRIPTOR } from "./.setup/cli-output-mode-BwH_6tH8.mjs";
2
- import { n as GOOGLE_MEET_NODE_COMMAND } from "./.setup/google-meet-platform-constants-Bs5iAg3E.mjs";
3
- import { r as resolveGoogleMeetConfig } from "./.setup/config-C-6enWkx.mjs";
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 "./.setup/plugin-registration-B3LXKV4R.mjs";
2
+ import { n as GOOGLE_MEET_NODE_COMMAND } from "./.setup/google-meet-platform-constants-CnRfrYX7.mjs";
3
+ import { r as resolveGoogleMeetConfig } from "./.setup/config-BXGAMntj.mjs";
4
+ import { a as formatGoogleMeetGatewayError, c as loadGoogleMeetNodeHostModule, d as normalizeTransport, f as readGoogleMeetParticipationParams, h as shouldJoinCreatedMeet, i as createLazyGoogleMeetNodeInvokePolicy, l as loadGoogleMeetPluginHelpers, m as sendGoogleMeetGatewayError, n as callGoogleMeetGatewayFromTool, o as keepTrustedToolAgentId, p as resolveMeetingInput, r as createGoogleMeetRuntimeAccessor, s as loadGoogleMeetCliModule, t as assertGoogleMeetAgentToolActionSupported, u as normalizeMode } from "./.setup/plugin-registration-aCEuCerg.mjs";
5
5
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
6
- import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
+ import { asNonArrayRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
7
  import { jsonResult } from "openclaw/plugin-sdk/tool-results";
8
8
  import { optionalPositiveIntegerSchema } from "openclaw/plugin-sdk/channel-actions";
9
9
  import { Type } from "typebox";
@@ -18,6 +18,8 @@ const GoogleMeetToolSchema = Type.Object({
18
18
  "create",
19
19
  "status",
20
20
  "transcript",
21
+ "participation_context",
22
+ "participate",
21
23
  "setup_status",
22
24
  "resolve_space",
23
25
  "preflight",
@@ -69,6 +71,14 @@ const GoogleMeetToolSchema = Type.Object({
69
71
  pin: Type.Optional(Type.String({ description: "Meet phone PIN for Twilio; # is appended if omitted" })),
70
72
  dtmfSequence: Type.Optional(Type.String({ description: "Explicit DTMF sequence for Twilio" })),
71
73
  sessionId: Type.Optional(Type.String({ description: "Meet session ID" })),
74
+ requestId: Type.Optional(Type.String({ description: "For participate, a unique request ID. Reuse the same ID only to retry the same action." })),
75
+ sourceId: Type.Optional(Type.String({ description: "For participate, the current source ID from participation_context." })),
76
+ correctionOf: Type.Optional(Type.String({ description: "For participate, the rejected request ID whose correction is being submitted." })),
77
+ participationAction: Type.Optional(Type.Object({
78
+ type: Type.String({ description: "Action type advertised by participation_context capabilities." }),
79
+ text: Type.Optional(Type.String({ description: "Text for a supported participation action." })),
80
+ reaction: Type.Optional(Type.String({ description: "Native reaction advertised by the current capability." }))
81
+ })),
72
82
  sinceIndex: Type.Optional(Type.Integer({
73
83
  description: "For transcript, resume from the previous response's nextIndex.",
74
84
  minimum: 0
@@ -119,7 +129,7 @@ var google_meet_default = definePluginEntry({
119
129
  });
120
130
  };
121
131
  const resolveTrustedJoinParams = ({ params, client }) => {
122
- const trustedParams = keepTrustedToolAgentId(asParamRecord(params), client);
132
+ const trustedParams = keepTrustedToolAgentId(asNonArrayRecord(params), client);
123
133
  return {
124
134
  url: resolveMeetingInput(config, trustedParams.url),
125
135
  transport: normalizeTransport(trustedParams.transport),
@@ -183,7 +193,7 @@ var google_meet_default = definePluginEntry({
183
193
  options.respond(true, await runtime.join(resolveTrustedJoinParams(options)));
184
194
  });
185
195
  registerGatewayMethod("googlemeet.create", async ({ params, client, respond }) => {
186
- const raw = keepTrustedToolAgentId(asParamRecord(params), client);
196
+ const raw = keepTrustedToolAgentId(asNonArrayRecord(params), client);
187
197
  const helpers = await loadGoogleMeetPluginHelpers();
188
198
  respond(true, shouldJoinCreatedMeet(raw) ? await helpers.createAndJoinMeetFromParams({
189
199
  config,
@@ -212,6 +222,24 @@ var google_meet_default = definePluginEntry({
212
222
  }
213
223
  respond(true, await (await ensureRuntime()).transcript(sessionId, sinceIndex === void 0 ? {} : { sinceIndex }));
214
224
  });
225
+ registerGatewayMethod("googlemeet.participationContext", async ({ params, respond }) => {
226
+ const sessionId = normalizeOptionalString(params?.sessionId);
227
+ if (!sessionId) {
228
+ sendGoogleMeetGatewayError(respond, /* @__PURE__ */ new Error("sessionId required"), "INVALID_REQUEST");
229
+ return;
230
+ }
231
+ respond(true, (await ensureRuntime()).participationContext(sessionId));
232
+ });
233
+ registerGatewayMethod("googlemeet.participate", async ({ params, respond }) => {
234
+ let parsed;
235
+ try {
236
+ parsed = readGoogleMeetParticipationParams(asNonArrayRecord(params));
237
+ } catch (err) {
238
+ sendGoogleMeetGatewayError(respond, err, "INVALID_REQUEST");
239
+ return;
240
+ }
241
+ respond(true, await (await ensureRuntime()).participate(parsed.sessionId, parsed.request));
242
+ });
215
243
  registerGatewayMethod("googlemeet.recoverCurrentTab", async ({ params, respond }) => {
216
244
  respond(true, await (await ensureRuntime()).recoverCurrentTab({
217
245
  url: normalizeOptionalString(params?.url),
@@ -231,10 +259,10 @@ var google_meet_default = definePluginEntry({
231
259
  ["googlemeet.artifacts", "artifacts"],
232
260
  ["googlemeet.attendance", "attendance"]
233
261
  ]) registerGatewayMethod(method, async ({ params, respond }) => {
234
- respond(true, await queryActions[action](asParamRecord(params)));
262
+ respond(true, await queryActions[action](asNonArrayRecord(params)));
235
263
  });
236
264
  registerGatewayMethod("googlemeet.export", async ({ params, respond }) => {
237
- respond(true, await (await loadGoogleMeetPluginHelpers()).exportGoogleMeetBundleFromParams(config, asParamRecord(params)));
265
+ respond(true, await (await loadGoogleMeetPluginHelpers()).exportGoogleMeetBundleFromParams(config, asNonArrayRecord(params)));
238
266
  });
239
267
  registerGatewayMethod("googlemeet.leave", async ({ params, respond }) => {
240
268
  const sessionId = normalizeOptionalString(params?.sessionId);
@@ -245,7 +273,7 @@ var google_meet_default = definePluginEntry({
245
273
  respond(true, await (await ensureRuntime()).leave(sessionId));
246
274
  });
247
275
  registerGatewayMethod("googlemeet.endActiveConference", async ({ params, respond }) => {
248
- const raw = asParamRecord(params);
276
+ const raw = asNonArrayRecord(params);
249
277
  const helpers = await loadGoogleMeetPluginHelpers();
250
278
  const token = await helpers.resolveGoogleMeetTokenFromParams(config, raw);
251
279
  respond(true, await helpers.endGoogleMeetActiveConference({
@@ -266,7 +294,7 @@ var google_meet_default = definePluginEntry({
266
294
  options.respond(true, await runtime.testSpeech(resolveTrustedJoinParams(options)));
267
295
  });
268
296
  registerGatewayMethod("googlemeet.testListen", async ({ params, client, respond }) => {
269
- const trustedParams = keepTrustedToolAgentId(asParamRecord(params), client);
297
+ const trustedParams = keepTrustedToolAgentId(asNonArrayRecord(params), client);
270
298
  const runtime = await ensureRuntime();
271
299
  const { readPositiveIntegerParam } = await import("openclaw/plugin-sdk/param-readers");
272
300
  respond(true, await runtime.testListen({
@@ -280,10 +308,10 @@ var google_meet_default = definePluginEntry({
280
308
  api.registerTool((toolContext) => ({
281
309
  name: "google_meet",
282
310
  label: "Google Meet",
283
- description: "Join and track Google Meet sessions through Chrome or Twilio. Call setup_status before join/create/test_listen/test_speech; if it reports a Chrome node offline, local audio missing, or missing Twilio dial plan, surface that blocker instead of retrying or switching transports. Twilio cannot dial a Meet URL directly: provide dialInNumber plus optional pin/dtmfSequence, or configure twilio.defaultDialInNumber. Offline nodes are diagnostics only, not usable candidates. Local Chrome talk-back needs macOS with BlackHole 2ch or Linux with PipeWire-Pulse; otherwise use mode=transcribe, transport=twilio, or a supported chrome-node. If a Meet tab is already open after a timeout, call recover_current_tab before retrying join to report login, permission, or admission blockers without opening another tab.",
311
+ description: "Join and track Google Meet sessions through Chrome or Twilio. Call setup_status before join/create/test_listen/test_speech; if it reports a Chrome node offline, local audio missing, or missing Twilio dial plan, surface that blocker instead of retrying or switching transports. Twilio cannot dial a Meet URL directly: provide dialInNumber plus optional pin/dtmfSequence, or configure twilio.defaultDialInNumber. Offline nodes are diagnostics only, not usable candidates. Local Chrome talk-back needs macOS with BlackHole 2ch or Linux with PipeWire-Pulse; otherwise use mode=transcribe, transport=twilio, or a supported chrome-node. If a Meet tab is already open after a timeout, call recover_current_tab before retrying join to report login, permission, or admission blockers without opening another tab. For meeting participation, call participation_context for current source identities and supported capabilities, then participate with a unique requestId and participationAction. An empty capability list means native participation is unavailable. Reuse a requestId only for an identical retry; use correctionOf only when a rejected result permits one correction.",
284
312
  parameters: GoogleMeetToolSchema,
285
313
  async execute(_toolCallId, params) {
286
- const raw = asParamRecord(params);
314
+ const raw = asNonArrayRecord(params);
287
315
  const requesterSessionKey = normalizeOptionalString(toolContext.sessionKey);
288
316
  try {
289
317
  const { normalizeAgentId, parseAgentSessionKey } = await import("openclaw/plugin-sdk/routing");
@@ -342,6 +370,14 @@ var google_meet_default = definePluginEntry({
342
370
  const helpers = await loadGoogleMeetPluginHelpers();
343
371
  return jsonResult(await helpers.exportGoogleMeetBundleFromParams(config, raw));
344
372
  }
373
+ case "participate":
374
+ readGoogleMeetParticipationParams(raw);
375
+ return jsonResult(await callGoogleMeetGatewayFromTool({
376
+ config,
377
+ action: raw.action,
378
+ raw
379
+ }));
380
+ case "participation_context":
345
381
  case "leave":
346
382
  case "speak":
347
383
  if (!normalizeOptionalString(raw.sessionId)) throw new Error("sessionId required");
@@ -16,9 +16,8 @@ function Separator() {
16
16
  function ImportSection(build) {
17
17
  const context = build.UseUnevaluated() ? [`import { CheckContext } from "typebox/schema"`] : [];
18
18
  const hashing = `import { Hashing } from "typebox/system"`;
19
- const format = `import { Format } from "typebox/format"`;
20
19
  const guard = `import { Guard } from "typebox/guard"`;
21
- return [...context, hashing, format, guard];
20
+ return [...context, hashing, guard];
22
21
  }
23
22
  // ------------------------------------------------------------------
24
23
  // ExternalSection
@@ -1,4 +1,5 @@
1
1
  // deno-fmt-ignore-file
2
+ import { EnableParseErrors, DisableParseErrors } from '../system/settings/internal.mjs';
2
3
  import { Settings } from '../system/settings/index.mjs';
3
4
  import { Errors, Clean, Convert, Create, Default, Decode, Encode, HasCodec, Parser, ParseError } from '../value/index.mjs';
4
5
  import { Build } from '../schema/index.mjs';
@@ -51,7 +52,10 @@ export class Validator {
51
52
  return value;
52
53
  if (Settings.Get().correctiveParse)
53
54
  return Parser(this.Context(), this.Type(), value);
54
- throw new ParseError(value, this.Errors(value));
55
+ EnableParseErrors();
56
+ const errors = this.Errors(value);
57
+ DisableParseErrors();
58
+ throw new ParseError(value, errors);
55
59
  }
56
60
  /** Returns an array of validation errors for the given value. */
57
61
  Errors(value) {
@@ -1,9 +1,10 @@
1
1
  // deno-lint-ignore-file no-control-regex
2
- const IpvFutureMatchMaxLength = 2048;
3
- const IpvFutureMatch = /\[[vV][0-9a-fA-F]+\.[^\]]+\]/; // Guarded By IpvFutureMatchMaxLength
4
- const InvalidIriChars = /[\x00-\x20<>\^`{|}\\]/;
5
- const InvalidPercentEncoding = /%(?![0-9a-fA-F]{2})/;
6
2
  // ------------------------------------------------------------------
3
+ //
4
+ // Removed by the following PR
5
+ //
6
+ // https://github.com/json-schema-org/JSON-Schema-Test-Suite/pull/1176
7
+ //
7
8
  // NarrowIpvFuture
8
9
  //
9
10
  // Substitutes an IPvFuture address with a standard IPv6 loopback
@@ -13,12 +14,18 @@ const InvalidPercentEncoding = /%(?![0-9a-fA-F]{2})/;
13
14
  // be expensive on large strings, this operation is strictly
14
15
  // limited to inputs under a defined length threshold.
15
16
  //
16
- // (review-optimization)
17
+ // ------------------------------------------------------------------
18
+ //
19
+ // const IpvFutureMatchMaxLength = 2048
20
+ // const IpvFutureMatch = /\[[vV][0-9a-fA-F]+\.[^\]]+\]/ // Guarded By IpvFutureMatchMaxLength
21
+ //
22
+ // function NarrowIpvFuture(value: string): string {
23
+ // return value.length < IpvFutureMatchMaxLength ? value.replace(IpvFutureMatch, '[::1]') : value
24
+ // }
17
25
  //
18
26
  // ------------------------------------------------------------------
19
- function NarrowIpvFuture(value) {
20
- return value.length < IpvFutureMatchMaxLength ? value.replace(IpvFutureMatch, '[::1]') : value;
21
- }
27
+ const InvalidIriChars = /[\x00-\x20<>\^`{|}\\]/;
28
+ const InvalidPercentEncoding = /%(?![0-9a-fA-F]{2})/;
22
29
  /**
23
30
  * Returns true if the value is a valid Internationalized Resource Identifier.
24
31
  * @specification https://datatracker.ietf.org/doc/html/rfc3987
@@ -31,5 +38,5 @@ export function IsIri(value) {
31
38
  if (InvalidPercentEncoding.test(value))
32
39
  return false;
33
40
  // 3. Delegate to the native URL parser, patching the IPvFuture edge case beforehand.
34
- return URL.canParse(NarrowIpvFuture(value));
41
+ return URL.canParse(value);
35
42
  }
@@ -97,10 +97,10 @@ export function IsGreaterEqualThan(left, right) {
97
97
  // String
98
98
  // --------------------------------------------------------------------------
99
99
  export function IsMinLength(value, length) {
100
- return `Guard.IsMinLength(${value}, ${length})`;
100
+ return `(${value}.length >= ${(+length) << 1} || (${value}.length >= ${length} && Guard.CodePointCount(${value}) >= ${length}))`;
101
101
  }
102
102
  export function IsMaxLength(value, length) {
103
- return `Guard.IsMaxLength(${value}, ${length})`;
103
+ return `(${value}.length <= ${length} || (${value}.length <= ${(+length) << 1} && Guard.CodePointCount(${value}) <= ${length}))`;
104
104
  }
105
105
  // --------------------------------------------------------------------------
106
106
  // Array
@@ -33,12 +33,14 @@ export declare function IsMultipleOf(dividend: bigint | number, divisor: bigint
33
33
  /** Returns true if the value appears to be an instance of a class. */
34
34
  export declare function IsClassInstance(value: unknown): boolean;
35
35
  export declare function IsValueLike(value: unknown): value is bigint | boolean | null | number | string | undefined;
36
- /** Returns the number of grapheme clusters in the string */
36
+ /** Returns the total number of visual grapheme clusters in the string. */
37
37
  export declare function GraphemeCount(value: string): number;
38
- /** Returns true if the string has at most the given number of graphemes */
39
- export declare function IsMaxLength(value: string, length: number): boolean;
40
- /** Returns true if the string has at least the given number of graphemes */
41
- export declare function IsMinLength(value: string, length: number): boolean;
38
+ /** Returns the total number of Unicode code points in the string. */
39
+ export declare function CodePointCount(value: string): number;
40
+ /** Returns true if the string length in Unicode code points does not exceed maxLength */
41
+ export declare function IsMaxLength(value: string, maxLength: number): boolean;
42
+ /** Returns true if the string length in Unicode code points is at least minLength */
43
+ export declare function IsMinLength(value: string, minLength: number): boolean;
42
44
  /** Returns true if every element from offset satisfies the callback, short-circuiting on the first failure */
43
45
  export declare function Every<T>(value: T[], offset: number, callback: (value: T, index: number) => boolean): boolean;
44
46
  /** Returns true if every element from offset satisfies the callback, using exhaustive enumeration */
@@ -1,5 +1,6 @@
1
1
  // deno-fmt-ignore-file
2
- import * as String from './string.mjs';
2
+ import * as UnicodeSegmentGuard from './unicode/unicode_segment.mjs';
3
+ import * as UnicodeGuard from './unicode/unicode.mjs';
3
4
  // --------------------------------------------------------------------------
4
5
  // Guards
5
6
  // --------------------------------------------------------------------------
@@ -123,17 +124,21 @@ export function IsValueLike(value) {
123
124
  // --------------------------------------------------------------------------
124
125
  // String
125
126
  // --------------------------------------------------------------------------
126
- /** Returns the number of grapheme clusters in the string */
127
+ /** Returns the total number of visual grapheme clusters in the string. */
127
128
  export function GraphemeCount(value) {
128
- return String.GraphemeCount(value);
129
+ return UnicodeSegmentGuard.GraphemeCount(value);
129
130
  }
130
- /** Returns true if the string has at most the given number of graphemes */
131
- export function IsMaxLength(value, length) {
132
- return String.IsMaxLength(value, length);
131
+ /** Returns the total number of Unicode code points in the string. */
132
+ export function CodePointCount(value) {
133
+ return UnicodeGuard.CodePointCount(value);
133
134
  }
134
- /** Returns true if the string has at least the given number of graphemes */
135
- export function IsMinLength(value, length) {
136
- return String.IsMinLength(value, length);
135
+ /** Returns true if the string length in Unicode code points does not exceed maxLength */
136
+ export function IsMaxLength(value, maxLength) {
137
+ return UnicodeGuard.IsMaxLength(value, maxLength);
138
+ }
139
+ /** Returns true if the string length in Unicode code points is at least minLength */
140
+ export function IsMinLength(value, minLength) {
141
+ return UnicodeGuard.IsMinLength(value, minLength);
137
142
  }
138
143
  // --------------------------------------------------------------------------
139
144
  // Array
@@ -1,6 +1,12 @@
1
+ // ------------------------------------------------------------------
2
+ // Guards
3
+ // ------------------------------------------------------------------
1
4
  export * as EmitGuard from './emit.mjs';
2
5
  export * as GlobalsGuard from './globals.mjs';
3
6
  export * as NativeGuard from './native.mjs';
7
+ // ------------------------------------------------------------------
8
+ // Default
9
+ // ------------------------------------------------------------------
4
10
  import * as Guard from './guard.mjs';
5
11
  export * as Guard from './guard.mjs';
6
12
  export default Guard;
@@ -0,0 +1,6 @@
1
+ /** Returns the total number of Unicode code points in the string */
2
+ export declare function CodePointCount(value: string): number;
3
+ /** Returns true if the string length in Unicode code points is less than or equal to maxLength */
4
+ export declare function IsMaxLength(value: string, maxLength: number): boolean;
5
+ /** Returns true if the string length in Unicode code points is greater than or equal to minLength */
6
+ export declare function IsMinLength(value: string, minLength: number): boolean;
@@ -0,0 +1,35 @@
1
+ // ------------------------------------------------------------------
2
+ // CodePointCount (10-bit Shift Branchless)
3
+ //
4
+ // Counts code points by enumerating UTF-16 sequences and incrementing
5
+ // when not within a high/low pairing. Because surrogate blocks are
6
+ // 1024 (2^10) wide and aligned, by shifting right by (0xA), we can
7
+ // collapse each unit to a constant per block (high: 0x36, low: 0x37)
8
+ // and shift again into a packed (0x3637) for comparison. Fetch calls
9
+ // to charCodeAt(...) are kept to one call per iteration.
10
+ //
11
+ // ------------------------------------------------------------------
12
+ /** Returns the total number of Unicode code points in the string */
13
+ export function CodePointCount(value) {
14
+ let result = 0, index = 0, prev = 0;
15
+ while (index < value.length) {
16
+ const next = value.charCodeAt(index++) >> 0xA; // shift (10-bits into high/low)
17
+ result += +(((prev << 8) | next) !== 0x3637); // packed (or +!(prev === 0x36 && next === 0x37))
18
+ prev = next;
19
+ }
20
+ return result;
21
+ }
22
+ // ------------------------------------------------------------------
23
+ // IsMaxLength
24
+ // ------------------------------------------------------------------
25
+ /** Returns true if the string length in Unicode code points is less than or equal to maxLength */
26
+ export function IsMaxLength(value, maxLength) {
27
+ return value.length <= maxLength || (value.length <= (maxLength << 1) && CodePointCount(value) <= maxLength);
28
+ }
29
+ // ------------------------------------------------------------------
30
+ // IsMinLength
31
+ // ------------------------------------------------------------------
32
+ /** Returns true if the string length in Unicode code points is greater than or equal to minLength */
33
+ export function IsMinLength(value, minLength) {
34
+ return value.length >= (minLength << 1) || (value.length >= minLength && CodePointCount(value) >= minLength);
35
+ }