@openclaw/google-meet 2026.10.10 → 2026.11.5-beta.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.
Files changed (99) hide show
  1. package/assets/activity.svg +1 -1
  2. package/dist/.setup/{chrome-create-DIcW4QCh.mjs → chrome-create-BlDlV2YP.mjs} +11 -30
  3. package/dist/.setup/{cli-9linTFHb.mjs → cli-C-MrY7IZ.mjs} +275 -309
  4. package/dist/.setup/{cli-export-CaDYoSP8.mjs → cli-export-6eiywS3T.mjs} +16 -35
  5. package/dist/.setup/{cli-output-mode-BJSm88N9.mjs → cli-output-mode-DztqqVeZ.mjs} +5 -6
  6. package/dist/.setup/config-CMTw0Anh.mjs +110 -0
  7. package/dist/.setup/{create-D3fHR8uX.mjs → create-DMk4zbMq.mjs} +23 -9
  8. package/dist/.setup/{google-meet-platform-adapter-D7poqL1J.mjs → google-meet-platform-adapter-DgchqNLV.mjs} +52 -18
  9. package/dist/.setup/{node-host-B196lvNZ.mjs → node-host-BIZD9InM.mjs} +2 -2
  10. package/dist/.setup/{node-invoke-policy-BzRAe25r.mjs → node-invoke-policy-bg7p_BWB.mjs} +1 -1
  11. package/dist/.setup/oauth-DZkuGMs1.mjs +1 -0
  12. package/dist/.setup/{plugin-helpers-Buhixxsx.mjs → plugin-helpers-ChCBuyAl.mjs} +363 -69
  13. package/dist/.setup/{plugin-registration-B_nOxAym.mjs → plugin-registration-CAW7_zO_.mjs} +8 -8
  14. package/dist/.setup/{runtime-D-dwEsSW.mjs → runtime-Cyc6bv1i.mjs} +37 -38
  15. package/dist/.source-module-urls/c06239f68b6f4959b5d3db7e0cee004911d8eb43092f4135c729b507e37f6333.json +1 -1
  16. package/dist/cli-metadata.js +1 -1
  17. package/dist/doctor-contract-api.js +25 -21
  18. package/dist/index.js +14 -13
  19. package/node_modules/typebox/build/format/duration.d.mts +2 -2
  20. package/node_modules/typebox/build/format/duration.mjs +2 -2
  21. package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
  22. package/node_modules/typebox/build/format/idn_email.mjs +1 -0
  23. package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
  24. package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
  25. package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
  26. package/node_modules/typebox/build/format/ipv4.mjs +2 -2
  27. package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
  28. package/node_modules/typebox/build/format/ipv6.mjs +1 -1
  29. package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
  30. package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
  31. package/node_modules/typebox/build/schema/build.mjs +1 -0
  32. package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
  33. package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
  34. package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
  35. package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
  36. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
  37. package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
  38. package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
  39. package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
  40. package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
  41. package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
  42. package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
  43. package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
  44. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
  45. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
  46. package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
  47. package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
  48. package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
  49. package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
  50. package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
  51. package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
  52. package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
  53. package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
  54. package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
  55. package/node_modules/typebox/build/system/memory/create.mjs +18 -13
  56. package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
  57. package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
  58. package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
  59. package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
  60. package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
  61. package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
  62. package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
  63. package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
  64. package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
  65. package/node_modules/typebox/build/system/memory/update.mjs +43 -16
  66. package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
  67. package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
  68. package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
  69. package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
  70. package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
  71. package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
  72. package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
  73. package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
  74. package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
  75. package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
  76. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
  77. package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
  78. package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
  79. package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
  80. package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
  81. package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
  82. package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
  83. package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
  84. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
  85. package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
  86. package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
  87. package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
  88. package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
  89. package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
  90. package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
  91. package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
  92. package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
  93. package/node_modules/typebox/package.json +1 -1
  94. package/node_modules/typebox/readme.md +1 -1
  95. package/package.json +5 -5
  96. package/dist/.setup/config-Cu3zsl_3.mjs +0 -239
  97. package/dist/.setup/oauth-DGv28ZgA.mjs +0 -158
  98. package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
  99. package/node_modules/typebox/build/system/memory/freeze.mjs +0 -6
@@ -1,4 +1,5 @@
1
- import { g as __exportAll } from "./plugin-helpers-Buhixxsx.mjs";
1
+ import "./plugin-helpers-ChCBuyAl.mjs";
2
+ import { readNonBlankString } from "openclaw/plugin-sdk/string-coerce-runtime";
2
3
  import { clampTimerTimeoutMs, parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
3
4
  import fsp, { stat } from "node:fs/promises";
4
5
  import path from "node:path";
@@ -122,10 +123,7 @@ async function callGoogleMeetGateway(params) {
122
123
  }, params.payload, { progress: false })
