@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.
- package/assets/activity.svg +1 -1
- package/dist/.setup/{chrome-create-DIcW4QCh.mjs → chrome-create-BlDlV2YP.mjs} +11 -30
- package/dist/.setup/{cli-9linTFHb.mjs → cli-C-MrY7IZ.mjs} +275 -309
- package/dist/.setup/{cli-export-CaDYoSP8.mjs → cli-export-6eiywS3T.mjs} +16 -35
- package/dist/.setup/{cli-output-mode-BJSm88N9.mjs → cli-output-mode-DztqqVeZ.mjs} +5 -6
- package/dist/.setup/config-CMTw0Anh.mjs +110 -0
- package/dist/.setup/{create-D3fHR8uX.mjs → create-DMk4zbMq.mjs} +23 -9
- package/dist/.setup/{google-meet-platform-adapter-D7poqL1J.mjs → google-meet-platform-adapter-DgchqNLV.mjs} +52 -18
- package/dist/.setup/{node-host-B196lvNZ.mjs → node-host-BIZD9InM.mjs} +2 -2
- package/dist/.setup/{node-invoke-policy-BzRAe25r.mjs → node-invoke-policy-bg7p_BWB.mjs} +1 -1
- package/dist/.setup/oauth-DZkuGMs1.mjs +1 -0
- package/dist/.setup/{plugin-helpers-Buhixxsx.mjs → plugin-helpers-ChCBuyAl.mjs} +363 -69
- package/dist/.setup/{plugin-registration-B_nOxAym.mjs → plugin-registration-CAW7_zO_.mjs} +8 -8
- package/dist/.setup/{runtime-D-dwEsSW.mjs → runtime-Cyc6bv1i.mjs} +37 -38
- package/dist/.source-module-urls/c06239f68b6f4959b5d3db7e0cee004911d8eb43092f4135c729b507e37f6333.json +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/doctor-contract-api.js +25 -21
- package/dist/index.js +14 -13
- package/node_modules/typebox/build/format/duration.d.mts +2 -2
- package/node_modules/typebox/build/format/duration.mjs +2 -2
- package/node_modules/typebox/build/format/idn_email.d.mts +1 -0
- package/node_modules/typebox/build/format/idn_email.mjs +1 -0
- package/node_modules/typebox/build/format/idn_hostname.d.mts +1 -1
- package/node_modules/typebox/build/format/idn_hostname.mjs +1 -1
- package/node_modules/typebox/build/format/ipv4.d.mts +2 -2
- package/node_modules/typebox/build/format/ipv4.mjs +2 -2
- package/node_modules/typebox/build/format/ipv6.d.mts +1 -1
- package/node_modules/typebox/build/format/ipv6.mjs +1 -1
- package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
- package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
- package/node_modules/typebox/build/schema/build.mjs +1 -0
- package/node_modules/typebox/build/schema/engine/_unique.d.mts +4 -2
- package/node_modules/typebox/build/schema/engine/_unique.mjs +7 -3
- package/node_modules/typebox/build/schema/engine/additionalItems.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/additionalProperties.d.mts +0 -3
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +15 -17
- package/node_modules/typebox/build/schema/engine/contains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/index.d.mts +1 -0
- package/node_modules/typebox/build/schema/engine/index.mjs +1 -0
- package/node_modules/typebox/build/schema/engine/items.mjs +7 -4
- package/node_modules/typebox/build/schema/engine/maxContains.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/minContains.mjs +3 -3
- package/node_modules/typebox/build/schema/engine/oneOf.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/unevaluatedItems.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/unevaluatedProperties.mjs +2 -2
- package/node_modules/typebox/build/system/hashing/hash.mjs +63 -34
- package/node_modules/typebox/build/system/locale/en_US.mjs +2 -1
- package/node_modules/typebox/build/system/memory/assign.d.mts +2 -8
- package/node_modules/typebox/build/system/memory/assign.mjs +13 -6
- package/node_modules/typebox/build/system/memory/clone.d.mts +4 -5
- package/node_modules/typebox/build/system/memory/clone.mjs +8 -96
- package/node_modules/typebox/build/system/memory/create.d.mts +1 -5
- package/node_modules/typebox/build/system/memory/create.mjs +18 -13
- package/node_modules/typebox/build/system/memory/deep.d.mts +2 -0
- package/node_modules/typebox/build/system/memory/deep.mjs +108 -0
- package/node_modules/typebox/build/system/memory/discard.d.mts +1 -1
- package/node_modules/typebox/build/system/memory/discard.mjs +9 -8
- package/node_modules/typebox/build/system/memory/finalize.d.mts +4 -0
- package/node_modules/typebox/build/system/memory/finalize.mjs +30 -0
- package/node_modules/typebox/build/system/memory/keys.d.mts +2 -0
- package/node_modules/typebox/build/system/memory/keys.mjs +8 -0
- package/node_modules/typebox/build/system/memory/update.d.mts +1 -4
- package/node_modules/typebox/build/system/memory/update.mjs +43 -16
- package/node_modules/typebox/build/type/engine/call/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/call/index.mjs +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/composite.d.mts +2 -24
- package/node_modules/typebox/build/type/engine/evaluate/composite.mjs +2 -29
- package/node_modules/typebox/build/type/engine/evaluate/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/index.mjs +1 -0
- package/node_modules/typebox/build/type/engine/evaluate/narrow.d.mts +5 -1
- package/node_modules/typebox/build/type/engine/evaluate/narrow.mjs +6 -1
- package/node_modules/typebox/build/type/engine/evaluate/property.d.mts +30 -0
- package/node_modules/typebox/build/type/engine/evaluate/property.mjs +29 -0
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/immutable/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/object/from_intersect.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/object/from_intersect.mjs +2 -2
- package/node_modules/typebox/build/type/engine/object/from_union.d.mts +2 -2
- package/node_modules/typebox/build/type/engine/object/from_union.mjs +2 -2
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.d.mts +1 -3
- package/node_modules/typebox/build/type/engine/readonly/instantiate_add.mjs +1 -4
- package/node_modules/typebox/build/type/engine/this/index.d.mts +1 -0
- package/node_modules/typebox/build/type/engine/this/index.mjs +1 -0
- package/node_modules/typebox/build/value/clone/clone.d.mts +4 -3
- package/node_modules/typebox/build/value/clone/clone.mjs +5 -7
- package/node_modules/typebox/build/value/repair/from_cyclic.d.mts +2 -0
- package/node_modules/typebox/build/value/repair/from_cyclic.mjs +6 -0
- package/node_modules/typebox/build/value/shared/union_priority_sort.mjs +25 -14
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +1 -1
- package/package.json +5 -5
- package/dist/.setup/config-Cu3zsl_3.mjs +0 -239
- package/dist/.setup/oauth-DGv28ZgA.mjs +0 -158
- package/node_modules/typebox/build/system/memory/freeze.d.mts +0 -4
- package/node_modules/typebox/build/system/memory/freeze.mjs +0 -6
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
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
|
-
|
|
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
|
|
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 {
|
|
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
|
-
|
|
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 {
|
|
2
|
-
import {
|
|
3
|
-
import { t as createMeetWithBrowserProxyOnNode } from "./chrome-create-
|
|
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(
|
|
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-
|
|
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
|
-
|
|
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
|
-
|
|
648
|
-
|
|
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 &&
|
|
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
|
-
|
|
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-
|
|
3
|
-
import { t as GOOGLE_MEET_PLATFORM_ADAPTER } from "./google-meet-platform-adapter-
|
|
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-
|
|
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";
|