@openclaw/google-meet 2026.6.34 → 2026.6.35
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-C48OmpbM.js → chrome-create-Bj2SRzJo.js} +38 -38
- package/dist/{cli-Cn8kxkfr.js → cli-2526f6ZI.js} +4 -4
- package/dist/{config-D_YKxh0m.js → config-DHJVagqv.js} +49 -13
- package/dist/{create-C0XRpM4Z.js → create-DY7DeuqN.js} +2 -2
- package/dist/index.js +21 -20
- package/dist/{oauth-DK1mwF2i.js → oauth-PrwH5ptn.js} +6 -2
- package/npm-shrinkwrap.json +3 -3
- package/package.json +4 -4
|
@@ -8,6 +8,7 @@ import { sleep } from "openclaw/plugin-sdk/runtime-env";
|
|
|
8
8
|
const GOOGLE_DRIVE_API_BASE_URL = "https://www.googleapis.com/drive/v3";
|
|
9
9
|
const GOOGLE_DRIVE_API_HOST = "www.googleapis.com";
|
|
10
10
|
const GOOGLE_DRIVE_MEET_SCOPE = "https://www.googleapis.com/auth/drive.meet.readonly";
|
|
11
|
+
const GOOGLE_DRIVE_REQUEST_TIMEOUT_MS = 3e4;
|
|
11
12
|
const TEXT_PLAIN_MIME = "text/plain";
|
|
12
13
|
function appendQuery$1(url, query) {
|
|
13
14
|
const parsed = new URL(url);
|
|
@@ -33,7 +34,8 @@ async function exportGoogleDriveDocumentText(params) {
|
|
|
33
34
|
Accept: TEXT_PLAIN_MIME
|
|
34
35
|
} },
|
|
35
36
|
policy: { allowedHostnames: [GOOGLE_DRIVE_API_HOST] },
|
|
36
|
-
auditContext: "google-meet.drive.files.export"
|
|
37
|
+
auditContext: "google-meet.drive.files.export",
|
|
38
|
+
timeoutMs: GOOGLE_DRIVE_REQUEST_TIMEOUT_MS
|
|
37
39
|
});
|
|
38
40
|
try {
|
|
39
41
|
if (!response.ok) throw await googleApiError({
|
|
@@ -51,6 +53,7 @@ async function exportGoogleDriveDocumentText(params) {
|
|
|
51
53
|
const GOOGLE_MEET_API_BASE_URL = `https://meet.googleapis.com/v2`;
|
|
52
54
|
const GOOGLE_MEET_URL_HOST = "meet.google.com";
|
|
53
55
|
const GOOGLE_MEET_API_HOST = "meet.googleapis.com";
|
|
56
|
+
const GOOGLE_MEET_REQUEST_TIMEOUT_MS = 3e4;
|
|
54
57
|
const GOOGLE_MEET_MEDIA_SCOPE = "https://www.googleapis.com/auth/meetings.conference.media.readonly";
|
|
55
58
|
const GOOGLE_MEET_SPACE_SCOPE = "https://www.googleapis.com/auth/meetings.space.readonly";
|
|
56
59
|
const GOOGLE_MEET_SPACE_CREATED_SCOPE = "https://www.googleapis.com/auth/meetings.space.created";
|
|
@@ -101,14 +104,28 @@ function assertResourceArray(value, key, context) {
|
|
|
101
104
|
function getErrorMessage(error) {
|
|
102
105
|
return error instanceof Error ? error.message : String(error);
|
|
103
106
|
}
|
|
104
|
-
async function
|
|
105
|
-
|
|
107
|
+
async function requestGoogleMeetApi(params) {
|
|
108
|
+
return await fetchWithSsrFGuard({
|
|
106
109
|
url: appendQuery(`${GOOGLE_MEET_API_BASE_URL}/${params.path}`, params.query),
|
|
107
|
-
init: {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
init: {
|
|
111
|
+
method: params.method,
|
|
112
|
+
headers: {
|
|
113
|
+
Authorization: `Bearer ${params.accessToken}`,
|
|
114
|
+
Accept: "application/json",
|
|
115
|
+
...params.body === void 0 ? {} : { "Content-Type": "application/json" }
|
|
116
|
+
},
|
|
117
|
+
body: params.body
|
|
118
|
+
},
|
|
111
119
|
policy: { allowedHostnames: [GOOGLE_MEET_API_HOST] },
|
|
120
|
+
auditContext: params.auditContext,
|
|
121
|
+
timeoutMs: GOOGLE_MEET_REQUEST_TIMEOUT_MS
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
async function fetchGoogleMeetJson(params) {
|
|
125
|
+
const { response, release } = await requestGoogleMeetApi({
|
|
126
|
+
accessToken: params.accessToken,
|
|
127
|
+
path: params.path,
|
|
128
|
+
query: params.query,
|
|
112
129
|
auditContext: params.auditContext
|
|
113
130
|
});
|
|
114
131
|
try {
|
|
@@ -145,13 +162,10 @@ async function listGoogleMeetCollection(params) {
|
|
|
145
162
|
return items;
|
|
146
163
|
}
|
|
147
164
|
async function fetchGoogleMeetSpace(params) {
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
Accept: "application/json"
|
|
153
|
-
} },
|
|
154
|
-
policy: { allowedHostnames: [GOOGLE_MEET_API_HOST] },
|
|
165
|
+
const name = normalizeGoogleMeetSpaceName(params.meeting);
|
|
166
|
+
const { response, release } = await requestGoogleMeetApi({
|
|
167
|
+
accessToken: params.accessToken,
|
|
168
|
+
path: encodeSpaceNameForPath(name),
|
|
155
169
|
auditContext: "google-meet.spaces.get"
|
|
156
170
|
});
|
|
157
171
|
try {
|
|
@@ -169,18 +183,11 @@ async function fetchGoogleMeetSpace(params) {
|
|
|
169
183
|
}
|
|
170
184
|
async function createGoogleMeetSpace(params) {
|
|
171
185
|
const body = params.config && Object.keys(params.config).length > 0 ? JSON.stringify({ config: params.config }) : "{}";
|
|
172
|
-
const { response, release } = await
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
Authorization: `Bearer ${params.accessToken}`,
|
|
178
|
-
Accept: "application/json",
|
|
179
|
-
"Content-Type": "application/json"
|
|
180
|
-
},
|
|
181
|
-
body
|
|
182
|
-
},
|
|
183
|
-
policy: { allowedHostnames: [GOOGLE_MEET_API_HOST] },
|
|
186
|
+
const { response, release } = await requestGoogleMeetApi({
|
|
187
|
+
accessToken: params.accessToken,
|
|
188
|
+
path: "spaces",
|
|
189
|
+
method: "POST",
|
|
190
|
+
body,
|
|
184
191
|
auditContext: "google-meet.spaces.create"
|
|
185
192
|
});
|
|
186
193
|
try {
|
|
@@ -206,18 +213,11 @@ async function endGoogleMeetActiveConference(params) {
|
|
|
206
213
|
accessToken: params.accessToken,
|
|
207
214
|
meeting: params.meeting
|
|
208
215
|
})).name;
|
|
209
|
-
const { response, release } = await
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
Authorization: `Bearer ${params.accessToken}`,
|
|
215
|
-
Accept: "application/json",
|
|
216
|
-
"Content-Type": "application/json"
|
|
217
|
-
},
|
|
218
|
-
body: "{}"
|
|
219
|
-
},
|
|
220
|
-
policy: { allowedHostnames: [GOOGLE_MEET_API_HOST] },
|
|
216
|
+
const { response, release } = await requestGoogleMeetApi({
|
|
217
|
+
accessToken: params.accessToken,
|
|
218
|
+
path: `${encodeSpaceNameForPath(space)}:endActiveConference`,
|
|
219
|
+
method: "POST",
|
|
220
|
+
body: "{}",
|
|
221
221
|
auditContext: "google-meet.spaces.endActiveConference"
|
|
222
222
|
});
|
|
223
223
|
try {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { a as buildGoogleMeetCalendarDayWindow, i as resolveGoogleMeetGatewayOperationTimeoutMs, o as findGoogleMeetCalendarEvent, s as listGoogleMeetCalendarEvents } from "./config-
|
|
2
|
-
import { d as createGoogleMeetSpace, f as endGoogleMeetActiveConference, g as fetchLatestGoogleMeetConferenceRecord, h as fetchGoogleMeetSpace, m as fetchGoogleMeetAttendance, p as fetchGoogleMeetArtifacts, u as buildGoogleMeetPreflightReport } from "./chrome-create-
|
|
3
|
-
import { buildGoogleMeetAuthUrl, createGoogleMeetOAuthState, createGoogleMeetPkce, exchangeGoogleMeetAuthCode, resolveGoogleMeetAccessToken, waitForGoogleMeetAuthCode } from "./oauth-
|
|
4
|
-
import { hasCreateSpaceConfigInput, resolveCreateSpaceConfig } from "./create-
|
|
1
|
+
import { a as buildGoogleMeetCalendarDayWindow, i as resolveGoogleMeetGatewayOperationTimeoutMs, o as findGoogleMeetCalendarEvent, s as listGoogleMeetCalendarEvents } from "./config-DHJVagqv.js";
|
|
2
|
+
import { d as createGoogleMeetSpace, f as endGoogleMeetActiveConference, g as fetchLatestGoogleMeetConferenceRecord, h as fetchGoogleMeetSpace, m as fetchGoogleMeetAttendance, p as fetchGoogleMeetArtifacts, u as buildGoogleMeetPreflightReport } from "./chrome-create-Bj2SRzJo.js";
|
|
3
|
+
import { buildGoogleMeetAuthUrl, createGoogleMeetOAuthState, createGoogleMeetPkce, exchangeGoogleMeetAuthCode, resolveGoogleMeetAccessToken, waitForGoogleMeetAuthCode } from "./oauth-PrwH5ptn.js";
|
|
4
|
+
import { hasCreateSpaceConfigInput, resolveCreateSpaceConfig } from "./create-DY7DeuqN.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";
|
|
@@ -3,34 +3,69 @@ import { asRecord, normalizeOptionalLowercaseString, normalizeOptionalString, no
|
|
|
3
3
|
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
4
4
|
import { addTimerTimeoutGraceMs, resolvePositiveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
5
5
|
import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, resolveRealtimeVoiceAgentConsultToolPolicy } from "openclaw/plugin-sdk/realtime-voice";
|
|
6
|
+
//#region extensions/google-meet/src/meet-url.ts
|
|
7
|
+
function normalizeOptionalString$1(value) {
|
|
8
|
+
if (typeof value !== "string") return;
|
|
9
|
+
return value.trim() || void 0;
|
|
10
|
+
}
|
|
11
|
+
function normalizeMeetUrl(input) {
|
|
12
|
+
const raw = normalizeOptionalString$1(input);
|
|
13
|
+
if (!raw) throw new Error("url required");
|
|
14
|
+
let url;
|
|
15
|
+
try {
|
|
16
|
+
url = new URL(raw);
|
|
17
|
+
} catch {
|
|
18
|
+
throw new Error("url must be a valid Google Meet URL");
|
|
19
|
+
}
|
|
20
|
+
if (url.protocol !== "https:" || url.hostname.toLowerCase() !== "meet.google.com" || url.port || url.username || url.password) throw new Error("url must be an explicit https://meet.google.com/... URL");
|
|
21
|
+
if (!/^\/[a-z]{3}-[a-z]{4}-[a-z]{3}(?:$|[/?#])/i.test(url.pathname)) throw new Error("url must include a Google Meet meeting code");
|
|
22
|
+
return url.toString();
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
6
25
|
//#region extensions/google-meet/src/calendar.ts
|
|
7
26
|
const GOOGLE_CALENDAR_API_BASE_URL = "https://www.googleapis.com/calendar/v3";
|
|
8
27
|
const GOOGLE_CALENDAR_API_HOST = "www.googleapis.com";
|
|
9
|
-
const GOOGLE_MEET_URL_HOST = "meet.google.com";
|
|
10
28
|
const GOOGLE_CALENDAR_EVENTS_SCOPE = "https://www.googleapis.com/auth/calendar.events.readonly";
|
|
29
|
+
const GOOGLE_CALENDAR_REQUEST_TIMEOUT_MS = 3e4;
|
|
11
30
|
function appendQuery(url, query) {
|
|
12
31
|
const parsed = new URL(url);
|
|
13
32
|
for (const [key, value] of Object.entries(query)) if (value !== void 0) parsed.searchParams.set(key, String(value));
|
|
14
33
|
return parsed.toString();
|
|
15
34
|
}
|
|
16
|
-
function
|
|
17
|
-
if (!value?.trim()) return
|
|
35
|
+
function normalizeGoogleMeetCalendarUri(value) {
|
|
36
|
+
if (!value?.trim()) return;
|
|
18
37
|
try {
|
|
19
|
-
|
|
38
|
+
const url = new URL(value);
|
|
39
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return;
|
|
40
|
+
if (url.hostname.toLowerCase() !== "meet.google.com" || url.port || url.username || url.password) return;
|
|
41
|
+
url.protocol = "https:";
|
|
42
|
+
return normalizeMeetUrl(url.toString());
|
|
20
43
|
} catch {
|
|
21
|
-
return
|
|
44
|
+
return;
|
|
22
45
|
}
|
|
23
46
|
}
|
|
24
47
|
function extractGoogleMeetUriFromText(value) {
|
|
25
|
-
|
|
48
|
+
const matches = value?.matchAll(/https:\/\/meet\.google\.com\/[a-z0-9-]+/gi);
|
|
49
|
+
for (const match of matches ?? []) {
|
|
50
|
+
const uri = normalizeGoogleMeetCalendarUri(match[0]);
|
|
51
|
+
if (uri) return uri;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function findFirstGoogleMeetCalendarUri(entryPoints, predicate = () => true) {
|
|
55
|
+
for (const entry of entryPoints) {
|
|
56
|
+
if (!predicate(entry)) continue;
|
|
57
|
+
const uri = normalizeGoogleMeetCalendarUri(entry.uri);
|
|
58
|
+
if (uri) return uri;
|
|
59
|
+
}
|
|
26
60
|
}
|
|
27
61
|
function extractGoogleMeetUriFromCalendarEvent(event) {
|
|
28
|
-
|
|
62
|
+
const hangoutLink = normalizeGoogleMeetCalendarUri(event.hangoutLink);
|
|
63
|
+
if (hangoutLink) return hangoutLink;
|
|
29
64
|
const entryPoints = event.conferenceData?.entryPoints ?? [];
|
|
30
|
-
const
|
|
31
|
-
if (
|
|
32
|
-
const
|
|
33
|
-
if (
|
|
65
|
+
const videoEntryUri = findFirstGoogleMeetCalendarUri(entryPoints, (entry) => entry.entryPointType === "video");
|
|
66
|
+
if (videoEntryUri) return videoEntryUri;
|
|
67
|
+
const meetEntryUri = findFirstGoogleMeetCalendarUri(entryPoints);
|
|
68
|
+
if (meetEntryUri) return meetEntryUri;
|
|
34
69
|
return extractGoogleMeetUriFromText(event.location) ?? extractGoogleMeetUriFromText(event.description);
|
|
35
70
|
}
|
|
36
71
|
function buildGoogleMeetCalendarDayWindow(now = /* @__PURE__ */ new Date()) {
|
|
@@ -90,7 +125,8 @@ async function fetchGoogleCalendarEvents(params) {
|
|
|
90
125
|
Accept: "application/json"
|
|
91
126
|
} },
|
|
92
127
|
policy: { allowedHostnames: [GOOGLE_CALENDAR_API_HOST] },
|
|
93
|
-
auditContext: "google-meet.calendar.events.list"
|
|
128
|
+
auditContext: "google-meet.calendar.events.list",
|
|
129
|
+
timeoutMs: GOOGLE_CALENDAR_REQUEST_TIMEOUT_MS
|
|
94
130
|
});
|
|
95
131
|
try {
|
|
96
132
|
if (!response.ok) throw await googleApiError({
|
|
@@ -463,4 +499,4 @@ function resolveGoogleMeetConfigWithEnv(input, env = process.env) {
|
|
|
463
499
|
};
|
|
464
500
|
}
|
|
465
501
|
//#endregion
|
|
466
|
-
export { buildGoogleMeetCalendarDayWindow as a, resolveGoogleMeetGatewayOperationTimeoutMs as i, DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND as n, findGoogleMeetCalendarEvent as o, resolveGoogleMeetConfig as r, listGoogleMeetCalendarEvents as s, DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND as t };
|
|
502
|
+
export { buildGoogleMeetCalendarDayWindow as a, normalizeMeetUrl as c, resolveGoogleMeetGatewayOperationTimeoutMs as i, DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND as n, findGoogleMeetCalendarEvent as o, resolveGoogleMeetConfig as r, listGoogleMeetCalendarEvents as s, DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as createGoogleMeetSpace, t as createMeetWithBrowserProxyOnNode } from "./chrome-create-
|
|
2
|
-
import { resolveGoogleMeetAccessToken } from "./oauth-
|
|
1
|
+
import { d as createGoogleMeetSpace, t as createMeetWithBrowserProxyOnNode } from "./chrome-create-Bj2SRzJo.js";
|
|
2
|
+
import { resolveGoogleMeetAccessToken } from "./oauth-PrwH5ptn.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,5 +1,5 @@
|
|
|
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-
|
|
2
|
-
import { a as isSameMeetUrlForReuse, c as resolveChromeNode, f as endGoogleMeetActiveConference, g as fetchLatestGoogleMeetConferenceRecord, h as fetchGoogleMeetSpace, i as callBrowserProxyOnNode, l as resolveChromeNodeInfo, m as fetchGoogleMeetAttendance, n as isGoogleMeetBrowserManualActionError, o as normalizeMeetUrlForReuse, p as fetchGoogleMeetArtifacts, r as asBrowserTabs, s as readBrowserTab, t as createMeetWithBrowserProxyOnNode, u as buildGoogleMeetPreflightReport } from "./chrome-create-
|
|
1
|
+
import { a as buildGoogleMeetCalendarDayWindow, c as normalizeMeetUrl, 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-DHJVagqv.js";
|
|
2
|
+
import { a as isSameMeetUrlForReuse, c as resolveChromeNode, f as endGoogleMeetActiveConference, g as fetchLatestGoogleMeetConferenceRecord, h as fetchGoogleMeetSpace, i as callBrowserProxyOnNode, l as resolveChromeNodeInfo, m as fetchGoogleMeetAttendance, n as isGoogleMeetBrowserManualActionError, o as normalizeMeetUrlForReuse, p as fetchGoogleMeetArtifacts, r as asBrowserTabs, s as readBrowserTab, t as createMeetWithBrowserProxyOnNode, u as buildGoogleMeetPreflightReport } from "./chrome-create-Bj2SRzJo.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";
|
|
@@ -210,8 +210,7 @@ function clearAudio(params) {
|
|
|
210
210
|
};
|
|
211
211
|
}
|
|
212
212
|
function startChrome(params) {
|
|
213
|
-
const url =
|
|
214
|
-
if (!url) throw new Error("url required");
|
|
213
|
+
const url = normalizeMeetUrl(params.url);
|
|
215
214
|
const timeoutMs = readNumber(params.joinTimeoutMs, 3e4);
|
|
216
215
|
const mode = readString$1(params.mode);
|
|
217
216
|
let bridgeId;
|
|
@@ -963,6 +962,8 @@ async function startCommandAgentAudioBridge(params) {
|
|
|
963
962
|
inputProcess.stderr?.on("data", (chunk) => {
|
|
964
963
|
params.logger.debug?.(`[google-meet] audio input: ${String(chunk).trim()}`);
|
|
965
964
|
});
|
|
965
|
+
inputProcess.stdout?.on("error", fail("audio input command stdout"));
|
|
966
|
+
inputProcess.stderr?.on("error", fail("audio input command stderr"));
|
|
966
967
|
outputProcess.on("error", fail("audio output command"));
|
|
967
968
|
outputProcess.stdin?.on?.("error", fail("audio output command"));
|
|
968
969
|
outputProcess.on("exit", (code, signal) => {
|
|
@@ -974,6 +975,7 @@ async function startCommandAgentAudioBridge(params) {
|
|
|
974
975
|
outputProcess.stderr?.on("data", (chunk) => {
|
|
975
976
|
params.logger.debug?.(`[google-meet] audio output: ${String(chunk).trim()}`);
|
|
976
977
|
});
|
|
978
|
+
outputProcess.stderr?.on("error", fail("audio output command stderr"));
|
|
977
979
|
const writeOutputAudio = (audio) => {
|
|
978
980
|
const suppression = recordGoogleMeetOutputActivity({
|
|
979
981
|
tracker: outputActivity,
|
|
@@ -1242,6 +1244,10 @@ async function startCommandRealtimeAudioBridge(params) {
|
|
|
1242
1244
|
proc.stderr?.on("data", (chunk) => {
|
|
1243
1245
|
params.logger.debug?.(`[google-meet] audio output: ${String(chunk).trim()}`);
|
|
1244
1246
|
});
|
|
1247
|
+
proc.stderr?.on("error", (error) => {
|
|
1248
|
+
if (proc !== outputProcess) return;
|
|
1249
|
+
fail("audio output command stderr")(error);
|
|
1250
|
+
});
|
|
1245
1251
|
};
|
|
1246
1252
|
const clearOutputPlayback = () => {
|
|
1247
1253
|
if (stopped) return;
|
|
@@ -1288,9 +1294,15 @@ async function startCommandRealtimeAudioBridge(params) {
|
|
|
1288
1294
|
if (beforeClearCount === clearCount) clearOutputPlayback();
|
|
1289
1295
|
params.logger.debug?.(`[google-meet] human barge-in detected by local input (rms=${Math.round(stats.rms)}, peak=${stats.peak})`);
|
|
1290
1296
|
});
|
|
1297
|
+
bargeInInputProcess.stdout?.on("error", (error) => {
|
|
1298
|
+
params.logger.warn(`[google-meet] human barge-in input stdout failed: ${formatErrorMessage(error)}`);
|
|
1299
|
+
});
|
|
1291
1300
|
bargeInInputProcess.stderr?.on("data", (chunk) => {
|
|
1292
1301
|
params.logger.debug?.(`[google-meet] barge-in input: ${String(chunk).trim()}`);
|
|
1293
1302
|
});
|
|
1303
|
+
bargeInInputProcess.stderr?.on("error", (error) => {
|
|
1304
|
+
params.logger.warn(`[google-meet] human barge-in input stderr failed: ${formatErrorMessage(error)}`);
|
|
1305
|
+
});
|
|
1294
1306
|
bargeInInputProcess.on("error", (error) => {
|
|
1295
1307
|
params.logger.warn(`[google-meet] human barge-in input failed: ${formatErrorMessage(error)}`);
|
|
1296
1308
|
});
|
|
@@ -1309,6 +1321,8 @@ async function startCommandRealtimeAudioBridge(params) {
|
|
|
1309
1321
|
inputProcess.stderr?.on("data", (chunk) => {
|
|
1310
1322
|
params.logger.debug?.(`[google-meet] audio input: ${String(chunk).trim()}`);
|
|
1311
1323
|
});
|
|
1324
|
+
inputProcess.stdout?.on("error", fail("audio input command stdout"));
|
|
1325
|
+
inputProcess.stderr?.on("error", fail("audio input command stderr"));
|
|
1312
1326
|
const resolved = resolveGoogleMeetRealtimeProvider({
|
|
1313
1327
|
config: params.config,
|
|
1314
1328
|
fullConfig: params.fullConfig,
|
|
@@ -3064,19 +3078,6 @@ function nowIso() {
|
|
|
3064
3078
|
function buildTwilioVoiceCallSessionKey(meetingSessionId) {
|
|
3065
3079
|
return `voice:google-meet:${meetingSessionId}`;
|
|
3066
3080
|
}
|
|
3067
|
-
function normalizeMeetUrl(input) {
|
|
3068
|
-
const raw = normalizeOptionalString(input);
|
|
3069
|
-
if (!raw) throw new Error("url required");
|
|
3070
|
-
let url;
|
|
3071
|
-
try {
|
|
3072
|
-
url = new URL(raw);
|
|
3073
|
-
} catch {
|
|
3074
|
-
throw new Error("url must be a valid Google Meet URL");
|
|
3075
|
-
}
|
|
3076
|
-
if (url.protocol !== "https:" || url.hostname.toLowerCase() !== "meet.google.com") throw new Error("url must be an explicit https://meet.google.com/... URL");
|
|
3077
|
-
if (!/^\/[a-z]{3}-[a-z]{4}-[a-z]{3}(?:$|[/?#])/i.test(url.pathname)) throw new Error("url must include a Google Meet meeting code");
|
|
3078
|
-
return url.toString();
|
|
3079
|
-
}
|
|
3080
3081
|
function resolveTransport(input, config) {
|
|
3081
3082
|
return input ?? config.defaultTransport;
|
|
3082
3083
|
}
|
|
@@ -3726,11 +3727,11 @@ var GoogleMeetRuntime = class {
|
|
|
3726
3727
|
let googleMeetCreateModulePromise = null;
|
|
3727
3728
|
let googleMeetCliModulePromise = null;
|
|
3728
3729
|
const loadGoogleMeetCreateModule = async () => {
|
|
3729
|
-
googleMeetCreateModulePromise ??= import("./create-
|
|
3730
|
+
googleMeetCreateModulePromise ??= import("./create-DY7DeuqN.js");
|
|
3730
3731
|
return await googleMeetCreateModulePromise;
|
|
3731
3732
|
};
|
|
3732
3733
|
const loadGoogleMeetCliModule = async () => {
|
|
3733
|
-
googleMeetCliModulePromise ??= import("./cli-
|
|
3734
|
+
googleMeetCliModulePromise ??= import("./cli-2526f6ZI.js");
|
|
3734
3735
|
return await googleMeetCliModulePromise;
|
|
3735
3736
|
};
|
|
3736
3737
|
const googleMeetConfigSchema = {
|
|
@@ -4103,7 +4104,7 @@ async function createAndJoinMeetFromParams(params) {
|
|
|
4103
4104
|
return (await loadGoogleMeetCreateModule()).createAndJoinMeetFromParams(params);
|
|
4104
4105
|
}
|
|
4105
4106
|
async function resolveGoogleMeetTokenFromParams(config, raw) {
|
|
4106
|
-
const { resolveGoogleMeetAccessToken } = await import("./oauth-
|
|
4107
|
+
const { resolveGoogleMeetAccessToken } = await import("./oauth-PrwH5ptn.js");
|
|
4107
4108
|
return resolveGoogleMeetAccessToken({
|
|
4108
4109
|
clientId: normalizeOptionalString(raw.clientId) ?? config.oauth.clientId,
|
|
4109
4110
|
clientSecret: normalizeOptionalString(raw.clientSecret) ?? config.oauth.clientSecret,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { n as readGoogleApiErrorDetail } from "./google-api-errors-CDUYkIcK.js";
|
|
2
2
|
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
3
|
+
import { readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
|
|
3
4
|
import { MAX_DATE_TIMESTAMP_MS, resolveDateTimestampMs, resolveExpiresAtMsFromDurationSeconds } from "openclaw/plugin-sdk/number-runtime";
|
|
4
5
|
import { generateHexPkceVerifierChallenge } from "openclaw/plugin-sdk/provider-auth";
|
|
5
6
|
import { generateOAuthState, parseOAuthCallbackInput, waitForLocalOAuthCallback } from "openclaw/plugin-sdk/provider-auth-runtime";
|
|
@@ -9,6 +10,8 @@ const GOOGLE_MEET_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
|
9
10
|
const GOOGLE_MEET_TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
10
11
|
const GOOGLE_MEET_TOKEN_HOST = "oauth2.googleapis.com";
|
|
11
12
|
const GOOGLE_MEET_DEFAULT_TOKEN_LIFETIME_SECONDS = 3600;
|
|
13
|
+
const GOOGLE_OAUTH_TOKEN_JSON_MAX_BYTES = 256 * 1024;
|
|
14
|
+
const GOOGLE_OAUTH_REQUEST_TIMEOUT_MS = 3e4;
|
|
12
15
|
const GOOGLE_MEET_SCOPES = [
|
|
13
16
|
"https://www.googleapis.com/auth/meetings.space.created",
|
|
14
17
|
"https://www.googleapis.com/auth/meetings.space.readonly",
|
|
@@ -47,14 +50,15 @@ async function executeGoogleTokenRequest(body) {
|
|
|
47
50
|
body
|
|
48
51
|
},
|
|
49
52
|
policy: { allowedHostnames: [GOOGLE_MEET_TOKEN_HOST] },
|
|
50
|
-
auditContext: "google-meet.oauth.token"
|
|
53
|
+
auditContext: "google-meet.oauth.token",
|
|
54
|
+
timeoutMs: GOOGLE_OAUTH_REQUEST_TIMEOUT_MS
|
|
51
55
|
});
|
|
52
56
|
try {
|
|
53
57
|
if (!response.ok) {
|
|
54
58
|
const detail = await readGoogleApiErrorDetail(response);
|
|
55
59
|
throw new Error(`Google OAuth token request failed (${response.status}): ${detail}`);
|
|
56
60
|
}
|
|
57
|
-
const payload = await response
|
|
61
|
+
const payload = await readProviderJsonResponse(response, "Google OAuth token", { maxBytes: GOOGLE_OAUTH_TOKEN_JSON_MAX_BYTES });
|
|
58
62
|
const accessToken = payload.access_token?.trim();
|
|
59
63
|
if (!accessToken) throw new Error("Google OAuth token response was missing access_token");
|
|
60
64
|
return {
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/google-meet",
|
|
3
|
-
"version": "2026.6.
|
|
3
|
+
"version": "2026.6.35",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@openclaw/google-meet",
|
|
9
|
-
"version": "2026.6.
|
|
9
|
+
"version": "2026.6.35",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"commander": "14.0.3",
|
|
12
12
|
"typebox": "1.1.39"
|
|
13
13
|
},
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"openclaw": ">=2026.6.
|
|
15
|
+
"openclaw": ">=2026.6.35"
|
|
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.6.
|
|
3
|
+
"version": "2026.6.35",
|
|
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.6.
|
|
15
|
+
"openclaw": ">=2026.6.35"
|
|
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.6.
|
|
32
|
+
"pluginApi": ">=2026.6.35"
|
|
33
33
|
},
|
|
34
34
|
"build": {
|
|
35
|
-
"openclawVersion": "2026.6.
|
|
35
|
+
"openclawVersion": "2026.6.35"
|
|
36
36
|
},
|
|
37
37
|
"release": {
|
|
38
38
|
"publishToClawHub": true,
|