@openclaw/google-meet 2026.9.5 → 2026.9.7
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/icon.png +0 -0
- package/dist/.setup/{chrome-create-BZRBHJp9.mjs → chrome-create-wuAK5Pnq.mjs} +14 -19
- package/dist/.setup/{cli-MJjnaxoP.mjs → cli-DVDq0TFu.mjs} +27 -695
- package/dist/.setup/cli-export-D4IM6KLJ.mjs +632 -0
- package/dist/.setup/config-BXGAMntj.mjs +240 -0
- package/dist/.setup/{create-sGWmlpgC.mjs → create-UrHOmnWb.mjs} +4 -17
- package/dist/.setup/{google-meet-platform-adapter-DQZ74Kd5.mjs → google-meet-platform-adapter-gosgbMIM.mjs} +337 -228
- package/dist/.setup/{google-meet-platform-constants-Bs5iAg3E.mjs → google-meet-platform-constants-CnRfrYX7.mjs} +1 -4
- package/dist/.setup/{node-host-BOzEP_Us.mjs → node-host-Tr7Mx3da.mjs} +4 -7
- package/dist/.setup/{node-invoke-policy-hwXq9MfV.mjs → node-invoke-policy-Dd3krTYV.mjs} +2 -2
- package/dist/.setup/{oauth-22Ey-zCb.mjs → oauth-BoyruWcS.mjs} +2 -2
- package/dist/.setup/{plugin-helpers-rGjL9QFK.mjs → plugin-helpers-CdQ_YNA7.mjs} +147 -236
- package/dist/.setup/{plugin-registration-CfZbUMDY.mjs → plugin-registration-aCEuCerg.mjs} +59 -16
- package/dist/.setup/{runtime-D_C0dFI1.mjs → runtime-BdiF53A2.mjs} +89 -41
- package/dist/doctor-contract-api.js +3 -6
- package/dist/index.js +54 -13
- package/node_modules/typebox/build/compile/code.mjs +1 -2
- package/node_modules/typebox/build/compile/validator.mjs +5 -1
- package/node_modules/typebox/build/format/iri.mjs +16 -9
- package/node_modules/typebox/build/guard/emit.mjs +2 -2
- package/node_modules/typebox/build/guard/guard.d.mts +7 -5
- package/node_modules/typebox/build/guard/guard.mjs +14 -9
- package/node_modules/typebox/build/guard/index.mjs +6 -0
- package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
- package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
- package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
- package/node_modules/typebox/build/schema/build.mjs +2 -3
- package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
- package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
- package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
- package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
- package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
- package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
- package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
- package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
- package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
- package/node_modules/typebox/build/schema/parse.mjs +3 -0
- package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
- package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
- package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
- package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
- package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
- package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
- package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
- package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
- package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
- package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
- package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +3 -1
- package/package.json +5 -5
- package/dist/.setup/config-C-6enWkx.mjs +0 -328
- package/dist/.setup/google-api-errors-BDYXfKRa.mjs +0 -17
- /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
|
@@ -1,15 +1,346 @@
|
|
|
1
|
-
import { n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-
|
|
1
|
+
import { n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-CnRfrYX7.mjs";
|
|
2
2
|
import { t as normalizeMeetUrl } from "./meet-url-BP2Jlvjs.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-
|
|
4
|
-
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
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-wuAK5Pnq.mjs";
|
|
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";
|
|
7
7
|
import { createMeetingBrowserAudioCaptureSource } from "openclaw/plugin-sdk/meeting-page-script-runtime";
|
|
8
8
|
//#region extensions/google-meet/src/transports/types.ts
|
|
9
9
|
const GOOGLE_MEET_TRANSCRIPT_MAX_LINES = 2e3;
|
|
10
10
|
//#endregion
|
|
11
|
-
//#region extensions/google-meet/src/transports/google-meet-
|
|
11
|
+
//#region extensions/google-meet/src/transports/google-meet-caption-scripts.ts
|
|
12
|
+
const CAPTION_LINE_COMMIT_SOURCE = `
|
|
13
|
+
const captionSelf = (value) => value === true ? "self" : value === false ? "other" : "unknown";
|
|
14
|
+
const captionHistoryKey = (text, ownEcho) => JSON.stringify([text, captionSelf(ownEcho)]);
|
|
15
|
+
const captionObservedEcho = (entry) => entry.provenance?.self === "self" ? true : entry.provenance?.self === "other" ? false : undefined;
|
|
16
|
+
const captionOriginMatches = (entry, row) => {
|
|
17
|
+
if (entry.node === row.node && entry.speaker === row.speaker) return true;
|
|
18
|
+
const previous = captionObservedEcho(entry);
|
|
19
|
+
return previous === undefined || row.ownEcho === undefined || previous === row.ownEcho;
|
|
20
|
+
};
|
|
21
|
+
const captionProvenance = (state, row) => Object.freeze({
|
|
22
|
+
observer: "google-meet-caption-dom",
|
|
23
|
+
observationId: (state.sessionId || "unscoped") + ":" + state.epoch + ":observation:" + (state.nextObservationId = (state.nextObservationId || 0) + 1),
|
|
24
|
+
...(state.sessionId ? { sessionId: state.sessionId } : {}),
|
|
25
|
+
epoch: state.epoch,
|
|
26
|
+
observedAt: new Date(Date.now()).toISOString(),
|
|
27
|
+
...(row.speaker ? { speaker: row.speaker } : {}),
|
|
28
|
+
self: captionSelf(row.ownEcho)
|
|
29
|
+
});
|
|
30
|
+
const captionLine = (entry) => ({
|
|
31
|
+
at: entry.at,
|
|
32
|
+
speaker: entry.speaker,
|
|
33
|
+
text: entry.text,
|
|
34
|
+
...(entry.source ? { source: { ...entry.source } } : {}),
|
|
35
|
+
...(entry.provenance ? { provenance: { ...entry.provenance } } : {})
|
|
36
|
+
});
|
|
37
|
+
const rememberCaptionSource = (state, entry) => {
|
|
38
|
+
if (!entry.source || !state.sourceHistory) return;
|
|
39
|
+
state.sourceRevisions?.set(entry.source.id, Math.max(state.sourceRevisions.get(entry.source.id) || 0, Number(entry.source.revision)));
|
|
40
|
+
// Remember every retained native origin without weakening its sticky source authority.
|
|
41
|
+
const key = captionHistoryKey(entry.text, captionObservedEcho(entry));
|
|
42
|
+
if (state.sourceHistory.has(key) || state.sourceHistory.size < ${GOOGLE_MEET_TRANSCRIPT_MAX_LINES}) {
|
|
43
|
+
state.sourceHistory.set(key, { ...entry.source });
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const reviseCaptionSource = (state, entry, changes) => {
|
|
47
|
+
if (!entry.source) return;
|
|
48
|
+
const revision = Number(entry.source.revision);
|
|
49
|
+
if (revision < (state.sourceRevisions?.get(entry.source.id) || 0)) {
|
|
50
|
+
entry.source = undefined;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
entry.source = { ...entry.source, ...changes, revision: String(revision + 1) };
|
|
54
|
+
};
|
|
55
|
+
const commitLines = (state, entries, stillVisible = []) => {
|
|
56
|
+
state.lines = Array.isArray(state.lines) ? state.lines : [];
|
|
57
|
+
const liveSources = new Set(stillVisible.flatMap((entry) => entry.source ? [entry.source.id] : []));
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
if (entry.source && Number(entry.source.revision) < (state.sourceRevisions?.get(entry.source.id) || 0)) entry.source = undefined;
|
|
60
|
+
if (entry.source && !entry.source.finalized && !liveSources.has(entry.source.id)) {
|
|
61
|
+
reviseCaptionSource(state, entry, { finalized: true });
|
|
62
|
+
}
|
|
63
|
+
rememberCaptionSource(state, entry);
|
|
64
|
+
state.lines.push(captionLine(entry));
|
|
65
|
+
}
|
|
66
|
+
const excess = state.lines.length - ${GOOGLE_MEET_TRANSCRIPT_MAX_LINES};
|
|
67
|
+
if (excess > 0) {
|
|
68
|
+
state.lines.splice(0, excess);
|
|
69
|
+
state.droppedLines = (state.droppedLines || 0) + excess;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
`;
|
|
73
|
+
function meetTranscriptScript(meetingUrl, meetingSessionId, finalize) {
|
|
74
|
+
const expectedMeetingUrl = normalizeMeetUrlForReuse(meetingUrl);
|
|
75
|
+
return `() => {
|
|
76
|
+
const expectedMeetingUrl = ${JSON.stringify(expectedMeetingUrl)};
|
|
77
|
+
const expectedSessionId = ${JSON.stringify(meetingSessionId)};
|
|
78
|
+
let currentMeetingUrl;
|
|
79
|
+
try {
|
|
80
|
+
const currentUrl = new URL(location.href);
|
|
81
|
+
currentMeetingUrl = currentUrl.origin + currentUrl.pathname.toLowerCase().replace(/\\/$/, "");
|
|
82
|
+
} catch {
|
|
83
|
+
return JSON.stringify({ urlMatched: false });
|
|
84
|
+
}
|
|
85
|
+
if (!expectedMeetingUrl || currentMeetingUrl !== expectedMeetingUrl) {
|
|
86
|
+
return JSON.stringify({ urlMatched: false });
|
|
87
|
+
}
|
|
88
|
+
const state = window.__openclawMeetCaptions;
|
|
89
|
+
${CAPTION_LINE_COMMIT_SOURCE}
|
|
90
|
+
if (state?.sessionId && state.sessionId !== expectedSessionId) {
|
|
91
|
+
return JSON.stringify({ urlMatched: true, sessionMatched: false });
|
|
92
|
+
}
|
|
93
|
+
if (${JSON.stringify(finalize)} && Array.isArray(state?.visible) && state.visible.length > 0) {
|
|
94
|
+
if (state.settleTimer !== undefined) clearTimeout(state.settleTimer);
|
|
95
|
+
state.settleTimer = undefined;
|
|
96
|
+
commitLines(state, state.visible);
|
|
97
|
+
state.visible = [];
|
|
98
|
+
}
|
|
99
|
+
const lines = Array.isArray(state?.lines) ? state.lines : [];
|
|
100
|
+
return JSON.stringify({
|
|
101
|
+
urlMatched: true,
|
|
102
|
+
sessionMatched: true,
|
|
103
|
+
epoch: typeof state?.epoch === "string" ? state.epoch : undefined,
|
|
104
|
+
droppedLines: Number.isFinite(state?.droppedLines) ? Math.max(0, Math.trunc(state.droppedLines)) : 0,
|
|
105
|
+
lines: lines.map((line) => ({
|
|
106
|
+
at: typeof line?.at === "string" ? line.at : undefined,
|
|
107
|
+
speaker: typeof line?.speaker === "string" ? line.speaker : undefined,
|
|
108
|
+
text: typeof line?.text === "string" ? line.text : "",
|
|
109
|
+
...(line?.source ? { source: { ...line.source } } : {}),
|
|
110
|
+
...(line?.provenance ? { provenance: { ...line.provenance } } : {})
|
|
111
|
+
})).filter((line) => line.text),
|
|
112
|
+
pendingLines: (Array.isArray(state?.visible) ? state.visible : []).map(captionLine)
|
|
113
|
+
});
|
|
114
|
+
}`;
|
|
115
|
+
}
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region extensions/google-meet/src/transports/google-meet-caption-observer-source.ts
|
|
12
118
|
const GOOGLE_MEET_CAPTION_SETTLE_MS = 1e3;
|
|
119
|
+
const GOOGLE_MEET_CAPTION_OBSERVER_SOURCE = `
|
|
120
|
+
let captioning = false;
|
|
121
|
+
let captionsEnabledAttempted = false;
|
|
122
|
+
let transcriptLines = 0;
|
|
123
|
+
let lastCaptionAt;
|
|
124
|
+
let lastCaptionSpeaker;
|
|
125
|
+
let lastCaptionText;
|
|
126
|
+
let recentTranscript = [];
|
|
127
|
+
const captionSelector = '[role="region"][aria-label*="aption" i], [aria-live="polite"][role="region"], div[aria-live="polite"]';
|
|
128
|
+
const captionState = (() => {
|
|
129
|
+
if (!captureCaptions) return undefined;
|
|
130
|
+
const w = window;
|
|
131
|
+
if (!inCall && !w.__openclawMeetCaptions) return undefined;
|
|
132
|
+
// A reused tab starts a fresh logical transcript for each OpenClaw session.
|
|
133
|
+
// Status refreshes omit the id, so they preserve the active page-owned buffer.
|
|
134
|
+
if (!w.__openclawMeetCaptions || (captionSessionId && w.__openclawMeetCaptions.sessionId !== captionSessionId)) {
|
|
135
|
+
if (w.__openclawMeetCaptions?.settleTimer !== undefined) {
|
|
136
|
+
clearTimeout(w.__openclawMeetCaptions.settleTimer);
|
|
137
|
+
}
|
|
138
|
+
w.__openclawMeetCaptions?.observer?.disconnect?.();
|
|
139
|
+
w.__openclawMeetCaptions = {
|
|
140
|
+
sessionId: captionSessionId,
|
|
141
|
+
// Epochs cross document lifetimes in the runtime transcript cursor.
|
|
142
|
+
// Strong UUIDs keep a reloaded page distinct from its prior buffer.
|
|
143
|
+
epoch: crypto.randomUUID(),
|
|
144
|
+
enabledAttempted: false,
|
|
145
|
+
observerInstalled: false,
|
|
146
|
+
observer: undefined,
|
|
147
|
+
droppedLines: 0,
|
|
148
|
+
nextSourceId: 0,
|
|
149
|
+
nextObservationId: 0,
|
|
150
|
+
sourceNodes: new WeakMap(),
|
|
151
|
+
sourceHistory: new Map(),
|
|
152
|
+
sourceRevisions: new Map(),
|
|
153
|
+
lines: [],
|
|
154
|
+
settleTimer: undefined,
|
|
155
|
+
visible: []
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
return w.__openclawMeetCaptions;
|
|
159
|
+
})();
|
|
160
|
+
const normalizeCaption = (speaker, captionText) => {
|
|
161
|
+
if (!captionState) return;
|
|
162
|
+
const clean = String(captionText || "").replace(/\\s+/g, " ").trim();
|
|
163
|
+
const cleanSpeaker = String(speaker || "").replace(/\\s+/g, " ").trim();
|
|
164
|
+
if (!clean || clean.length < 2) return undefined;
|
|
165
|
+
if (/^(turn on captions|turn off captions|captions)$/i.test(clean)) return undefined;
|
|
166
|
+
return { speaker: cleanSpeaker || undefined, text: clean };
|
|
167
|
+
};
|
|
168
|
+
${CAPTION_LINE_COMMIT_SOURCE}
|
|
169
|
+
const captionOwnEcho = (node) => {
|
|
170
|
+
const marked = node?.closest?.('[data-is-self]') || node;
|
|
171
|
+
const value = marked?.getAttribute?.("data-is-self");
|
|
172
|
+
return value === "true" ? true : value === "false" ? false : undefined;
|
|
173
|
+
};
|
|
174
|
+
const sourceForCaption = (row, continuing) => {
|
|
175
|
+
// Text is only a replay lookup, never the minted identity. Keep the original
|
|
176
|
+
// handle for ambiguous repeated utterances; their transcript entries remain.
|
|
177
|
+
const known = captionState.sourceNodes?.get(row.node);
|
|
178
|
+
const sameLifecycle = known && captionOriginMatches(known, row) && (continuing || known.text === row.text ||
|
|
179
|
+
known.text.startsWith(row.text) || row.text.startsWith(known.text));
|
|
180
|
+
if (sameLifecycle && !known.source) return undefined;
|
|
181
|
+
if (sameLifecycle && known.text !== row.text && known.text.startsWith(row.text)) return undefined;
|
|
182
|
+
const remembered = sameLifecycle ? known.source : captionState.sourceHistory?.get(captionHistoryKey(row.text, row.ownEcho));
|
|
183
|
+
if (remembered) {
|
|
184
|
+
if (Number(remembered.revision) < (captionState.sourceRevisions?.get(remembered.id) || 0)) return undefined;
|
|
185
|
+
return sameLifecycle && known.text !== row.text
|
|
186
|
+
? { ...remembered, revision: String(Number(remembered.revision) + 1), finalized: false }
|
|
187
|
+
: { ...remembered };
|
|
188
|
+
}
|
|
189
|
+
// Missing attribution cannot turn remembered speech into fresh authority.
|
|
190
|
+
const unknown = captionState.sourceHistory?.get(captionHistoryKey(row.text, undefined));
|
|
191
|
+
// A text correction does not resolve the native attribution of its older observation.
|
|
192
|
+
if (unknown || (row.ownEcho === undefined && [true, false].some((self) => captionState.sourceHistory?.has(captionHistoryKey(row.text, self))))) return undefined;
|
|
193
|
+
// At the replay bound, retain row provenance but do not mint new authority.
|
|
194
|
+
if (!captionState.sessionId || !captionState.sourceHistory || row.text.length > 16_384 || captionState.sourceHistory.size >= ${GOOGLE_MEET_TRANSCRIPT_MAX_LINES}) return undefined;
|
|
195
|
+
captionState.nextSourceId += 1;
|
|
196
|
+
return {
|
|
197
|
+
id: captionState.sessionId + ":" + captionState.epoch + ":" + captionState.nextSourceId,
|
|
198
|
+
epoch: captionState.epoch,
|
|
199
|
+
revision: "1",
|
|
200
|
+
finalized: false,
|
|
201
|
+
...(row.ownEcho === undefined ? {} : { ownEcho: row.ownEcho })
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
const scrapeCaptions = () => {
|
|
205
|
+
if (!captionState) return;
|
|
206
|
+
const regions = [...document.querySelectorAll(captionSelector)];
|
|
207
|
+
const rows = [];
|
|
208
|
+
for (const region of regions) {
|
|
209
|
+
const raw = text(region);
|
|
210
|
+
if (!raw) continue;
|
|
211
|
+
const pieces = raw.split(/\\n+/).map((part) => part.trim()).filter(Boolean);
|
|
212
|
+
const row = pieces.length >= 2
|
|
213
|
+
? normalizeCaption(pieces[0], pieces.slice(1).join(" "))
|
|
214
|
+
: normalizeCaption("", pieces[0] || raw);
|
|
215
|
+
if (row) rows.push({ ...row, node: region, ownEcho: captionOwnEcho(region) });
|
|
216
|
+
}
|
|
217
|
+
if (rows.length === 0) {
|
|
218
|
+
// Meet briefly removes caption rows while rerendering. Keep them mutable
|
|
219
|
+
// for one settle window so a DOM gap cannot fabricate a repeated line.
|
|
220
|
+
if (captionState.visible.length > 0 && captionState.settleTimer === undefined) {
|
|
221
|
+
const pendingState = captionState;
|
|
222
|
+
pendingState.settleTimer = setTimeout(() => {
|
|
223
|
+
if (window.__openclawMeetCaptions !== pendingState) return;
|
|
224
|
+
commitLines(pendingState, pendingState.visible);
|
|
225
|
+
pendingState.visible = [];
|
|
226
|
+
pendingState.settleTimer = undefined;
|
|
227
|
+
}, ${GOOGLE_MEET_CAPTION_SETTLE_MS});
|
|
228
|
+
}
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (captionState.settleTimer !== undefined) {
|
|
232
|
+
clearTimeout(captionState.settleTimer);
|
|
233
|
+
captionState.settleTimer = undefined;
|
|
234
|
+
}
|
|
235
|
+
const previous = Array.isArray(captionState.visible) ? captionState.visible : [];
|
|
236
|
+
const unmatchedPrevious = [...previous];
|
|
237
|
+
const nextVisible = [];
|
|
238
|
+
const retired = [];
|
|
239
|
+
const now = Date.now();
|
|
240
|
+
for (let index = 0; index < rows.length; index += 1) {
|
|
241
|
+
const row = rows[index];
|
|
242
|
+
const sameNodeIndex = unmatchedPrevious.findIndex((candidate) => candidate.node === row.node);
|
|
243
|
+
const matchesPrior = (candidate) => {
|
|
244
|
+
const sameTextLifecycle =
|
|
245
|
+
candidate.text === row.text ||
|
|
246
|
+
row.text.startsWith(candidate.text) ||
|
|
247
|
+
candidate.text.startsWith(row.text);
|
|
248
|
+
const sameDomLifecycle =
|
|
249
|
+
candidate.node === row.node || now - candidate.seenAt <= ${GOOGLE_MEET_CAPTION_SETTLE_MS};
|
|
250
|
+
return candidate.speaker === row.speaker && captionOriginMatches(candidate, row) && sameTextLifecycle && sameDomLifecycle;
|
|
251
|
+
};
|
|
252
|
+
const priorIndex = sameNodeIndex >= 0
|
|
253
|
+
? (matchesPrior(unmatchedPrevious[sameNodeIndex]) ? sameNodeIndex : -1)
|
|
254
|
+
: unmatchedPrevious.findIndex(matchesPrior);
|
|
255
|
+
const prior = priorIndex >= 0 ? unmatchedPrevious.splice(priorIndex, 1)[0] : undefined;
|
|
256
|
+
if (prior) {
|
|
257
|
+
if (prior.source && Number(prior.source.revision) < (captionState.sourceRevisions?.get(prior.source.id) || 0)) prior.source = undefined;
|
|
258
|
+
// A shortening often accompanies a DOM redraw; preserve the fuller line.
|
|
259
|
+
const changed = prior.text !== row.text && !prior.text.startsWith(row.text);
|
|
260
|
+
const ownEcho = prior.source?.ownEcho === true || row.ownEcho === true
|
|
261
|
+
? true : prior.source?.ownEcho ?? row.ownEcho;
|
|
262
|
+
if (prior.source && (changed || ownEcho !== prior.source.ownEcho)) {
|
|
263
|
+
reviseCaptionSource(captionState, prior, { finalized: changed ? false : prior.source.finalized, ...(ownEcho === undefined ? {} : { ownEcho }) });
|
|
264
|
+
}
|
|
265
|
+
if (changed || prior.node !== row.node || prior.provenance?.self !== captionSelf(row.ownEcho)) prior.provenance = captionProvenance(captionState, row);
|
|
266
|
+
if (changed) prior.text = row.text;
|
|
267
|
+
prior.node = row.node;
|
|
268
|
+
prior.seenAt = now;
|
|
269
|
+
captionState.sourceNodes?.set(row.node, prior);
|
|
270
|
+
rememberCaptionSource(captionState, prior);
|
|
271
|
+
nextVisible.push(prior);
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
// Keep the transcript's existing non-prefix line boundary, while a reused
|
|
275
|
+
// live DOM row cannot turn a correction into a fresh participation source.
|
|
276
|
+
const continuingIndex = unmatchedPrevious.findIndex((candidate) => candidate.node === row.node);
|
|
277
|
+
const continuing = continuingIndex >= 0 ? unmatchedPrevious.splice(continuingIndex, 1)[0] : undefined;
|
|
278
|
+
if (continuing) retired.push(continuing);
|
|
279
|
+
const entry = {
|
|
280
|
+
at: new Date().toISOString(),
|
|
281
|
+
node: row.node,
|
|
282
|
+
seenAt: now,
|
|
283
|
+
speaker: row.speaker,
|
|
284
|
+
text: row.text,
|
|
285
|
+
source: sourceForCaption(row, Boolean(continuing)),
|
|
286
|
+
provenance: captionProvenance(captionState, row)
|
|
287
|
+
};
|
|
288
|
+
const ownEcho = entry.source?.ownEcho === true || row.ownEcho === true
|
|
289
|
+
? true : entry.source?.ownEcho ?? row.ownEcho;
|
|
290
|
+
if (entry.source && ownEcho !== entry.source.ownEcho) {
|
|
291
|
+
reviseCaptionSource(captionState, entry, { ownEcho });
|
|
292
|
+
}
|
|
293
|
+
captionState.sourceNodes?.set(row.node, entry);
|
|
294
|
+
rememberCaptionSource(captionState, entry);
|
|
295
|
+
nextVisible.push(entry);
|
|
296
|
+
}
|
|
297
|
+
commitLines(captionState, [...retired, ...unmatchedPrevious], nextVisible);
|
|
298
|
+
captionState.visible = nextVisible;
|
|
299
|
+
};
|
|
300
|
+
if (captionState) {
|
|
301
|
+
if (!readOnly && inCall && !captionState.enabledAttempted) {
|
|
302
|
+
const captionButton = findButton(/turn on captions|show captions|captions/i);
|
|
303
|
+
const captionLabel = captionButton ? (captionButton.getAttribute("aria-label") || captionButton.getAttribute("data-tooltip") || text(captionButton)) : "";
|
|
304
|
+
if (captionButton) {
|
|
305
|
+
captionState.enabledAttempted = true;
|
|
306
|
+
captionsEnabledAttempted = true;
|
|
307
|
+
if (!/turn off captions|hide captions/i.test(captionLabel)) {
|
|
308
|
+
captionButton.click();
|
|
309
|
+
notes.push("Attempted to enable Meet captions for observe-only transcript health.");
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
} else if (captionState.enabledAttempted) {
|
|
313
|
+
captionsEnabledAttempted = true;
|
|
314
|
+
}
|
|
315
|
+
if (inCall && !captionState.observerInstalled) {
|
|
316
|
+
captionState.observerInstalled = true;
|
|
317
|
+
captionState.observer = new MutationObserver(scrapeCaptions);
|
|
318
|
+
captionState.observer.observe(document.body, {
|
|
319
|
+
childList: true,
|
|
320
|
+
subtree: true,
|
|
321
|
+
characterData: true,
|
|
322
|
+
attributes: true,
|
|
323
|
+
attributeFilter: ["data-is-self"]
|
|
324
|
+
});
|
|
325
|
+
notes.push("Installed Meet caption observer for observe-only transcript health.");
|
|
326
|
+
}
|
|
327
|
+
if (inCall) {
|
|
328
|
+
scrapeCaptions();
|
|
329
|
+
}
|
|
330
|
+
const committedLines = Array.isArray(captionState.lines) ? captionState.lines : [];
|
|
331
|
+
const visibleLines = Array.isArray(captionState.visible) ? captionState.visible : [];
|
|
332
|
+
const lines = [...committedLines, ...visibleLines];
|
|
333
|
+
const last = lines[lines.length - 1];
|
|
334
|
+
captioning = document.querySelector(captionSelector) !== null || lines.length > 0;
|
|
335
|
+
transcriptLines = (captionState.droppedLines || 0) + lines.length;
|
|
336
|
+
lastCaptionAt = last?.at;
|
|
337
|
+
lastCaptionSpeaker = last?.speaker;
|
|
338
|
+
lastCaptionText = last?.text;
|
|
339
|
+
recentTranscript = lines.slice(-5).map(captionLine);
|
|
340
|
+
}
|
|
341
|
+
`;
|
|
342
|
+
//#endregion
|
|
343
|
+
//#region extensions/google-meet/src/transports/google-meet-page-scripts.ts
|
|
13
344
|
function meetAudioCaptureScript(params) {
|
|
14
345
|
return createMeetingBrowserAudioCaptureSource({
|
|
15
346
|
...params,
|
|
@@ -338,179 +669,7 @@ function meetStatusScript(params) {
|
|
|
338
669
|
if (inCall) {
|
|
339
670
|
await routeMeetAudioOutput();
|
|
340
671
|
}
|
|
341
|
-
|
|
342
|
-
let captionsEnabledAttempted = false;
|
|
343
|
-
let transcriptLines = 0;
|
|
344
|
-
let lastCaptionAt;
|
|
345
|
-
let lastCaptionSpeaker;
|
|
346
|
-
let lastCaptionText;
|
|
347
|
-
let recentTranscript = [];
|
|
348
|
-
const captionSelector = '[role="region"][aria-label*="aption" i], [aria-live="polite"][role="region"], div[aria-live="polite"]';
|
|
349
|
-
const captionState = (() => {
|
|
350
|
-
if (!captureCaptions) return undefined;
|
|
351
|
-
const w = window;
|
|
352
|
-
if (!inCall && !w.__openclawMeetCaptions) return undefined;
|
|
353
|
-
// A reused tab starts a fresh logical transcript for each OpenClaw session.
|
|
354
|
-
// Status refreshes omit the id, so they preserve the active page-owned buffer.
|
|
355
|
-
if (!w.__openclawMeetCaptions || (captionSessionId && w.__openclawMeetCaptions.sessionId !== captionSessionId)) {
|
|
356
|
-
if (w.__openclawMeetCaptions?.settleTimer !== undefined) {
|
|
357
|
-
clearTimeout(w.__openclawMeetCaptions.settleTimer);
|
|
358
|
-
}
|
|
359
|
-
w.__openclawMeetCaptions?.observer?.disconnect?.();
|
|
360
|
-
w.__openclawMeetCaptions = {
|
|
361
|
-
sessionId: captionSessionId,
|
|
362
|
-
// Epochs cross document lifetimes in the runtime transcript cursor.
|
|
363
|
-
// Strong UUIDs keep a reloaded page distinct from its prior buffer.
|
|
364
|
-
epoch: crypto.randomUUID(),
|
|
365
|
-
enabledAttempted: false,
|
|
366
|
-
observerInstalled: false,
|
|
367
|
-
observer: undefined,
|
|
368
|
-
droppedLines: 0,
|
|
369
|
-
lines: [],
|
|
370
|
-
settleTimer: undefined,
|
|
371
|
-
visible: []
|
|
372
|
-
};
|
|
373
|
-
}
|
|
374
|
-
return w.__openclawMeetCaptions;
|
|
375
|
-
})();
|
|
376
|
-
const normalizeCaption = (speaker, captionText) => {
|
|
377
|
-
if (!captionState) return;
|
|
378
|
-
const clean = String(captionText || "").replace(/\\s+/g, " ").trim();
|
|
379
|
-
const cleanSpeaker = String(speaker || "").replace(/\\s+/g, " ").trim();
|
|
380
|
-
if (!clean || clean.length < 2) return undefined;
|
|
381
|
-
if (/^(turn on captions|turn off captions|captions)$/i.test(clean)) return undefined;
|
|
382
|
-
return { speaker: cleanSpeaker || undefined, text: clean };
|
|
383
|
-
};
|
|
384
|
-
const commitLines = (state, entries) => {
|
|
385
|
-
state.lines.push(...entries.map((entry) => ({
|
|
386
|
-
at: entry.at,
|
|
387
|
-
speaker: entry.speaker,
|
|
388
|
-
text: entry.text
|
|
389
|
-
})));
|
|
390
|
-
const excess = state.lines.length - ${GOOGLE_MEET_TRANSCRIPT_MAX_LINES};
|
|
391
|
-
if (excess > 0) {
|
|
392
|
-
state.lines.splice(0, excess);
|
|
393
|
-
state.droppedLines = (state.droppedLines || 0) + excess;
|
|
394
|
-
}
|
|
395
|
-
};
|
|
396
|
-
const scrapeCaptions = () => {
|
|
397
|
-
if (!captionState) return;
|
|
398
|
-
const regions = [...document.querySelectorAll(captionSelector)];
|
|
399
|
-
const rows = [];
|
|
400
|
-
for (const region of regions) {
|
|
401
|
-
const raw = text(region);
|
|
402
|
-
if (!raw) continue;
|
|
403
|
-
const pieces = raw.split(/\\n+/).map((part) => part.trim()).filter(Boolean);
|
|
404
|
-
const row = pieces.length >= 2
|
|
405
|
-
? normalizeCaption(pieces[0], pieces.slice(1).join(" "))
|
|
406
|
-
: normalizeCaption("", pieces[0] || raw);
|
|
407
|
-
if (row) rows.push({ ...row, node: region });
|
|
408
|
-
}
|
|
409
|
-
if (rows.length === 0) {
|
|
410
|
-
// Meet briefly removes caption rows while rerendering. Keep them mutable
|
|
411
|
-
// for one settle window so a DOM gap cannot fabricate a repeated line.
|
|
412
|
-
if (captionState.visible.length > 0 && captionState.settleTimer === undefined) {
|
|
413
|
-
const pendingState = captionState;
|
|
414
|
-
pendingState.settleTimer = setTimeout(() => {
|
|
415
|
-
if (window.__openclawMeetCaptions !== pendingState) return;
|
|
416
|
-
commitLines(pendingState, pendingState.visible);
|
|
417
|
-
pendingState.visible = [];
|
|
418
|
-
pendingState.settleTimer = undefined;
|
|
419
|
-
}, ${GOOGLE_MEET_CAPTION_SETTLE_MS});
|
|
420
|
-
}
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
if (captionState.settleTimer !== undefined) {
|
|
424
|
-
clearTimeout(captionState.settleTimer);
|
|
425
|
-
captionState.settleTimer = undefined;
|
|
426
|
-
}
|
|
427
|
-
const previous = Array.isArray(captionState.visible) ? captionState.visible : [];
|
|
428
|
-
const unmatchedPrevious = [...previous];
|
|
429
|
-
const nextVisible = [];
|
|
430
|
-
const now = Date.now();
|
|
431
|
-
for (let index = 0; index < rows.length; index += 1) {
|
|
432
|
-
const row = rows[index];
|
|
433
|
-
const priorIndex = unmatchedPrevious.findIndex((candidate) => {
|
|
434
|
-
const sameTextLifecycle =
|
|
435
|
-
candidate.text === row.text ||
|
|
436
|
-
row.text.startsWith(candidate.text) ||
|
|
437
|
-
candidate.text.startsWith(row.text);
|
|
438
|
-
const sameDomLifecycle =
|
|
439
|
-
candidate.node === row.node || now - candidate.seenAt <= ${GOOGLE_MEET_CAPTION_SETTLE_MS};
|
|
440
|
-
return candidate.speaker === row.speaker && sameTextLifecycle && sameDomLifecycle;
|
|
441
|
-
});
|
|
442
|
-
const prior = priorIndex >= 0 ? unmatchedPrevious.splice(priorIndex, 1)[0] : undefined;
|
|
443
|
-
const sameSpeaker = Boolean(prior) && prior.speaker === row.speaker;
|
|
444
|
-
if (sameSpeaker && prior.text === row.text) {
|
|
445
|
-
prior.node = row.node;
|
|
446
|
-
prior.seenAt = now;
|
|
447
|
-
nextVisible.push(prior);
|
|
448
|
-
continue;
|
|
449
|
-
}
|
|
450
|
-
if (sameSpeaker && row.text.startsWith(prior.text)) {
|
|
451
|
-
prior.text = row.text;
|
|
452
|
-
prior.node = row.node;
|
|
453
|
-
prior.seenAt = now;
|
|
454
|
-
nextVisible.push(prior);
|
|
455
|
-
continue;
|
|
456
|
-
}
|
|
457
|
-
if (sameSpeaker && prior.text.startsWith(row.text)) {
|
|
458
|
-
prior.node = row.node;
|
|
459
|
-
prior.seenAt = now;
|
|
460
|
-
nextVisible.push(prior);
|
|
461
|
-
continue;
|
|
462
|
-
}
|
|
463
|
-
const entry = {
|
|
464
|
-
at: new Date().toISOString(),
|
|
465
|
-
node: row.node,
|
|
466
|
-
seenAt: now,
|
|
467
|
-
speaker: row.speaker,
|
|
468
|
-
text: row.text
|
|
469
|
-
};
|
|
470
|
-
nextVisible.push(entry);
|
|
471
|
-
}
|
|
472
|
-
commitLines(captionState, unmatchedPrevious);
|
|
473
|
-
captionState.visible = nextVisible;
|
|
474
|
-
};
|
|
475
|
-
if (captionState) {
|
|
476
|
-
if (!readOnly && inCall && !captionState.enabledAttempted) {
|
|
477
|
-
const captionButton = findButton(/turn on captions|show captions|captions/i);
|
|
478
|
-
const captionLabel = captionButton ? (captionButton.getAttribute("aria-label") || captionButton.getAttribute("data-tooltip") || text(captionButton)) : "";
|
|
479
|
-
if (captionButton) {
|
|
480
|
-
captionState.enabledAttempted = true;
|
|
481
|
-
captionsEnabledAttempted = true;
|
|
482
|
-
if (!/turn off captions|hide captions/i.test(captionLabel)) {
|
|
483
|
-
captionButton.click();
|
|
484
|
-
notes.push("Attempted to enable Meet captions for observe-only transcript health.");
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
} else if (captionState.enabledAttempted) {
|
|
488
|
-
captionsEnabledAttempted = true;
|
|
489
|
-
}
|
|
490
|
-
if (inCall && !captionState.observerInstalled) {
|
|
491
|
-
captionState.observerInstalled = true;
|
|
492
|
-
captionState.observer = new MutationObserver(scrapeCaptions);
|
|
493
|
-
captionState.observer.observe(document.body, {
|
|
494
|
-
childList: true,
|
|
495
|
-
subtree: true,
|
|
496
|
-
characterData: true
|
|
497
|
-
});
|
|
498
|
-
notes.push("Installed Meet caption observer for observe-only transcript health.");
|
|
499
|
-
}
|
|
500
|
-
if (inCall) {
|
|
501
|
-
scrapeCaptions();
|
|
502
|
-
}
|
|
503
|
-
const committedLines = Array.isArray(captionState.lines) ? captionState.lines : [];
|
|
504
|
-
const visibleLines = Array.isArray(captionState.visible) ? captionState.visible : [];
|
|
505
|
-
const lines = [...committedLines, ...visibleLines];
|
|
506
|
-
const last = lines[lines.length - 1];
|
|
507
|
-
captioning = document.querySelector(captionSelector) !== null || lines.length > 0;
|
|
508
|
-
transcriptLines = (captionState.droppedLines || 0) + lines.length;
|
|
509
|
-
lastCaptionAt = last?.at;
|
|
510
|
-
lastCaptionSpeaker = last?.speaker;
|
|
511
|
-
lastCaptionText = last?.text;
|
|
512
|
-
recentTranscript = lines.slice(-5);
|
|
513
|
-
}
|
|
672
|
+
${GOOGLE_MEET_CAPTION_OBSERVER_SOURCE}
|
|
514
673
|
const lobbyWaiting = !inCall && /asking to be let in|you.?ll join when someone lets you in|waiting to be let in|ask to join/i.test(pageText);
|
|
515
674
|
const leaveReason = !inCall && /you left the meeting|you.?ve left the meeting|removed from the meeting|you were removed|call ended|meeting ended/i.test(pageText)
|
|
516
675
|
? pageText.match(/you left the meeting|you.?ve left the meeting|removed from the meeting|you were removed|call ended|meeting ended/i)?.[0]
|
|
@@ -559,55 +718,6 @@ function meetStatusScript(params) {
|
|
|
559
718
|
});
|
|
560
719
|
}`;
|
|
561
720
|
}
|
|
562
|
-
function meetTranscriptScript(meetingUrl, meetingSessionId, finalize) {
|
|
563
|
-
const expectedMeetingUrl = normalizeMeetUrlForReuse(meetingUrl);
|
|
564
|
-
return `() => {
|
|
565
|
-
const expectedMeetingUrl = ${JSON.stringify(expectedMeetingUrl)};
|
|
566
|
-
const expectedSessionId = ${JSON.stringify(meetingSessionId)};
|
|
567
|
-
let currentMeetingUrl;
|
|
568
|
-
try {
|
|
569
|
-
const currentUrl = new URL(location.href);
|
|
570
|
-
currentMeetingUrl = currentUrl.origin + currentUrl.pathname.toLowerCase().replace(/\\/$/, "");
|
|
571
|
-
} catch {
|
|
572
|
-
return JSON.stringify({ urlMatched: false });
|
|
573
|
-
}
|
|
574
|
-
if (!expectedMeetingUrl || currentMeetingUrl !== expectedMeetingUrl) {
|
|
575
|
-
return JSON.stringify({ urlMatched: false });
|
|
576
|
-
}
|
|
577
|
-
const state = window.__openclawMeetCaptions;
|
|
578
|
-
if (state?.sessionId && state.sessionId !== expectedSessionId) {
|
|
579
|
-
return JSON.stringify({ urlMatched: true, sessionMatched: false });
|
|
580
|
-
}
|
|
581
|
-
if (${JSON.stringify(finalize)} && Array.isArray(state?.visible) && state.visible.length > 0) {
|
|
582
|
-
if (state.settleTimer !== undefined) clearTimeout(state.settleTimer);
|
|
583
|
-
state.settleTimer = undefined;
|
|
584
|
-
state.lines = Array.isArray(state.lines) ? state.lines : [];
|
|
585
|
-
state.lines.push(...state.visible.map((entry) => ({
|
|
586
|
-
at: entry.at,
|
|
587
|
-
speaker: entry.speaker,
|
|
588
|
-
text: entry.text
|
|
589
|
-
})));
|
|
590
|
-
state.visible = [];
|
|
591
|
-
const excess = state.lines.length - ${GOOGLE_MEET_TRANSCRIPT_MAX_LINES};
|
|
592
|
-
if (excess > 0) {
|
|
593
|
-
state.lines.splice(0, excess);
|
|
594
|
-
state.droppedLines = (state.droppedLines || 0) + excess;
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
const lines = Array.isArray(state?.lines) ? state.lines : [];
|
|
598
|
-
return JSON.stringify({
|
|
599
|
-
urlMatched: true,
|
|
600
|
-
sessionMatched: true,
|
|
601
|
-
epoch: typeof state?.epoch === "string" ? state.epoch : undefined,
|
|
602
|
-
droppedLines: Number.isFinite(state?.droppedLines) ? Math.max(0, Math.trunc(state.droppedLines)) : 0,
|
|
603
|
-
lines: lines.map((line) => ({
|
|
604
|
-
at: typeof line?.at === "string" ? line.at : undefined,
|
|
605
|
-
speaker: typeof line?.speaker === "string" ? line.speaker : undefined,
|
|
606
|
-
text: typeof line?.text === "string" ? line.text : ""
|
|
607
|
-
})).filter((line) => line.text)
|
|
608
|
-
});
|
|
609
|
-
}`;
|
|
610
|
-
}
|
|
611
721
|
function meetLeaveScript(meetingUrl) {
|
|
612
722
|
const expectedMeetingUrl = normalizeMeetUrlForReuse(meetingUrl);
|
|
613
723
|
return `() => {
|
|
@@ -700,8 +810,7 @@ function prefixDtmfWait(sequence, delayMs) {
|
|
|
700
810
|
//#endregion
|
|
701
811
|
//#region extensions/google-meet/src/transports/google-meet-platform-adapter.ts
|
|
702
812
|
function parsePermissionGrantNotes(result) {
|
|
703
|
-
const
|
|
704
|
-
const unsupportedPermissions = Array.isArray(record.unsupportedPermissions) ? record.unsupportedPermissions.filter((value) => typeof value === "string") : [];
|
|
813
|
+
const unsupportedPermissions = filterStringEntries(asRecord(result).unsupportedPermissions);
|
|
705
814
|
const notes = ["Granted Meet microphone/camera permissions through browser control."];
|
|
706
815
|
if (unsupportedPermissions.includes("speakerSelection")) notes.push("Chrome did not accept the optional Meet speaker-selection permission.");
|
|
707
816
|
return notes;
|
|
@@ -10,9 +10,6 @@ var GoogleMeetBrowserManualActionError = class extends Error {
|
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
};
|
|
13
|
-
function isGoogleMeetBrowserManualActionError(error) {
|
|
14
|
-
return error instanceof GoogleMeetBrowserManualActionError;
|
|
15
|
-
}
|
|
16
13
|
//#endregion
|
|
17
14
|
//#region extensions/google-meet/src/transports/google-meet-platform-constants.ts
|
|
18
15
|
const GOOGLE_MEET_NODE_COMMAND = "googlemeet.chrome";
|
|
@@ -22,4 +19,4 @@ const GOOGLE_MEET_BROWSER_NODE_ADAPTER = {
|
|
|
22
19
|
nodeConfigPath: "plugins.entries.google-meet.config.chromeNode.node"
|
|
23
20
|
};
|
|
24
21
|
//#endregion
|
|
25
|
-
export {
|
|
22
|
+
export { GOOGLE_MEET_NODE_COMMAND as n, GoogleMeetBrowserManualActionError as r, GOOGLE_MEET_BROWSER_NODE_ADAPTER as t };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-
|
|
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-
|
|
1
|
+
import { n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-CnRfrYX7.mjs";
|
|
2
|
+
import { n as DEFAULT_GOOGLE_MEET_AUDIO_OUTPUT_COMMAND, t as DEFAULT_GOOGLE_MEET_AUDIO_INPUT_COMMAND } from "./config-BXGAMntj.mjs";
|
|
3
|
+
import { t as GOOGLE_MEET_PLATFORM_ADAPTER } from "./google-meet-platform-adapter-gosgbMIM.mjs";
|
|
4
4
|
import { MeetingPlatformAdapter } from "openclaw/plugin-sdk/meeting-runtime";
|
|
5
5
|
//#region extensions/google-meet/src/node-host.ts
|
|
6
6
|
function normalizeMeetKey(value) {
|
|
@@ -13,7 +13,7 @@ function normalizeMeetKey(value) {
|
|
|
13
13
|
return value;
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
const
|
|
16
|
+
const handleGoogleMeetNodeHostCommand = MeetingPlatformAdapter.createNodeHostHandler({
|
|
17
17
|
commandName: GOOGLE_MEET_NODE_COMMAND,
|
|
18
18
|
displayName: "Google Meet",
|
|
19
19
|
browserLabel: "Meet",
|
|
@@ -42,8 +42,5 @@ const googleMeetNodeHost = MeetingPlatformAdapter.createNodeHostHandler({
|
|
|
42
42
|
openedNotes: ["Browser page control is handled by OpenClaw browser automation when using chrome-node."]
|
|
43
43
|
}
|
|
44
44
|
});
|
|
45
|
-
async function handleGoogleMeetNodeHostCommand(paramsJSON) {
|
|
46
|
-
return await googleMeetNodeHost(paramsJSON);
|
|
47
|
-
}
|
|
48
45
|
//#endregion
|
|
49
46
|
export { handleGoogleMeetNodeHostCommand };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-
|
|
2
|
-
import { t as GOOGLE_MEET_PLATFORM_ADAPTER } from "./google-meet-platform-adapter-
|
|
1
|
+
import { n as GOOGLE_MEET_NODE_COMMAND } from "./google-meet-platform-constants-CnRfrYX7.mjs";
|
|
2
|
+
import { t as GOOGLE_MEET_PLATFORM_ADAPTER } from "./google-meet-platform-adapter-gosgbMIM.mjs";
|
|
3
3
|
import { createMeetingBrowserNodeInvokePolicy } from "openclaw/plugin-sdk/meeting-runtime";
|
|
4
4
|
//#region extensions/google-meet/src/node-invoke-policy.ts
|
|
5
5
|
const GOOGLE_MEET_CHROME_NODE_COMMAND = GOOGLE_MEET_NODE_COMMAND;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { g as readGoogleApiErrorDetail } from "./plugin-helpers-CdQ_YNA7.mjs";
|
|
2
2
|
import { MAX_DATE_TIMESTAMP_MS, resolveDateTimestampMs, resolveExpiresAtMsFromDurationSeconds } from "openclaw/plugin-sdk/number-runtime";
|
|
3
|
-
import { parseOAuthCallbackInput, waitForLocalOAuthCallback } from "openclaw/plugin-sdk/provider-auth-runtime";
|
|
4
3
|
import { readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
|
|
5
4
|
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
5
|
+
import { parseOAuthCallbackInput, waitForLocalOAuthCallback } from "openclaw/plugin-sdk/provider-auth-runtime";
|
|
6
6
|
//#region extensions/google-meet/src/oauth.ts
|
|
7
7
|
const GOOGLE_MEET_REDIRECT_URI = "http://localhost:8085/oauth2callback";
|
|
8
8
|
const GOOGLE_MEET_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|