@openclaw/google-meet 2026.6.11 → 2026.7.1-beta.2
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/dist/{chrome-create-DWEeDc7N.js → chrome-create-C1akZT_q.js} +18 -5
- package/dist/{cli-BnEq0tBJ.js → cli-BXICNPAs.js} +3 -3
- package/dist/{create-C7GxW7BL.js → create-CHlW2v6-.js} +2 -2
- package/dist/index.js +179 -39
- package/dist/{oauth-BzOU5Ztq.js → oauth-DK1mwF2i.js} +32 -15
- package/npm-shrinkwrap.json +3 -3
- package/package.json +4 -4
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as googleApiError } from "./google-api-errors-CDUYkIcK.js";
|
|
2
2
|
import { uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
3
|
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
4
|
+
import { readProviderTextResponse } from "openclaw/plugin-sdk/provider-http";
|
|
4
5
|
import { addTimerTimeoutGraceMs } from "openclaw/plugin-sdk/number-runtime";
|
|
5
6
|
import { sleep } from "openclaw/plugin-sdk/runtime-env";
|
|
6
7
|
//#region extensions/google-meet/src/drive.ts
|
|
@@ -40,7 +41,7 @@ async function exportGoogleDriveDocumentText(params) {
|
|
|
40
41
|
prefix: "Google Drive files.export",
|
|
41
42
|
scopes: [GOOGLE_DRIVE_MEET_SCOPE]
|
|
42
43
|
});
|
|
43
|
-
return await response.
|
|
44
|
+
return await readProviderTextResponse(response, "Google Drive files.export");
|
|
44
45
|
} finally {
|
|
45
46
|
await release();
|
|
46
47
|
}
|
|
@@ -597,6 +598,15 @@ function buildGoogleMeetPreflightReport(params) {
|
|
|
597
598
|
}
|
|
598
599
|
//#endregion
|
|
599
600
|
//#region extensions/google-meet/src/transports/chrome-browser-proxy.ts
|
|
601
|
+
function forceMeetEnglishUi(url) {
|
|
602
|
+
try {
|
|
603
|
+
const parsed = new URL(url);
|
|
604
|
+
parsed.searchParams.set("hl", "en");
|
|
605
|
+
return parsed.toString();
|
|
606
|
+
} catch {
|
|
607
|
+
return url;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
600
610
|
function normalizeMeetUrlForReuse(url) {
|
|
601
611
|
if (!url) return;
|
|
602
612
|
try {
|
|
@@ -698,7 +708,8 @@ async function callBrowserProxyOnNode(params) {
|
|
|
698
708
|
body: params.body,
|
|
699
709
|
timeoutMs: params.timeoutMs
|
|
700
710
|
},
|
|
701
|
-
timeoutMs: addTimerTimeoutGraceMs(params.timeoutMs) ?? 1
|
|
711
|
+
timeoutMs: addTimerTimeoutGraceMs(params.timeoutMs) ?? 1,
|
|
712
|
+
scopes: ["operator.admin"]
|
|
702
713
|
}));
|
|
703
714
|
}
|
|
704
715
|
function asBrowserTabs(result) {
|
|
@@ -817,7 +828,9 @@ const CREATE_MEET_FROM_BROWSER_SCRIPT = `async () => {
|
|
|
817
828
|
}
|
|
818
829
|
const href = current();
|
|
819
830
|
if (meetUrlPattern.test(href)) {
|
|
820
|
-
|
|
831
|
+
// The /new redirect keeps the hl=en param we open with; strip query/hash so the
|
|
832
|
+
// meeting link handed to users stays canonical instead of forcing English on them.
|
|
833
|
+
return { meetingUri: href.split(/[?#]/)[0], browserUrl: href, browserTitle: document.title, notes };
|
|
821
834
|
}
|
|
822
835
|
const pageText = text(document.body);
|
|
823
836
|
if (clickButton(/\\buse microphone\\b/i, "Accepted Meet microphone prompt with browser automation.")) {
|
|
@@ -896,7 +909,7 @@ async function createMeetWithBrowserProxyOnNode(params) {
|
|
|
896
909
|
nodeId,
|
|
897
910
|
method: "POST",
|
|
898
911
|
path: "/tabs/open",
|
|
899
|
-
body: { url: GOOGLE_MEET_NEW_URL },
|
|
912
|
+
body: { url: forceMeetEnglishUi(GOOGLE_MEET_NEW_URL) },
|
|
900
913
|
timeoutMs: stepTimeoutMs
|
|
901
914
|
}));
|
|
902
915
|
const targetId = tab?.targetId;
|
|
@@ -950,4 +963,4 @@ async function createMeetWithBrowserProxyOnNode(params) {
|
|
|
950
963
|
throw new Error(lastResult?.manualAction ?? `Google Meet did not return a meeting URL from the browser create flow before timeout.${lastError ? ` Last browser automation error: ${formatBrowserAutomationError(lastError)}` : ""}`);
|
|
951
964
|
}
|
|
952
965
|
//#endregion
|
|
953
|
-
export {
|
|
966
|
+
export { fetchLatestGoogleMeetConferenceRecord as _, forceMeetEnglishUi as a, readBrowserTab as c, buildGoogleMeetPreflightReport as d, createGoogleMeetSpace as f, fetchGoogleMeetSpace as g, fetchGoogleMeetAttendance as h, callBrowserProxyOnNode as i, resolveChromeNode as l, fetchGoogleMeetArtifacts as m, isGoogleMeetBrowserManualActionError as n, isSameMeetUrlForReuse as o, endGoogleMeetActiveConference as p, asBrowserTabs as r, normalizeMeetUrlForReuse as s, createMeetWithBrowserProxyOnNode as t, resolveChromeNodeInfo as u };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as buildGoogleMeetCalendarDayWindow, i as resolveGoogleMeetGatewayOperationTimeoutMs, o as findGoogleMeetCalendarEvent, s as listGoogleMeetCalendarEvents } from "./config-D_YKxh0m.js";
|
|
2
|
-
import {
|
|
3
|
-
import { buildGoogleMeetAuthUrl, createGoogleMeetOAuthState, createGoogleMeetPkce, exchangeGoogleMeetAuthCode, resolveGoogleMeetAccessToken, waitForGoogleMeetAuthCode } from "./oauth-
|
|
4
|
-
import { hasCreateSpaceConfigInput, resolveCreateSpaceConfig } from "./create-
|
|
2
|
+
import { _ as fetchLatestGoogleMeetConferenceRecord, d as buildGoogleMeetPreflightReport, f as createGoogleMeetSpace, g as fetchGoogleMeetSpace, h as fetchGoogleMeetAttendance, m as fetchGoogleMeetArtifacts, p as endGoogleMeetActiveConference } from "./chrome-create-C1akZT_q.js";
|
|
3
|
+
import { buildGoogleMeetAuthUrl, createGoogleMeetOAuthState, createGoogleMeetPkce, exchangeGoogleMeetAuthCode, resolveGoogleMeetAccessToken, waitForGoogleMeetAuthCode } from "./oauth-DK1mwF2i.js";
|
|
4
|
+
import { hasCreateSpaceConfigInput, resolveCreateSpaceConfig } from "./create-CHlW2v6-.js";
|
|
5
5
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
6
6
|
import { callGatewayFromCli } from "openclaw/plugin-sdk/gateway-runtime";
|
|
7
7
|
import { clampTimerTimeoutMs, parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { resolveGoogleMeetAccessToken } from "./oauth-
|
|
1
|
+
import { f as createGoogleMeetSpace, t as createMeetWithBrowserProxyOnNode } from "./chrome-create-C1akZT_q.js";
|
|
2
|
+
import { resolveGoogleMeetAccessToken } from "./oauth-DK1mwF2i.js";
|
|
3
3
|
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
//#region extensions/google-meet/src/create.ts
|
|
5
5
|
function normalizeTransport(value) {
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { a as buildGoogleMeetCalendarDayWindow, i as resolveGoogleMeetGatewayOperationTimeoutMs, n as DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND, o as findGoogleMeetCalendarEvent, r as resolveGoogleMeetConfig, s as listGoogleMeetCalendarEvents, t as DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND } from "./config-D_YKxh0m.js";
|
|
2
|
-
import { a as
|
|
2
|
+
import { _ as fetchLatestGoogleMeetConferenceRecord, a as forceMeetEnglishUi, c as readBrowserTab, d as buildGoogleMeetPreflightReport, g as fetchGoogleMeetSpace, h as fetchGoogleMeetAttendance, i as callBrowserProxyOnNode, l as resolveChromeNode, m as fetchGoogleMeetArtifacts, n as isGoogleMeetBrowserManualActionError, o as isSameMeetUrlForReuse, p as endGoogleMeetActiveConference, r as asBrowserTabs, s as normalizeMeetUrlForReuse, t as createMeetWithBrowserProxyOnNode, u as resolveChromeNodeInfo } from "./chrome-create-C1akZT_q.js";
|
|
3
3
|
import { optionalPositiveIntegerSchema, readPositiveIntegerParam } from "openclaw/plugin-sdk/channel-actions";
|
|
4
4
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
5
5
|
import { ErrorCodes, GatewayClient, callGatewayFromCli, errorShape, startGatewayClientWhenEventLoopReady } from "openclaw/plugin-sdk/gateway-runtime";
|
|
6
|
+
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
6
7
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
7
8
|
import { asRecord, normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
8
9
|
import { Type } from "typebox";
|
|
@@ -31,10 +32,10 @@ function readStringArray(value) {
|
|
|
31
32
|
const result = value.filter((entry) => typeof entry === "string" && entry.length > 0);
|
|
32
33
|
return result.length > 0 ? result : void 0;
|
|
33
34
|
}
|
|
34
|
-
function asRecord$
|
|
35
|
+
function asRecord$3(value) {
|
|
35
36
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
36
37
|
}
|
|
37
|
-
function readString$
|
|
38
|
+
function readString$2(value) {
|
|
38
39
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
39
40
|
}
|
|
40
41
|
function formatErrorMessage$1(error) {
|
|
@@ -155,7 +156,7 @@ function terminateChild(child) {
|
|
|
155
156
|
}, 2e3).unref?.();
|
|
156
157
|
}
|
|
157
158
|
async function pullAudio(params) {
|
|
158
|
-
const bridgeId = readString$
|
|
159
|
+
const bridgeId = readString$2(params.bridgeId);
|
|
159
160
|
if (!bridgeId) throw new Error("bridgeId required");
|
|
160
161
|
const session = sessions.get(bridgeId);
|
|
161
162
|
if (!session) throw new Error(`unknown bridgeId: ${bridgeId}`);
|
|
@@ -171,8 +172,8 @@ async function pullAudio(params) {
|
|
|
171
172
|
};
|
|
172
173
|
}
|
|
173
174
|
function pushAudio(params) {
|
|
174
|
-
const bridgeId = readString$
|
|
175
|
-
const base64 = readString$
|
|
175
|
+
const bridgeId = readString$2(params.bridgeId);
|
|
176
|
+
const base64 = readString$2(params.base64);
|
|
176
177
|
if (!bridgeId || !base64) throw new Error("bridgeId and base64 required");
|
|
177
178
|
const session = sessions.get(bridgeId);
|
|
178
179
|
if (!session || session.closed) throw new Error(`bridge is not open: ${bridgeId}`);
|
|
@@ -191,7 +192,7 @@ function pushAudio(params) {
|
|
|
191
192
|
};
|
|
192
193
|
}
|
|
193
194
|
function clearAudio(params) {
|
|
194
|
-
const bridgeId = readString$
|
|
195
|
+
const bridgeId = readString$2(params.bridgeId);
|
|
195
196
|
if (!bridgeId) throw new Error("bridgeId required");
|
|
196
197
|
const session = sessions.get(bridgeId);
|
|
197
198
|
if (!session || session.closed) throw new Error(`bridge is not open: ${bridgeId}`);
|
|
@@ -209,10 +210,10 @@ function clearAudio(params) {
|
|
|
209
210
|
};
|
|
210
211
|
}
|
|
211
212
|
function startChrome(params) {
|
|
212
|
-
const url = readString$
|
|
213
|
+
const url = readString$2(params.url);
|
|
213
214
|
if (!url) throw new Error("url required");
|
|
214
215
|
const timeoutMs = readNumber(params.joinTimeoutMs, 3e4);
|
|
215
|
-
const mode = readString$
|
|
216
|
+
const mode = readString$2(params.mode);
|
|
216
217
|
let bridgeId;
|
|
217
218
|
let audioBridge;
|
|
218
219
|
if (mode === "agent" || mode === "bidi" || mode === "realtime") {
|
|
@@ -242,11 +243,11 @@ function startChrome(params) {
|
|
|
242
243
|
const argv = [
|
|
243
244
|
"open",
|
|
244
245
|
"-a",
|
|
245
|
-
"Google Chrome"
|
|
246
|
+
"Google Chrome",
|
|
247
|
+
url
|
|
246
248
|
];
|
|
247
|
-
const browserProfile = readString$
|
|
249
|
+
const browserProfile = readString$2(params.browserProfile);
|
|
248
250
|
if (browserProfile) argv.push("--args", `--profile-directory=${browserProfile}`);
|
|
249
|
-
argv.push(url);
|
|
250
251
|
const result = runCommandWithTimeout(argv, timeoutMs);
|
|
251
252
|
if (result.code !== 0) {
|
|
252
253
|
if (bridgeId) {
|
|
@@ -268,7 +269,7 @@ function startChrome(params) {
|
|
|
268
269
|
};
|
|
269
270
|
}
|
|
270
271
|
function bridgeStatus(params) {
|
|
271
|
-
const bridgeId = readString$
|
|
272
|
+
const bridgeId = readString$2(params.bridgeId);
|
|
272
273
|
const session = bridgeId ? sessions.get(bridgeId) : void 0;
|
|
273
274
|
return { bridge: session ? {
|
|
274
275
|
bridgeId,
|
|
@@ -311,15 +312,15 @@ function summarizeSession(session) {
|
|
|
311
312
|
};
|
|
312
313
|
}
|
|
313
314
|
function listSessions(params) {
|
|
314
|
-
const urlKey = normalizeMeetKey(readString$
|
|
315
|
-
const mode = readString$
|
|
315
|
+
const urlKey = normalizeMeetKey(readString$2(params.url));
|
|
316
|
+
const mode = readString$2(params.mode);
|
|
316
317
|
return { bridges: [...sessions.values()].filter((session) => !session.closed).filter((session) => !urlKey || normalizeMeetKey(session.url) === urlKey).filter((session) => !mode || session.mode === mode).map(summarizeSession) };
|
|
317
318
|
}
|
|
318
319
|
function stopSessionsByUrl(params) {
|
|
319
|
-
const urlKey = normalizeMeetKey(readString$
|
|
320
|
+
const urlKey = normalizeMeetKey(readString$2(params.url));
|
|
320
321
|
if (!urlKey) throw new Error("url required");
|
|
321
|
-
const mode = readString$
|
|
322
|
-
const exceptBridgeId = readString$
|
|
322
|
+
const mode = readString$2(params.mode);
|
|
323
|
+
const exceptBridgeId = readString$2(params.exceptBridgeId);
|
|
323
324
|
let stopped = 0;
|
|
324
325
|
for (const [bridgeId, session] of sessions) {
|
|
325
326
|
if (exceptBridgeId && bridgeId === exceptBridgeId) continue;
|
|
@@ -336,7 +337,7 @@ function stopSessionsByUrl(params) {
|
|
|
336
337
|
};
|
|
337
338
|
}
|
|
338
339
|
function stopChrome(params) {
|
|
339
|
-
const bridgeId = readString$
|
|
340
|
+
const bridgeId = readString$2(params.bridgeId);
|
|
340
341
|
if (!bridgeId) return {
|
|
341
342
|
ok: true,
|
|
342
343
|
stopped: false
|
|
@@ -360,8 +361,8 @@ async function handleGoogleMeetNodeHostCommand(paramsJSON) {
|
|
|
360
361
|
} catch {
|
|
361
362
|
throw new Error("Google Meet node host received malformed params JSON.");
|
|
362
363
|
}
|
|
363
|
-
const params = asRecord$
|
|
364
|
-
const action = readString$
|
|
364
|
+
const params = asRecord$3(raw);
|
|
365
|
+
const action = readString$2(params.action);
|
|
365
366
|
let result;
|
|
366
367
|
switch (action) {
|
|
367
368
|
case "setup":
|
|
@@ -1575,10 +1576,10 @@ async function startCommandRealtimeAudioBridge(params) {
|
|
|
1575
1576
|
}
|
|
1576
1577
|
//#endregion
|
|
1577
1578
|
//#region extensions/google-meet/src/realtime-node.ts
|
|
1578
|
-
function asRecord$
|
|
1579
|
+
function asRecord$2(value) {
|
|
1579
1580
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1580
1581
|
}
|
|
1581
|
-
function readString(value) {
|
|
1582
|
+
function readString$1(value) {
|
|
1582
1583
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
1583
1584
|
}
|
|
1584
1585
|
function normalizeGoogleMeetTtsPromptText(text) {
|
|
@@ -1609,10 +1610,10 @@ function startGoogleMeetNodeAudioInputLoop(params) {
|
|
|
1609
1610
|
},
|
|
1610
1611
|
timeoutMs: 2e3
|
|
1611
1612
|
});
|
|
1612
|
-
const result = asRecord$
|
|
1613
|
+
const result = asRecord$2(asRecord$2(raw).payload ?? raw);
|
|
1613
1614
|
consecutiveInputErrors = 0;
|
|
1614
1615
|
lastInputError = void 0;
|
|
1615
|
-
const base64 = readString(result.base64);
|
|
1616
|
+
const base64 = readString$1(result.base64);
|
|
1616
1617
|
if (base64) {
|
|
1617
1618
|
const audio = Buffer.from(base64, "base64");
|
|
1618
1619
|
if (params.isInputSuppressed()) {
|
|
@@ -2389,7 +2390,7 @@ function meetStatusScript(params) {
|
|
|
2389
2390
|
notes.push("Muted Meet microphone for observe-only mode.");
|
|
2390
2391
|
}
|
|
2391
2392
|
const join = !readOnly && ${JSON.stringify(params.autoJoin)}
|
|
2392
|
-
? findButton(/join now|ask to join/i)
|
|
2393
|
+
? findButton(/join now|ask to join|join here too/i)
|
|
2393
2394
|
: null;
|
|
2394
2395
|
if (join) join.click();
|
|
2395
2396
|
const microphoneChoice = findButton(/\\buse microphone\\b/i);
|
|
@@ -2623,7 +2624,7 @@ async function openMeetWithBrowserRequest(params) {
|
|
|
2623
2624
|
tab = readBrowserTab(await params.callBrowser({
|
|
2624
2625
|
method: "POST",
|
|
2625
2626
|
path: "/tabs/open",
|
|
2626
|
-
body: { url: params.url },
|
|
2627
|
+
body: { url: forceMeetEnglishUi(params.url) },
|
|
2627
2628
|
timeoutMs
|
|
2628
2629
|
}));
|
|
2629
2630
|
targetId = tab?.targetId;
|
|
@@ -3721,17 +3722,154 @@ var GoogleMeetRuntime = class {
|
|
|
3721
3722
|
}
|
|
3722
3723
|
};
|
|
3723
3724
|
//#endregion
|
|
3725
|
+
//#region extensions/google-meet/src/node-invoke-policy.ts
|
|
3726
|
+
const GOOGLE_MEET_CHROME_NODE_COMMAND = "googlemeet.chrome";
|
|
3727
|
+
const START_MODES = new Set([
|
|
3728
|
+
"agent",
|
|
3729
|
+
"bidi",
|
|
3730
|
+
"realtime",
|
|
3731
|
+
"transcribe"
|
|
3732
|
+
]);
|
|
3733
|
+
function asRecord$1(value) {
|
|
3734
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
3735
|
+
}
|
|
3736
|
+
function readString(value) {
|
|
3737
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
3738
|
+
}
|
|
3739
|
+
function readPositiveNumber(value) {
|
|
3740
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
|
|
3741
|
+
}
|
|
3742
|
+
function copyCommand(command) {
|
|
3743
|
+
return command && command.length > 0 ? [...command] : void 0;
|
|
3744
|
+
}
|
|
3745
|
+
function denied(message, code = "GOOGLE_MEET_NODE_POLICY_DENIED") {
|
|
3746
|
+
return {
|
|
3747
|
+
ok: false,
|
|
3748
|
+
code,
|
|
3749
|
+
message
|
|
3750
|
+
};
|
|
3751
|
+
}
|
|
3752
|
+
function approved(params) {
|
|
3753
|
+
return {
|
|
3754
|
+
approved: true,
|
|
3755
|
+
params
|
|
3756
|
+
};
|
|
3757
|
+
}
|
|
3758
|
+
function buildStartParams(params, config) {
|
|
3759
|
+
let url;
|
|
3760
|
+
try {
|
|
3761
|
+
url = normalizeMeetUrl(params.url);
|
|
3762
|
+
} catch (error) {
|
|
3763
|
+
return {
|
|
3764
|
+
approved: false,
|
|
3765
|
+
result: denied(error instanceof Error ? error.message : "googlemeet.chrome start requires url")
|
|
3766
|
+
};
|
|
3767
|
+
}
|
|
3768
|
+
const mode = readString(params.mode);
|
|
3769
|
+
if (mode && !START_MODES.has(mode)) return {
|
|
3770
|
+
approved: false,
|
|
3771
|
+
result: denied(`googlemeet.chrome start mode is unsupported: ${mode}`)
|
|
3772
|
+
};
|
|
3773
|
+
const startParams = {
|
|
3774
|
+
action: "start",
|
|
3775
|
+
url,
|
|
3776
|
+
launch: params.launch === false ? false : config.chrome.launch,
|
|
3777
|
+
browserProfile: config.chrome.browserProfile,
|
|
3778
|
+
joinTimeoutMs: config.chrome.joinTimeoutMs
|
|
3779
|
+
};
|
|
3780
|
+
if (mode) startParams.mode = mode;
|
|
3781
|
+
const audioInputCommand = copyCommand(config.chrome.audioInputCommand);
|
|
3782
|
+
if (audioInputCommand) startParams.audioInputCommand = audioInputCommand;
|
|
3783
|
+
const audioOutputCommand = copyCommand(config.chrome.audioOutputCommand);
|
|
3784
|
+
if (audioOutputCommand) startParams.audioOutputCommand = audioOutputCommand;
|
|
3785
|
+
const audioBridgeCommand = copyCommand(config.chrome.audioBridgeCommand);
|
|
3786
|
+
if (audioBridgeCommand) startParams.audioBridgeCommand = audioBridgeCommand;
|
|
3787
|
+
const audioBridgeHealthCommand = copyCommand(config.chrome.audioBridgeHealthCommand);
|
|
3788
|
+
if (audioBridgeHealthCommand) startParams.audioBridgeHealthCommand = audioBridgeHealthCommand;
|
|
3789
|
+
return approved(startParams);
|
|
3790
|
+
}
|
|
3791
|
+
function buildForwardParams(params) {
|
|
3792
|
+
const action = readString(params.action);
|
|
3793
|
+
switch (action) {
|
|
3794
|
+
case "setup": return { action };
|
|
3795
|
+
case "status": {
|
|
3796
|
+
const bridgeId = readString(params.bridgeId);
|
|
3797
|
+
return bridgeId ? {
|
|
3798
|
+
action,
|
|
3799
|
+
bridgeId
|
|
3800
|
+
} : { action };
|
|
3801
|
+
}
|
|
3802
|
+
case "list": {
|
|
3803
|
+
const forwarded = { action };
|
|
3804
|
+
const url = readString(params.url);
|
|
3805
|
+
const mode = readString(params.mode);
|
|
3806
|
+
if (url) forwarded.url = url;
|
|
3807
|
+
if (mode) forwarded.mode = mode;
|
|
3808
|
+
return forwarded;
|
|
3809
|
+
}
|
|
3810
|
+
case "stopByUrl": {
|
|
3811
|
+
const forwarded = { action };
|
|
3812
|
+
const url = readString(params.url);
|
|
3813
|
+
const mode = readString(params.mode);
|
|
3814
|
+
const exceptBridgeId = readString(params.exceptBridgeId);
|
|
3815
|
+
if (url) forwarded.url = url;
|
|
3816
|
+
if (mode) forwarded.mode = mode;
|
|
3817
|
+
if (exceptBridgeId) forwarded.exceptBridgeId = exceptBridgeId;
|
|
3818
|
+
return forwarded;
|
|
3819
|
+
}
|
|
3820
|
+
case "pullAudio": {
|
|
3821
|
+
const forwarded = { action };
|
|
3822
|
+
const bridgeId = readString(params.bridgeId);
|
|
3823
|
+
const timeoutMs = readPositiveNumber(params.timeoutMs);
|
|
3824
|
+
if (bridgeId) forwarded.bridgeId = bridgeId;
|
|
3825
|
+
if (timeoutMs) forwarded.timeoutMs = timeoutMs;
|
|
3826
|
+
return forwarded;
|
|
3827
|
+
}
|
|
3828
|
+
case "pushAudio": {
|
|
3829
|
+
const forwarded = { action };
|
|
3830
|
+
const bridgeId = readString(params.bridgeId);
|
|
3831
|
+
const base64 = readString(params.base64);
|
|
3832
|
+
if (bridgeId) forwarded.bridgeId = bridgeId;
|
|
3833
|
+
if (base64) forwarded.base64 = base64;
|
|
3834
|
+
return forwarded;
|
|
3835
|
+
}
|
|
3836
|
+
case "clearAudio":
|
|
3837
|
+
case "stop": {
|
|
3838
|
+
const bridgeId = readString(params.bridgeId);
|
|
3839
|
+
return bridgeId ? {
|
|
3840
|
+
action,
|
|
3841
|
+
bridgeId
|
|
3842
|
+
} : { action };
|
|
3843
|
+
}
|
|
3844
|
+
default: return null;
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3847
|
+
function createGoogleMeetChromeNodeInvokePolicy(config) {
|
|
3848
|
+
return {
|
|
3849
|
+
commands: [GOOGLE_MEET_CHROME_NODE_COMMAND],
|
|
3850
|
+
dangerous: true,
|
|
3851
|
+
async handle(ctx) {
|
|
3852
|
+
if (ctx.command !== "googlemeet.chrome") return denied(`unsupported Google Meet node command: ${ctx.command}`);
|
|
3853
|
+
const params = asRecord$1(ctx.params);
|
|
3854
|
+
const action = readString(params.action);
|
|
3855
|
+
let decision;
|
|
3856
|
+
if (action === "start") decision = buildStartParams(params, config);
|
|
3857
|
+
else {
|
|
3858
|
+
const forwardParams = buildForwardParams(params);
|
|
3859
|
+
decision = forwardParams ? approved(forwardParams) : {
|
|
3860
|
+
approved: false,
|
|
3861
|
+
result: denied("unsupported googlemeet.chrome action")
|
|
3862
|
+
};
|
|
3863
|
+
}
|
|
3864
|
+
if (!decision.approved) return decision.result;
|
|
3865
|
+
return await ctx.invokeNode({ params: decision.params });
|
|
3866
|
+
}
|
|
3867
|
+
};
|
|
3868
|
+
}
|
|
3869
|
+
//#endregion
|
|
3724
3870
|
//#region extensions/google-meet/index.ts
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
const loadGoogleMeetCreateModule = async () => {
|
|
3728
|
-
googleMeetCreateModulePromise ??= import("./create-C7GxW7BL.js");
|
|
3729
|
-
return await googleMeetCreateModulePromise;
|
|
3730
|
-
};
|
|
3731
|
-
const loadGoogleMeetCliModule = async () => {
|
|
3732
|
-
googleMeetCliModulePromise ??= import("./cli-BnEq0tBJ.js");
|
|
3733
|
-
return await googleMeetCliModulePromise;
|
|
3734
|
-
};
|
|
3871
|
+
const loadGoogleMeetCreateModule = createLazyRuntimeModule(() => import("./create-CHlW2v6-.js"));
|
|
3872
|
+
const loadGoogleMeetCliModule = createLazyRuntimeModule(() => import("./cli-BXICNPAs.js"));
|
|
3735
3873
|
const googleMeetConfigSchema = {
|
|
3736
3874
|
parse(value) {
|
|
3737
3875
|
return resolveGoogleMeetConfig(value);
|
|
@@ -4102,7 +4240,7 @@ async function createAndJoinMeetFromParams(params) {
|
|
|
4102
4240
|
return (await loadGoogleMeetCreateModule()).createAndJoinMeetFromParams(params);
|
|
4103
4241
|
}
|
|
4104
4242
|
async function resolveGoogleMeetTokenFromParams(config, raw) {
|
|
4105
|
-
const { resolveGoogleMeetAccessToken } = await import("./oauth-
|
|
4243
|
+
const { resolveGoogleMeetAccessToken } = await import("./oauth-DK1mwF2i.js");
|
|
4106
4244
|
return resolveGoogleMeetAccessToken({
|
|
4107
4245
|
clientId: normalizeOptionalString(raw.clientId) ?? config.oauth.clientId,
|
|
4108
4246
|
clientSecret: normalizeOptionalString(raw.clientSecret) ?? config.oauth.clientSecret,
|
|
@@ -4602,10 +4740,12 @@ var google_meet_default = definePluginEntry({
|
|
|
4602
4740
|
}
|
|
4603
4741
|
}), { name: "google_meet" });
|
|
4604
4742
|
api.registerNodeHostCommand({
|
|
4605
|
-
command:
|
|
4743
|
+
command: GOOGLE_MEET_CHROME_NODE_COMMAND,
|
|
4606
4744
|
cap: "google-meet",
|
|
4745
|
+
dangerous: true,
|
|
4607
4746
|
handle: handleGoogleMeetNodeHostCommand
|
|
4608
4747
|
});
|
|
4748
|
+
api.registerNodeInvokePolicy(createGoogleMeetChromeNodeInvokePolicy(config));
|
|
4609
4749
|
api.registerCli(async ({ program }) => {
|
|
4610
4750
|
const { registerGoogleMeetCli } = await loadGoogleMeetCliModule();
|
|
4611
4751
|
registerGoogleMeetCli({
|
|
@@ -124,25 +124,42 @@ function createGoogleMeetPkce() {
|
|
|
124
124
|
function createGoogleMeetOAuthState() {
|
|
125
125
|
return generateOAuthState();
|
|
126
126
|
}
|
|
127
|
+
function isLocalCallbackListenerError(error) {
|
|
128
|
+
if (!(error instanceof Error)) return false;
|
|
129
|
+
return error.message.includes("EADDRINUSE") || error.message.includes("port") || error.message.includes("listen");
|
|
130
|
+
}
|
|
131
|
+
async function readManualGoogleMeetAuthCode(params) {
|
|
132
|
+
const parsed = parseOAuthCallbackInput(await params.promptInput("Paste the full redirect URL here: "), {
|
|
133
|
+
missingState: "Missing 'state' parameter. Paste the full redirect URL.",
|
|
134
|
+
invalidInput: "Paste the full redirect URL, not just the code."
|
|
135
|
+
});
|
|
136
|
+
if ("error" in parsed) throw new Error(parsed.error);
|
|
137
|
+
if (parsed.state !== params.state) throw new Error("OAuth state mismatch - please try again");
|
|
138
|
+
return parsed.code;
|
|
139
|
+
}
|
|
127
140
|
async function waitForGoogleMeetAuthCode(params) {
|
|
128
141
|
params.writeLine(`Open this URL in your browser:\n\n${params.authUrl}\n`);
|
|
129
|
-
if (params.manual) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
142
|
+
if (params.manual) return await readManualGoogleMeetAuthCode({
|
|
143
|
+
state: params.state,
|
|
144
|
+
promptInput: params.promptInput
|
|
145
|
+
});
|
|
146
|
+
try {
|
|
147
|
+
return (await waitForLocalOAuthCallback({
|
|
148
|
+
expectedState: params.state,
|
|
149
|
+
timeoutMs: params.timeoutMs,
|
|
150
|
+
port: 8085,
|
|
151
|
+
callbackPath: "/oauth2callback",
|
|
152
|
+
redirectUri: GOOGLE_MEET_REDIRECT_URI,
|
|
153
|
+
successTitle: "Google Meet OAuth complete"
|
|
154
|
+
})).code;
|
|
155
|
+
} catch (error) {
|
|
156
|
+
if (!isLocalCallbackListenerError(error)) throw error;
|
|
157
|
+
params.writeLine("Local callback server failed. Switching to manual mode...");
|
|
158
|
+
return await readManualGoogleMeetAuthCode({
|
|
159
|
+
state: params.state,
|
|
160
|
+
promptInput: params.promptInput
|
|
133
161
|
});
|
|
134
|
-
if ("error" in parsed) throw new Error(parsed.error);
|
|
135
|
-
if (parsed.state !== params.state) throw new Error("OAuth state mismatch - please try again");
|
|
136
|
-
return parsed.code;
|
|
137
162
|
}
|
|
138
|
-
return (await waitForLocalOAuthCallback({
|
|
139
|
-
expectedState: params.state,
|
|
140
|
-
timeoutMs: params.timeoutMs,
|
|
141
|
-
port: 8085,
|
|
142
|
-
callbackPath: "/oauth2callback",
|
|
143
|
-
redirectUri: GOOGLE_MEET_REDIRECT_URI,
|
|
144
|
-
successTitle: "Google Meet OAuth complete"
|
|
145
|
-
})).code;
|
|
146
163
|
}
|
|
147
164
|
//#endregion
|
|
148
165
|
export { buildGoogleMeetAuthUrl, createGoogleMeetOAuthState, createGoogleMeetPkce, exchangeGoogleMeetAuthCode, resolveGoogleMeetAccessToken, waitForGoogleMeetAuthCode };
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/google-meet",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.7.1-beta.2",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@openclaw/google-meet",
|
|
9
|
-
"version": "2026.
|
|
9
|
+
"version": "2026.7.1-beta.2",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"commander": "14.0.3",
|
|
12
12
|
"typebox": "1.1.39"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"openclaw": ">=2026.
|
|
15
|
+
"openclaw": ">=2026.7.1-beta.2"
|
|
16
16
|
},
|
|
17
17
|
"peerDependenciesMeta": {
|
|
18
18
|
"openclaw": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/google-meet",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.7.1-beta.2",
|
|
4
4
|
"description": "OpenClaw Google Meet participant plugin for joining calls through Chrome or Twilio transports.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"typebox": "1.1.39"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"openclaw": ">=2026.
|
|
15
|
+
"openclaw": ">=2026.7.1-beta.2"
|
|
16
16
|
},
|
|
17
17
|
"peerDependenciesMeta": {
|
|
18
18
|
"openclaw": {
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"minHostVersion": ">=2026.4.20"
|
|
30
30
|
},
|
|
31
31
|
"compat": {
|
|
32
|
-
"pluginApi": ">=2026.
|
|
32
|
+
"pluginApi": ">=2026.7.1-beta.2"
|
|
33
33
|
},
|
|
34
34
|
"build": {
|
|
35
|
-
"openclawVersion": "2026.
|
|
35
|
+
"openclawVersion": "2026.7.1-beta.2"
|
|
36
36
|
},
|
|
37
37
|
"release": {
|
|
38
38
|
"publishToClawHub": true,
|