123
124
  };
124
125
  } catch (err) {
125
- if (isGatewayUnavailableForLocalFallback(err, params.method)) return {
126
- ok: false,
127
- error: err
128
- };
126
+ if (isGatewayUnavailableForLocalFallback(err, params.method)) return { ok: false };
129
127
  throw err;
130
128
  }
131
129
  }
@@ -245,30 +243,6 @@ function writeLeaveResult(sessionId, result) {
245
243
  writeStdoutLine("left %s", sessionId);
246
244
  }
247
245
  // extensions/google-meet/src/cli-export.ts
248
- var cli_export_exports = /* @__PURE__ */ __exportAll({
249
- buildGoogleMeetExportManifest: () => buildGoogleMeetExportManifest,
250
- exportGoogleMeetBundle: () => exportGoogleMeetBundle,
251
- googleMeetExportFileNames: () => googleMeetExportFileNames,
252
- renderArtifacts: () => renderArtifacts,
253
- renderAttendance: () => renderAttendance,
254
- renderAttendanceCsv: () => renderAttendanceCsv,
255
- writeCalendarEventsSummary: () => writeCalendarEventsSummary,
256
- writeLatestConferenceRecordSummary: () => writeLatestConferenceRecordSummary,
257
- writeMeetExportBundle: () => writeMeetExportBundle
258
- });
259
- function appendArtifactSummary(lines, entry) {
260
- if (entry.smartNotesError) lines.push(`smart notes warning: ${entry.smartNotesError}`);
261
- for (const recording of entry.recordings) lines.push(`- recording: ${recording.name}`);
262
- for (const transcript of entry.transcripts) {
263
- lines.push(`- transcript: ${transcript.name}`);
264
- if (transcript.documentTextError) lines.push(`- transcript document body warning: ${transcript.documentTextError}`);
265
- }
266
- for (const transcriptEntries of entry.transcriptEntries) if (transcriptEntries.entriesError) lines.push(`- transcript entries warning: ${transcriptEntries.transcript}: ${transcriptEntries.entriesError}`);
267
- for (const smartNote of entry.smartNotes) {
268
- lines.push(`- smart note: ${smartNote.name}`);
269
- if (smartNote.documentTextError) lines.push(`- smart note document body warning: ${smartNote.documentTextError}`);
270
- }
271
- }
272
246
  function createReport(title, result, format) {
273
247
  const markdown = format === "markdown";
274
248
  const lines = markdown ? [`# Google Meet ${title}`] : [];
@@ -353,7 +327,17 @@ function renderArtifacts(result, format) {
353
327
  field("Transcript entries", entry.transcriptEntries.reduce((count, transcript) => count + transcript.entries.length, 0));
354
328
  field("Smart notes", entry.smartNotes.length);
355
329
  if (!markdown) {
356
- appendArtifactSummary(lines, entry);
330
+ if (entry.smartNotesError) lines.push(`smart notes warning: ${entry.smartNotesError}`);
331
+ for (const recording of entry.recordings) lines.push(`- recording: ${recording.name}`);
332
+ for (const transcript of entry.transcripts) {
333
+ lines.push(`- transcript: ${transcript.name}`);
334
+ if (transcript.documentTextError) lines.push(`- transcript document body warning: ${transcript.documentTextError}`);
335
+ }
336
+ for (const transcriptEntries of entry.transcriptEntries) if (transcriptEntries.entriesError) lines.push(`- transcript entries warning: ${transcriptEntries.transcript}: ${transcriptEntries.entriesError}`);
337
+ for (const smartNote of entry.smartNotes) {
338
+ lines.push(`- smart note: ${smartNote.name}`);
339
+ if (smartNote.documentTextError) lines.push(`- smart note document body warning: ${smartNote.documentTextError}`);
340
+ }
357
341
  continue;
358
342
  }
359
343
  const warnings = collectGoogleMeetArtifactWarnings({
@@ -537,9 +521,6 @@ function googleMeetExportFileNames() {
537
521
  "manifest.json"
538
522
  ];
539
523
  }
540
- function defaultExportDirectory() {
541
- return `google-meet-export-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
542
- }
543
524
  async function publishMeetExportFile(outputPath, content) {
544
525
  const absolutePath = path.resolve(outputPath);
545
526
  await writeExternalFileWithinRoot({
@@ -551,7 +532,7 @@ async function publishMeetExportFile(outputPath, content) {
551
532
  });
552
533
  }
553
534
  async function writeMeetExportBundle(params) {
554
- const outputDir = params.outputDir?.trim() || defaultExportDirectory();
535
+ const outputDir = readNonBlankString(params.outputDir) ?? `google-meet-export-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
555
536
  await fsp.mkdir(outputDir, { recursive: true });
556
537
  let zipOutputDir = outputDir;
557
538
  if (params.zip) {
@@ -628,4 +609,4 @@ async function exportGoogleMeetBundle(params) {
628
609
  ...metadata
629
610
  };
630
611
  }
631
- export { writeStdoutJson as C, writeSetupStatus as S, resolveGoogleMeetOAuthCallbackTimeoutMs as _, renderAttendanceCsv as a, writeLeaveResult as b, callGoogleMeetGateway as c, parseGoogleMeetTransport as d, parseOptionalNumber as f, resolveCliJoinRequest as g, promptInput as h, renderAttendance as i, parseGoogleMeetBrowserTransport as l, parsePositiveNumber as m, exportGoogleMeetBundle as n, writeCalendarEventsSummary as o, parsePositiveIntegerOption as p, renderArtifacts as r, writeLatestConferenceRecordSummary as s, cli_export_exports as t, parseGoogleMeetMode as u, writeCliOutput as v, writeStdoutLine as w, writeRecoverCurrentTabResult as x, writeDoctorStatus as y };
612
+ export { writeStdoutLine as _, parseOptionalNumber as a, buildGoogleMeetExportManifest, promptInput as c, writeCliOutput as d, exportGoogleMeetBundle, writeDoctorStatus as f, writeStdoutJson as g, googleMeetExportFileNames, writeSetupStatus as h, parseGoogleMeetTransport as i, resolveCliJoinRequest as l, writeRecoverCurrentTabResult as m, parseGoogleMeetBrowserTransport as n, parsePositiveIntegerOption as o, writeLeaveResult as p, parseGoogleMeetMode as r, renderArtifacts, renderAttendance, renderAttendanceCsv, parsePositiveNumber as s, callGoogleMeetGateway as t, resolveGoogleMeetOAuthCallbackTimeoutMs as u, writeCalendarEventsSummary, writeLatestConferenceRecordSummary, writeMeetExportBundle };
@@ -13,15 +13,14 @@ function hasOption(argv, flag) {
13
13
  }
14
14
  return false;
15
15
  }
16
- /** Runtime probe commands emit JSON without requiring the shared `--json` option. */
17
- function isGoogleMeetMachineOutput(params) {
18
- const [, command] = getRootOptionAwareCommandPath(params.argv, 2);
19
- return DEFAULT_JSON_COMMANDS.has(command ?? "") || command === "export" && hasOption(params.argv, "--dry-run");
20
- }
21
16
  const GOOGLE_MEET_CLI_DESCRIPTOR = {
22
17
  name: "googlemeet",
23
18
  description: "Join and manage Google Meet calls",
24
19
  hasSubcommands: true,
25
- machineOutput: isGoogleMeetMachineOutput
20
+ /** Runtime probe commands emit JSON without requiring the shared `--json` option. */
21
+ machineOutput: (params) => {
22
+ const [, command] = getRootOptionAwareCommandPath(params.argv, 2);
23
+ return DEFAULT_JSON_COMMANDS.has(command ?? "") || command === "export" && hasOption(params.argv, "--dry-run");
24
+ }
26
25
  };
27
26
  export { GOOGLE_MEET_CLI_DESCRIPTOR as t };
@@ -0,0 +1,110 @@
1
+ import { asBoolean, asRecord, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeOptionalTrimmedStringList, parseBooleanValue } from "openclaw/plugin-sdk/string-coerce-runtime";
2
+ import { buildMeetingConfigAudioCommands, resolveMeetingChromeConfig, resolveMeetingRealtimeConfig } from "openclaw/plugin-sdk/meeting-config";
3
+ import { addTimerTimeoutGraceMs, resolvePositiveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
4
+ import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME } from "openclaw/plugin-sdk/realtime-voice";
5
+ // extensions/google-meet/src/config.ts
6
+ function resolveGoogleMeetGatewayOperationTimeoutMs(config) {
7
+ return Math.max(6e4, addTimerTimeoutGraceMs(config.chrome.joinTimeoutMs, 3e4) ?? 1, addTimerTimeoutGraceMs(config.voiceCall.requestTimeoutMs, 1e4) ?? 1);
8
+ }
9
+ const DEFAULT_GOOGLE_MEET_AUDIO_BUFFER_BYTES = 4096;
10
+ const PLAIN_DECIMAL_NUMBER_RE = /^\d+(?:\.\d+)?$/;
11
+ const DEFAULT_GOOGLE_MEET_AUDIO_COMMANDS = buildMeetingConfigAudioCommands("blackhole-2ch", "pcm16-24khz", DEFAULT_GOOGLE_MEET_AUDIO_BUFFER_BYTES);
12
+ const DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND = DEFAULT_GOOGLE_MEET_AUDIO_COMMANDS.inputCommand;
13
+ const DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND = DEFAULT_GOOGLE_MEET_AUDIO_COMMANDS.outputCommand;
14
+ 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.`;
15
+ function resolveOptionalNumber(value) {
16
+ if (typeof value === "number" && Number.isFinite(value)) return value;
17
+ if (typeof value === "string" && value.trim()) {
18
+ const trimmed = value.trim();
19
+ const parsed = PLAIN_DECIMAL_NUMBER_RE.test(trimmed) ? Number(trimmed) : NaN;
20
+ return Number.isFinite(parsed) ? parsed : void 0;
21
+ }
22
+ }
23
+ function readGoogleMeetEnv(env, name) {
24
+ return normalizeOptionalString(env[name]) ?? normalizeOptionalString(env[name.slice(9)]);
25
+ }
26
+ function resolveTransport(value, fallback) {
27
+ const normalized = normalizeOptionalLowercaseString(value);
28
+ return normalized === "chrome" || normalized === "chrome-node" || normalized === "twilio" ? normalized : fallback;
29
+ }
30
+ function resolveMode(value, fallback) {
31
+ const normalized = normalizeOptionalLowercaseString(value);
32
+ if (normalized === "realtime") return "agent";
33
+ return normalized === "agent" || normalized === "bidi" || normalized === "transcribe" ? normalized : fallback;
34
+ }
35
+ function resolveChromeAudioFormat(value) {
36
+ switch (normalizeOptionalString(value)?.toLowerCase().replaceAll("_", "-")) {
37
+ case "pcm16-24khz":
38
+ case "pcm16-24k":
39
+ case "pcm24":
40
+ case "pcm": return "pcm16-24khz";
41
+ case "g711-ulaw-8khz":
42
+ case "g711-ulaw-8k":
43
+ case "g711-ulaw":
44
+ case "mulaw":
45
+ case "mu-law": return "g711-ulaw-8khz";
46
+ default: return;
47
+ }
48
+ }
49
+ function resolveGoogleMeetConfig(input) {
50
+ const env = process.env;
51
+ const raw = asRecord(input);
52
+ const defaults = asRecord(raw.defaults);
53
+ const preview = asRecord(raw.preview);
54
+ const chrome = asRecord(raw.chrome);
55
+ const chromeNode = asRecord(raw.chromeNode);
56
+ const twilio = asRecord(raw.twilio);
57
+ const voiceCall = asRecord(raw.voiceCall);
58
+ const realtime = asRecord(raw.realtime);
59
+ const realtimeProvider = normalizeOptionalString(realtime.provider);
60
+ const oauth = asRecord(raw.oauth);
61
+ const auth = asRecord(raw.auth);
62
+ return {
63
+ enabled: asBoolean(raw.enabled) ?? true,
64
+ defaults: { meeting: normalizeOptionalString(defaults.meeting) ?? readGoogleMeetEnv(env, "OPENCLAW_GOOGLE_MEET_DEFAULT_MEETING") },
65
+ preview: { enrollmentAcknowledged: asBoolean(preview.enrollmentAcknowledged) ?? parseBooleanValue(readGoogleMeetEnv(env, "OPENCLAW_GOOGLE_MEET_PREVIEW_ACK")) ?? false },
66
+ defaultTransport: resolveTransport(raw.defaultTransport, "chrome"),
67
+ defaultMode: resolveMode(raw.defaultMode, "agent"),
68
+ chrome: {
69
+ ...resolveMeetingChromeConfig(chrome, {
70
+ resolveAudioFormat: (hasCustomCommands) => resolveChromeAudioFormat(chrome.audioFormat) ?? (hasCustomCommands ? "g711-ulaw-8khz" : "pcm16-24khz"),
71
+ waitForInCallMs: 2e4
72
+ }),
73
+ audioBridgeCommand: normalizeOptionalTrimmedStringList(chrome.audioBridgeCommand),
74
+ audioBridgeHealthCommand: normalizeOptionalTrimmedStringList(chrome.audioBridgeHealthCommand)
75
+ },
76
+ chromeNode: { node: normalizeOptionalString(chromeNode.node) },
77
+ twilio: {
78
+ defaultDialInNumber: normalizeOptionalString(twilio.defaultDialInNumber),
79
+ defaultPin: normalizeOptionalString(twilio.defaultPin),
80
+ defaultDtmfSequence: normalizeOptionalString(twilio.defaultDtmfSequence)
81
+ },
82
+ voiceCall: {
83
+ enabled: asBoolean(voiceCall.enabled) ?? true,
84
+ gatewayUrl: normalizeOptionalString(voiceCall.gatewayUrl),
85
+ token: normalizeOptionalString(voiceCall.token),
86
+ requestTimeoutMs: resolvePositiveTimerTimeoutMs(voiceCall.requestTimeoutMs, 3e4),
87
+ dtmfDelayMs: resolvePositiveTimerTimeoutMs(voiceCall.dtmfDelayMs, 12e3),
88
+ postDtmfSpeechDelayMs: resolvePositiveTimerTimeoutMs(voiceCall.postDtmfSpeechDelayMs, 5e3),
89
+ introMessage: normalizeOptionalString(voiceCall.introMessage)
90
+ },
91
+ realtime: resolveMeetingRealtimeConfig(realtime, {
92
+ instructions: DEFAULT_GOOGLE_MEET_REALTIME_INSTRUCTIONS,
93
+ transcriptionProvider: realtimeProvider && realtimeProvider !== "google" ? realtimeProvider : "openai"
94
+ }),
95
+ oauth: {
96
+ clientId: normalizeOptionalString(oauth.clientId) ?? normalizeOptionalString(auth.clientId) ?? readGoogleMeetEnv(env, "OPENCLAW_GOOGLE_MEET_CLIENT_ID"),
97
+ clientSecret: normalizeOptionalString(oauth.clientSecret) ?? normalizeOptionalString(auth.clientSecret) ?? readGoogleMeetEnv(env, "OPENCLAW_GOOGLE_MEET_CLIENT_SECRET"),
98
+ refreshToken: normalizeOptionalString(oauth.refreshToken) ?? readGoogleMeetEnv(env, "OPENCLAW_GOOGLE_MEET_REFRESH_TOKEN"),
99
+ accessToken: normalizeOptionalString(oauth.accessToken) ?? readGoogleMeetEnv(env, "OPENCLAW_GOOGLE_MEET_ACCESS_TOKEN"),
100
+ expiresAt: resolveOptionalNumber(oauth.expiresAt) ?? resolveOptionalNumber(readGoogleMeetEnv(env, "OPENCLAW_GOOGLE_MEET_ACCESS_TOKEN_EXPIRES_AT"))
101
+ },
102
+ auth: {
103
+ provider: "google-oauth",
104
+ clientId: normalizeOptionalString(auth.clientId),
105
+ clientSecret: normalizeOptionalString(auth.clientSecret),
106
+ tokenPath: normalizeOptionalString(auth.tokenPath)
107
+ }
108
+ };
109
+ }
110
+ export { resolveGoogleMeetGatewayOperationTimeoutMs as i, DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND as n, resolveGoogleMeetConfig as r, DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND as t };
@@ -1,7 +1,18 @@
1
- import { g as __exportAll, o as resolveGoogleMeetTokenFromParams, u as createGoogleMeetSpace } from "./plugin-helpers-Buhixxsx.mjs";
2
- import { d as normalizeMode, f as normalizeTransport } from "./plugin-registration-B_nOxAym.mjs";
3
- import { t as createMeetWithBrowserProxyOnNode } from "./chrome-create-DIcW4QCh.mjs";
1
+ import { d as normalizeMode, f as normalizeTransport } from "./plugin-registration-CAW7_zO_.mjs";
2
+ import { resolveGoogleMeetTokenFromParams, s as createGoogleMeetSpace } from "./plugin-helpers-ChCBuyAl.mjs";
3
+ import { t as createMeetWithBrowserProxyOnNode } from "./chrome-create-BlDlV2YP.mjs";
4
4
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
+ // \0rolldown/runtime.js
6
+ var __defProp = Object.defineProperty;
7
+ var __exportAll = (all, no_symbols) => {
8
+ let target = {};
9
+ for (var name in all) __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true
12
+ });
13
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
14
+ return target;
15
+ };
5
16
  // extensions/google-meet/src/create.ts
6
17
  var create_exports = /* @__PURE__ */ __exportAll({
7
18
  createAndJoinMeetFromParams: () => createAndJoinMeetFromParams,
@@ -35,8 +46,8 @@ function resolveCreateSpaceConfig(raw) {
35
46
  function hasCreateSpaceConfigInput(raw) {
36
47
  return normalizeOptionalString(raw.accessType) !== void 0 || normalizeOptionalString(raw.entryPointAccess) !== void 0;
37
48
  }
38
- async function createSpaceFromParams(config, raw) {
39
- const token = await resolveGoogleMeetTokenFromParams(config, raw);
49
+ async function createSpaceFromParams(config, raw, runtime) {
50
+ const token = await resolveGoogleMeetTokenFromParams(config, raw, runtime);
40
51
  return {
41
52
  source: "api",
42
53
  token,
@@ -51,7 +62,7 @@ function hasGoogleMeetOAuth(config, raw) {
51
62
  }
52
63
  async function createMeetFromParams(params) {
53
64
  if (hasGoogleMeetOAuth(params.config, params.raw)) {
54
- const { token: _token, ...result } = await createSpaceFromParams(params.config, params.raw);
65
+ const { token: _token, ...result } = await createSpaceFromParams(params.config, params.raw, params.runtime);
55
66
  return {
56
67
  ...result,
57
68
  joined: false,
@@ -59,10 +70,10 @@ async function createMeetFromParams(params) {
59
70
  };
60
71
  }
61
72
  if (hasCreateSpaceConfigInput(params.raw)) throw new Error("Google Meet access policy options require OAuth/API room creation. Configure Google Meet OAuth or remove accessType/entryPointAccess.");
62
- const browser = await createMeetWithBrowserProxyOnNode({
73
+ const browser = await (params.createViaBrowser ? params.createViaBrowser() : createMeetWithBrowserProxyOnNode({
63
74
  runtime: params.runtime,
64
75
  config: params.config
65
- });
76
+ }));
66
77
  return {
67
78
  source: browser.source,
68
79
  meetingUri: browser.meetingUri,
@@ -82,7 +93,10 @@ async function createMeetFromParams(params) {
82
93
  };
83
94
  }
84
95
  async function createAndJoinMeetFromParams(params) {
85
- const created = await createMeetFromParams(params);
96
+ const created = await createMeetFromParams({
97
+ ...params,
98
+ createViaBrowser: async () => (await params.ensureRuntime()).createViaBrowser()
99
+ });
86
100
  const join = await (await params.ensureRuntime()).join({
87
101
  url: created.meetingUri,
88
102
  transport: normalizeTransport(params.raw.transport),
@@ -1,6 +1,6 @@
1
1
  import { n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-C83Cdmpd.mjs";
2
2
  import { t as normalizeMeetUrl } from "./meet-url-DzLdrq0Z.mjs";
3
- import { a as isSameMeetUrlForReuse, i as isRecoverableMeetTab, n as forceMeetEnglishUi, o as normalizeMeetUrlForReuse, r as isEnglishMeetTab, s as readMeetAuthUser, t as createMeetWithBrowserProxyOnNode } from "./chrome-create-DIcW4QCh.mjs";
3
+ import { a as isSameMeetUrlForReuse, i as isRecoverableMeetTab, n as forceMeetEnglishUi, o as normalizeMeetUrlForReuse, r as isEnglishMeetTab, s as readMeetAuthUser, t as createMeetWithBrowserProxyOnNode } from "./chrome-create-BlDlV2YP.mjs";
4
4
  import { asRecord, filterStringEntries, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
6
6
  import { MeetingPlatformAdapter } from "openclaw/plugin-sdk/meeting-runtime";
@@ -341,6 +341,7 @@ const GOOGLE_MEET_CAPTION_OBSERVER_SOURCE = `
341
341
  function meetAudioCaptureScript(params) {
342
342
  return createMeetingBrowserAudioCaptureSource({
343
343
  ...params,
344
+ webAudioPlaybackGlobal: "__openclawMeetPlayback",
344
345
  ownershipSource: `
345
346
  const expectedUrl = ${JSON.stringify(normalizeMeetUrlForReuse(params.meetingUrl))};
346
347
  const currentUrl = new URL(location.href);
@@ -368,6 +369,24 @@ function meetStatusScript(params) {
368
369
  ]
369
370
  .filter(Boolean)
370
371
  .join(" ");
372
+ const pageText = text(document.body).toLowerCase();
373
+ const host = location.hostname.toLowerCase();
374
+ const googleLoginRequired = host === "accounts.google.com" || /use your google account|to continue to google meet|choose an account|sign in to (join|continue)/i.test(pageText);
375
+ if (!readOnly && host === "meet.google.com" && !googleLoginRequired && allowMicrophone && captionSessionId && !window.__openclawMeetPlayback?.early) {
376
+ const inCall = buttons().some((button) => /leave call/i.test(buttonLabel(button)));
377
+ // Custom input bridges can adopt active calls without browser capture.
378
+ // Managed capture checks early observation itself before it collects audio.
379
+ if (!inCall) {
380
+ const reloadKey = "__openclawMeetPlaybackReload";
381
+ if (${JSON.stringify(params.autoJoin)} && sessionStorage.getItem(reloadKey) !== captionSessionId) {
382
+ sessionStorage.setItem(reloadKey, captionSessionId);
383
+ setTimeout(() => location.reload(), 0);
384
+ return JSON.stringify({ inCall: false, micMuted: true, url: location.href, notes: ["Reloading pre-join Meet once to observe native WebAudio playback."] });
385
+ }
386
+ return JSON.stringify({ inCall, manualAction: manualActionFor("meet-playback-observer-required", "Rejoin this Meet after native WebAudio observation is available."), url: location.href, notes: [] });
387
+ }
388
+ }
389
+ if (!readOnly && window.__openclawMeetPlayback?.early) sessionStorage.removeItem("__openclawMeetPlaybackReload");
371
390
  const buttonLabels = buttons().map(buttonLabel).filter(Boolean);
372
391
  const notes = [];
373
392
  let audioInputRouted;
@@ -411,9 +430,7 @@ function meetStatusScript(params) {
411
430
  input.dispatchEvent(new Event('input', { bubbles: true }));
412
431
  input.dispatchEvent(new Event('change', { bubbles: true }));
413
432
  }
414
- const pageText = text(document.body).toLowerCase();
415
433
  const permissionText = [pageText, ...buttonLabels].join("\\n");
416
- const host = location.hostname.toLowerCase();
417
434
  const pageUrl = location.href;
418
435
  const permissionNeeded = /permission needed|microphone problem|speaker problem|allow.*(microphone|camera)|blocked.*(microphone|camera)|permission.*(microphone|camera|speaker)/i.test(permissionText);
419
436
  let mic = findCallControlButton(/^\\s*turn (?:off|on) microphone\\b/i);
@@ -442,6 +459,8 @@ function meetStatusScript(params) {
442
459
  '[role="combobox"][aria-label*="microphone" i]',
443
460
  '[role="listbox"][aria-label*="microphone" i]',
444
461
  '[aria-haspopup="listbox"][aria-label*="microphone" i]',
462
+ 'button[aria-haspopup="menu"][aria-label^="microphone:" i]',
463
+ '[role="button"][aria-haspopup="menu"][aria-label^="microphone:" i]',
445
464
  ];
446
465
  for (const selector of selectors) {
447
466
  const control = document.querySelector(selector);
@@ -620,7 +639,7 @@ function meetStatusScript(params) {
620
639
  ) return;
621
640
  const mediaElements = [...document.querySelectorAll('audio, video')]
622
641
  .filter((el) => typeof el.setSinkId === 'function');
623
- if (mediaElements.length === 0) return;
642
+
624
643
  try {
625
644
  const devices = await navigator.mediaDevices.enumerateDevices();
626
645
  const inputFamily = audioDeviceFamily(audioInputDeviceLabel);
@@ -638,14 +657,30 @@ function meetStatusScript(params) {
638
657
  }
639
658
  return;
640
659
  }
660
+ if (mediaElements.length === 0) {
661
+ // Meet can use WebAudio without DOM media; device presence alone does not prove selection.
662
+ const control = document.querySelector(
663
+ 'button[aria-haspopup="menu"][aria-label^="speaker:" i], [role="button"][aria-haspopup="menu"][aria-label^="speaker:" i]'
664
+ );
665
+ audioOutputRouted = Boolean(control) && audioDeviceFamily(deviceNodeLabel(control)) === audioDeviceFamily(output.label);
666
+ if (audioOutputRouted) audioOutputDeviceLabel = output.label;
667
+ return;
668
+ }
641
669
  let routed = 0;
670
+ let rejected = 0;
642
671
  for (const element of mediaElements) {
643
672
  if (element.sinkId !== output.deviceId) {
644
673
  if (readOnly) {
645
674
  continue;
646
675
  }
647
- await element.setSinkId(output.deviceId);
648
- routed += 1;
676
+ // One element (e.g. Meet's <video>) rejecting must not abort routing for the rest.
677
+ try {
678
+ await element.setSinkId(output.deviceId);
679
+ routed += 1;
680
+ } catch (error) {
681
+ rejected += 1;
682
+ audioOutputRouteError ??= error?.message || String(error);
683
+ }
649
684
  }
650
685
  }
651
686
  audioOutputRouted = mediaElements.some((element) => element.sinkId === output.deviceId);
@@ -656,6 +691,11 @@ function meetStatusScript(params) {
656
691
  ? \`Routed Meet media output to \${audioOutputDeviceLabel}.\`
657
692
  : \`Meet media output already routed to \${audioOutputDeviceLabel}.\`
658
693
  );
694
+ if (rejected > 0) {
695
+ notes.push(\`\${rejected} Meet media element(s) rejected the speaker route: \${audioOutputRouteError}\`);
696
+ }
697
+ } else if (rejected > 0) {
698
+ notes.push(\`Could not route Meet speaker output to the virtual audio device: \${audioOutputRouteError}\`);
659
699
  }
660
700
  } catch (error) {
661
701
  audioOutputRouted = false;
@@ -672,7 +712,7 @@ function meetStatusScript(params) {
672
712
  ? pageText.match(/you left the meeting|you.?ve left the meeting|removed from the meeting|you were removed|call ended|meeting ended/i)?.[0]
673
713
  : undefined;
674
714
  let manualAction;
675
- if (!inCall && (host === "accounts.google.com" || /use your google account|to continue to google meet|choose an account|sign in to (join|continue)/i.test(pageText))) {
715
+ if (!inCall && googleLoginRequired) {
676
716
  manualAction = manualActionFor("google-login-required", "Sign in to Google in the OpenClaw browser profile, then retry the Meet join.");
677
717
  } else if (!inCall && joinElsewhere) {
678
718
  manualAction = manualActionFor("meet-session-conflict", "Meet is already active in another tab or device. Leave that session or reuse an English-pinned tab before retrying.");
@@ -803,12 +843,6 @@ function prefixDtmfWait(sequence, delayMs) {
803
843
  return `${"w".repeat(waitCount)}${sequence}`;
804
844
  }
805
845
  // extensions/google-meet/src/transports/google-meet-platform-adapter.ts
806
- function parsePermissionGrantNotes(result) {
807
- const unsupportedPermissions = filterStringEntries(asRecord(result).unsupportedPermissions);
808
- const notes = ["Granted Meet microphone/camera permissions through browser control."];
809
- if (unsupportedPermissions.includes("speakerSelection")) notes.push("Chrome did not accept the optional Meet speaker-selection permission.");
810
- return notes;
811
- }
812
846
  const manualActionCategories = /* @__PURE__ */ new Map([
813
847
  ["browser-control-unavailable", "browser-control-unavailable"],
814
848
  ["google-login-required", "login-required"],
@@ -818,9 +852,6 @@ const manualActionCategories = /* @__PURE__ */ new Map([
818
852
  ["meet-permission-required", "permission-required"],
819
853
  ["meet-session-conflict", "session-conflict"]
820
854
  ]);
821
- function classifyManualActionReason(reason) {
822
- return manualActionCategories.get(reason) ?? "custom";
823
- }
824
855
  const GOOGLE_MEET_PLATFORM_ADAPTER = MeetingPlatformAdapter.create({
825
856
  id: "google-meet",
826
857
  displayName: "Google Meet",
@@ -893,7 +924,10 @@ const GOOGLE_MEET_PLATFORM_ADAPTER = MeetingPlatformAdapter.create({
893
924
  permissionNotes: ({ allowMicrophone, error, result }) => {
894
925
  if (!allowMicrophone) return ["Observe-only mode skips Meet microphone/camera permission grants."];
895
926
  if (error) return [`Could not grant Meet media permissions automatically: ${formatErrorMessage(error)}`];
896
- return parsePermissionGrantNotes(result);
927
+ const unsupportedPermissions = filterStringEntries(asRecord(result).unsupportedPermissions);
928
+ const notes = ["Granted Meet microphone/camera permissions through browser control."];
929
+ if (unsupportedPermissions.includes("speakerSelection")) notes.push("Chrome did not accept the optional Meet speaker-selection permission.");
930
+ return notes;
897
931
  }
898
932
  },
899
933
  create: { browser: createMeetWithBrowserProxyOnNode },
@@ -911,7 +945,7 @@ const GOOGLE_MEET_PLATFORM_ADAPTER = MeetingPlatformAdapter.create({
911
945
  };
912
946
  } },
913
947
  parsing: {
914
- classifyManualActionReason,
948
+ classifyManualActionReason: (reason) => manualActionCategories.get(reason) ?? "custom",
915
949
  displayName: "Meet",
916
950
  invalidTranscriptMessage: "Google Meet transcript payload is invalid.",
917
951
  malformedStatusMessage: "Google Meet browser status JSON is malformed.",
@@ -1,6 +1,6 @@
1
1
  import { n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-C83Cdmpd.mjs";
2
- import { n as DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND, t as DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND } from "./config-Cu3zsl_3.mjs";
3
- import { t as GOOGLE_MEET_PLATFORM_ADAPTER } from "./google-meet-platform-adapter-D7poqL1J.mjs";
2
+ import { n as DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND, t as DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND } from "./config-CMTw0Anh.mjs";
3
+ import { t as GOOGLE_MEET_PLATFORM_ADAPTER } from "./google-meet-platform-adapter-DgchqNLV.mjs";
4
4
  import { MeetingPlatformAdapter } from "openclaw/plugin-sdk/meeting-runtime";
5
5
  // extensions/google-meet/src/node-host.ts
6
6
  function normalizeMeetKey(value) {
@@ -1,5 +1,5 @@
1
1
  import { n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-C83Cdmpd.mjs";
2
- import { t as GOOGLE_MEET_PLATFORM_ADAPTER } from "./google-meet-platform-adapter-D7poqL1J.mjs";
2
+ import { t as GOOGLE_MEET_PLATFORM_ADAPTER } from "./google-meet-platform-adapter-DgchqNLV.mjs";
3
3
  import { createMeetingBrowserNodeInvokePolicy } from "openclaw/plugin-sdk/meeting-runtime";
4
4
  // extensions/google-meet/src/node-invoke-policy.ts
5
5
  const START_MODES = /* @__PURE__ */ new Set([
@@ -0,0 +1 @@
1
+ export { i as resolveGoogleMeetAccessToken } from "./plugin-helpers-ChCBuyAl.mjs";