@openclaw/zoom-meetings 2026.8.1-beta.2 → 2026.8.1-beta.3
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/index.js +40 -225
- package/openclaw.plugin.json +7 -0
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { n as zoomMeetingsInvalidRequest, r as zoomMeetingsConfig, t as ZoomMeet
|
|
|
2
2
|
import { MeetingPlatformAdapter } from "openclaw/plugin-sdk/meeting-runtime";
|
|
3
3
|
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
|
4
4
|
import { Type } from "typebox";
|
|
5
|
+
import { createMeetingLeaveSource, createMeetingTranscriptSource } from "openclaw/plugin-sdk/meeting-page-script-runtime";
|
|
5
6
|
//#region extensions/zoom-meetings/src/transports/zoom-meetings-selectors.ts
|
|
6
7
|
const ZOOM_MEETING_SELECTORS = {
|
|
7
8
|
continueInBrowser: [],
|
|
@@ -622,7 +623,6 @@ function isRecoverableZoomMeetingTab(tab, url) {
|
|
|
622
623
|
}
|
|
623
624
|
//#endregion
|
|
624
625
|
//#region extensions/zoom-meetings/src/transports/zoom-meetings-page-scripts.ts
|
|
625
|
-
const ZOOM_MEETING_TRANSCRIPT_MAX_LINES = 500;
|
|
626
626
|
function pageIdentityFunctionSource() {
|
|
627
627
|
return `const meetingIdentity = (rawUrl) => {
|
|
628
628
|
try {
|
|
@@ -680,168 +680,23 @@ function zoomMeetingStatusScript(params) {
|
|
|
680
680
|
}) + zoomMeetingStatusCallSource();
|
|
681
681
|
}
|
|
682
682
|
function zoomMeetingTranscriptScript(meetingUrl, meetingSessionId, finalize) {
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
: archivedCaptions;
|
|
696
|
-
// A same-session finalized buffer belongs to the departed call even if Zoom
|
|
697
|
-
// immediately navigated this tab into another meeting before transcript pickup.
|
|
698
|
-
const useFinalizedCaptions = Boolean(
|
|
699
|
-
captions?.finalized === true &&
|
|
700
|
-
captions?.identity === expectedIdentity &&
|
|
701
|
-
(!captions?.sessionId || captions.sessionId === expectedSessionId)
|
|
702
|
-
);
|
|
703
|
-
const effectiveIdentity = useFinalizedCaptions
|
|
704
|
-
? captions.identity
|
|
705
|
-
: currentIdentity || state?.identity || captions?.identity;
|
|
706
|
-
if (!expectedIdentity || effectiveIdentity !== expectedIdentity) {
|
|
707
|
-
return JSON.stringify({ urlMatched: false, droppedLines: 0, lines: [] });
|
|
708
|
-
}
|
|
709
|
-
if (!useFinalizedCaptions && state?.sessionId && state.sessionId !== expectedSessionId) {
|
|
710
|
-
return JSON.stringify({ urlMatched: true, sessionMatched: false, droppedLines: 0, lines: [] });
|
|
711
|
-
}
|
|
712
|
-
if (captions?.sessionId && captions.sessionId !== expectedSessionId) {
|
|
713
|
-
return JSON.stringify({ urlMatched: true, sessionMatched: false, droppedLines: 0, lines: [] });
|
|
714
|
-
}
|
|
715
|
-
if (${JSON.stringify(finalize)} && Array.isArray(captions?.visible) && captions.visible.length > 0) {
|
|
716
|
-
if (captions.settleTimer !== undefined) clearTimeout(captions.settleTimer);
|
|
717
|
-
captions.settleTimer = undefined;
|
|
718
|
-
captions.lines = Array.isArray(captions.lines) ? captions.lines : [];
|
|
719
|
-
captions.lines.push(...captions.visible.map((entry) => ({
|
|
720
|
-
at: entry.at,
|
|
721
|
-
speaker: entry.speaker,
|
|
722
|
-
text: entry.text,
|
|
723
|
-
})));
|
|
724
|
-
captions.visible = [];
|
|
725
|
-
const excess = captions.lines.length - ${ZOOM_MEETING_TRANSCRIPT_MAX_LINES};
|
|
726
|
-
if (excess > 0) {
|
|
727
|
-
captions.lines.splice(0, excess);
|
|
728
|
-
captions.droppedLines = (captions.droppedLines || 0) + excess;
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
if (${JSON.stringify(finalize)} && captions) {
|
|
732
|
-
if (captions.settleTimer !== undefined) clearTimeout(captions.settleTimer);
|
|
733
|
-
captions.settleTimer = undefined;
|
|
734
|
-
captions.observer?.disconnect?.();
|
|
735
|
-
captions.observer = undefined;
|
|
736
|
-
captions.observerInstalled = false;
|
|
737
|
-
captions.identity = expectedIdentity;
|
|
738
|
-
captions.finalized = true;
|
|
739
|
-
captions.finalizedAt = Date.now();
|
|
740
|
-
}
|
|
741
|
-
const allLines = [
|
|
742
|
-
...(Array.isArray(captions?.lines) ? captions.lines : []),
|
|
743
|
-
...(${JSON.stringify(finalize)} || !Array.isArray(captions?.visible) ? [] : captions.visible),
|
|
744
|
-
];
|
|
745
|
-
const visibleOverflow = Math.max(0, allLines.length - ${ZOOM_MEETING_TRANSCRIPT_MAX_LINES});
|
|
746
|
-
const lines = allLines.slice(-${ZOOM_MEETING_TRANSCRIPT_MAX_LINES});
|
|
747
|
-
const result = {
|
|
748
|
-
urlMatched: true,
|
|
749
|
-
sessionMatched: true,
|
|
750
|
-
epoch: typeof captions?.epoch === "string" ? captions.epoch : undefined,
|
|
751
|
-
droppedLines: (Number.isFinite(captions?.droppedLines)
|
|
752
|
-
? Math.max(0, Math.trunc(captions.droppedLines))
|
|
753
|
-
: 0) + visibleOverflow,
|
|
754
|
-
lines: lines.map((line) => ({
|
|
755
|
-
at: typeof line?.at === "string" ? line.at : undefined,
|
|
756
|
-
speaker: typeof line?.speaker === "string" ? line.speaker : undefined,
|
|
757
|
-
text: typeof line?.text === "string" ? line.text : "",
|
|
758
|
-
})).filter((line) => line.text),
|
|
759
|
-
};
|
|
760
|
-
return JSON.stringify(result);
|
|
761
|
-
}`;
|
|
683
|
+
return createMeetingTranscriptSource({
|
|
684
|
+
expectedIdentity: normalizeZoomMeetingUrlForReuse(meetingUrl),
|
|
685
|
+
finalize,
|
|
686
|
+
globals: {
|
|
687
|
+
captionArchive: "__openclawZoomCaptionArchive",
|
|
688
|
+
captions: "__openclawZoomCaptions",
|
|
689
|
+
meeting: "__openclawZoomMeeting"
|
|
690
|
+
},
|
|
691
|
+
meetingSessionId,
|
|
692
|
+
pageIdentitySource: pageIdentityFunctionSource(),
|
|
693
|
+
platformDisplayName: "Zoom"
|
|
694
|
+
});
|
|
762
695
|
}
|
|
763
696
|
function zoomMeetingLeaveScript(params) {
|
|
764
697
|
const selectors = JSON.stringify(ZOOM_MEETING_SELECTORS);
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
${pageIdentityFunctionSource()}
|
|
768
|
-
const topDocument = globalThis.document;
|
|
769
|
-
const document = topDocument.querySelector("#webclient")?.contentDocument || topDocument;
|
|
770
|
-
const selectors = ${selectors};
|
|
771
|
-
const expectedIdentity = ${JSON.stringify(expectedIdentity)};
|
|
772
|
-
const expectedSessionId = ${JSON.stringify(params.meetingSessionId)};
|
|
773
|
-
const leaveInitiated = ${JSON.stringify(params.leaveInitiated)};
|
|
774
|
-
const currentIdentity = meetingIdentity(location.href);
|
|
775
|
-
const state = window.__openclawZoomMeeting;
|
|
776
|
-
const enforceSessionOwnership = Boolean(expectedSessionId);
|
|
777
|
-
if (enforceSessionOwnership && state?.sessionId && state.sessionId !== expectedSessionId) {
|
|
778
|
-
return JSON.stringify({ departed: false, sessionConflict: true, sessionMatched: false, urlMatched: true });
|
|
779
|
-
}
|
|
780
|
-
const sessionAdoptedFromUrl = Boolean(
|
|
781
|
-
enforceSessionOwnership &&
|
|
782
|
-
!state?.sessionId &&
|
|
783
|
-
currentIdentity === expectedIdentity &&
|
|
784
|
-
(!state?.identity || state.identity === expectedIdentity)
|
|
785
|
-
);
|
|
786
|
-
const sessionMatched = !enforceSessionOwnership ||
|
|
787
|
-
state?.sessionId === expectedSessionId ||
|
|
788
|
-
sessionAdoptedFromUrl;
|
|
789
|
-
const retainedLeaveOwnership = Boolean(!sessionMatched && leaveInitiated);
|
|
790
|
-
if (!sessionMatched && !retainedLeaveOwnership) {
|
|
791
|
-
return JSON.stringify({ departed: false, sessionMatched: false, urlMatched: true });
|
|
792
|
-
}
|
|
793
|
-
const retireOwnedAudioBridges = () => {
|
|
794
|
-
const entries = Array.isArray(window.__openclawZoomAudioOutputs)
|
|
795
|
-
? window.__openclawZoomAudioOutputs
|
|
796
|
-
: [];
|
|
797
|
-
const retained = [];
|
|
798
|
-
const activeSessionId = expectedSessionId || state?.sessionId;
|
|
799
|
-
for (const entry of entries) {
|
|
800
|
-
const ownedByActiveSession = Boolean(
|
|
801
|
-
!entry?.sessionId || (activeSessionId && entry.sessionId === activeSessionId)
|
|
802
|
-
);
|
|
803
|
-
if (!ownedByActiveSession) {
|
|
804
|
-
retained.push(entry);
|
|
805
|
-
continue;
|
|
806
|
-
}
|
|
807
|
-
const mediaSourceUrl = (element) => String(element?.currentSrc || element?.src || "");
|
|
808
|
-
const sources = Array.isArray(entry?.sources)
|
|
809
|
-
? entry.sources
|
|
810
|
-
: entry?.source
|
|
811
|
-
? [{ element: entry.source, muted: Boolean(entry.sourceMuted), stream: entry.stream, url: entry.sourceUrl }]
|
|
812
|
-
: [];
|
|
813
|
-
for (const source of sources) {
|
|
814
|
-
const element = source?.element;
|
|
815
|
-
const sourceMatches = source?.stream || element?.srcObject
|
|
816
|
-
? element?.srcObject === source?.stream
|
|
817
|
-
: Boolean(source?.url && mediaSourceUrl(element) === source.url);
|
|
818
|
-
const sourceIsEmpty = Boolean(element && !element.srcObject && !mediaSourceUrl(element));
|
|
819
|
-
if (!element) continue;
|
|
820
|
-
if (sourceIsEmpty) {
|
|
821
|
-
element.muted = true;
|
|
822
|
-
continue;
|
|
823
|
-
}
|
|
824
|
-
if (!sourceMatches) continue;
|
|
825
|
-
const detachedLiveSource = Boolean(
|
|
826
|
-
element.isConnected === false &&
|
|
827
|
-
element.srcObject?.getAudioTracks?.().some((track) => track.readyState === "live")
|
|
828
|
-
);
|
|
829
|
-
if (detachedLiveSource) {
|
|
830
|
-
element.muted = true;
|
|
831
|
-
element.pause?.();
|
|
832
|
-
element.srcObject = null;
|
|
833
|
-
} else {
|
|
834
|
-
element.muted = Boolean(source.muted);
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
entry?.bridge?.pause?.();
|
|
838
|
-
if (entry?.bridge) entry.bridge.srcObject = null;
|
|
839
|
-
entry?.bridge?.remove?.();
|
|
840
|
-
}
|
|
841
|
-
if (retained.length > 0) window.__openclawZoomAudioOutputs = retained;
|
|
842
|
-
else delete window.__openclawZoomAudioOutputs;
|
|
843
|
-
};
|
|
844
|
-
const first = (list) => {
|
|
698
|
+
return createMeetingLeaveSource({
|
|
699
|
+
controlSource: `const first = (list) => {
|
|
845
700
|
for (const selector of list) {
|
|
846
701
|
const node = document.querySelector(selector);
|
|
847
702
|
if (!node) continue;
|
|
@@ -865,73 +720,33 @@ function zoomMeetingLeaveScript(params) {
|
|
|
865
720
|
try {
|
|
866
721
|
const currentUrl = new URL(location.href);
|
|
867
722
|
webClientHome = !leave && currentUrl.hostname === "app.zoom.us" && /^\\/wc\\/?$/.test(currentUrl.pathname);
|
|
868
|
-
} catch {}
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
!
|
|
888
|
-
|
|
889
|
-
state?.inCallControl?.isConnected === false &&
|
|
890
|
-
state?.inCallUrl === location.href &&
|
|
891
|
-
Date.now() - state?.verifiedAt < 5_000 &&
|
|
892
|
-
!leave
|
|
893
|
-
);
|
|
894
|
-
const meetingIdentityMatches = Boolean(
|
|
895
|
-
currentUrlMatches || preservedCallMatches || pendingLeaveMatches || rerenderPendingMatches
|
|
896
|
-
);
|
|
897
|
-
// Zoom can replace the document between our Leave click and its post-call marker.
|
|
898
|
-
// Retain request ownership only while no identity or live-call control contradicts it.
|
|
899
|
-
const initiatedLeaveTransitionMatches = Boolean(
|
|
900
|
-
leaveInitiated &&
|
|
901
|
-
!currentIdentity &&
|
|
902
|
-
!leave &&
|
|
723
|
+
} catch {}`,
|
|
724
|
+
departedMarkerSource: "(postCall || webClientHome)",
|
|
725
|
+
documentSetupSource: `const topDocument = globalThis.document;
|
|
726
|
+
const document = topDocument.querySelector("#webclient")?.contentDocument || topDocument;`,
|
|
727
|
+
expectedIdentity: normalizeZoomMeetingUrlForReuse(params.meetingUrl),
|
|
728
|
+
leaveInitiated: params.leaveInitiated,
|
|
729
|
+
meetingSessionId: params.meetingSessionId,
|
|
730
|
+
meetingStateSource: "sessionId: expectedSessionId || state?.sessionId,",
|
|
731
|
+
pageIdentitySource: pageIdentityFunctionSource(),
|
|
732
|
+
platform: {
|
|
733
|
+
displayName: "Zoom",
|
|
734
|
+
globals: {
|
|
735
|
+
audioOutputs: "__openclawZoomAudioOutputs",
|
|
736
|
+
meeting: "__openclawZoomMeeting"
|
|
737
|
+
}
|
|
738
|
+
},
|
|
739
|
+
selectors,
|
|
740
|
+
sessionMatchSource: `const sessionAdoptedFromUrl = Boolean(
|
|
741
|
+
enforceSessionOwnership &&
|
|
742
|
+
!state?.sessionId &&
|
|
743
|
+
currentIdentity === expectedIdentity &&
|
|
903
744
|
(!state?.identity || state.identity === expectedIdentity)
|
|
904
745
|
);
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
}
|
|
910
|
-
if (!meetingIdentityMatches && !initiatedLeaveTransitionMatches) {
|
|
911
|
-
return JSON.stringify({ departed: false, urlMatched: false });
|
|
912
|
-
}
|
|
913
|
-
if (!sessionMatched) {
|
|
914
|
-
return JSON.stringify({ departed: false, urlMatched: true });
|
|
915
|
-
}
|
|
916
|
-
if (confirmation) {
|
|
917
|
-
confirmation.click();
|
|
918
|
-
return JSON.stringify({ departed: false, leaveAction: "confirm", urlMatched: true });
|
|
919
|
-
}
|
|
920
|
-
if (leave) {
|
|
921
|
-
window.__openclawZoomMeeting = {
|
|
922
|
-
...state,
|
|
923
|
-
identity: expectedIdentity,
|
|
924
|
-
sessionId: expectedSessionId || state?.sessionId,
|
|
925
|
-
inCallControl: leave,
|
|
926
|
-
inCallUrl: location.href,
|
|
927
|
-
leavePending: true,
|
|
928
|
-
leavePendingAt: Date.now(),
|
|
929
|
-
};
|
|
930
|
-
leave.click();
|
|
931
|
-
return JSON.stringify({ departed: false, leaveAction: "leave", urlMatched: true });
|
|
932
|
-
}
|
|
933
|
-
return JSON.stringify({ departed: false, urlMatched: true });
|
|
934
|
-
}`;
|
|
746
|
+
const sessionMatched = !enforceSessionOwnership ||
|
|
747
|
+
state?.sessionId === expectedSessionId ||
|
|
748
|
+
sessionAdoptedFromUrl;`
|
|
749
|
+
});
|
|
935
750
|
}
|
|
936
751
|
//#endregion
|
|
937
752
|
//#region extensions/zoom-meetings/src/transports/zoom-meetings-platform-constants.ts
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
"id": "zoom-meetings",
|
|
3
3
|
"name": "Zoom meetings",
|
|
4
4
|
"description": "Join Zoom meetings as a Chrome browser guest.",
|
|
5
|
+
"cliCommands": [
|
|
6
|
+
{
|
|
7
|
+
"name": "zoommeetings",
|
|
8
|
+
"description": "Join and manage Zoom meeting guests",
|
|
9
|
+
"hasSubcommands": true
|
|
10
|
+
}
|
|
11
|
+
],
|
|
5
12
|
"icon": "https://cdn.simpleicons.org/zoom",
|
|
6
13
|
"enabledByDefault": true,
|
|
7
14
|
"commandAliases": [{ "name": "zoommeetings" }],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/zoom-meetings",
|
|
3
|
-
"version": "2026.8.1-beta.
|
|
3
|
+
"version": "2026.8.1-beta.3",
|
|
4
4
|
"description": "OpenClaw Zoom browser meeting participant plugin.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"typebox": "1.3.6"
|
|
12
12
|
},
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"openclaw": ">=2026.8.1-beta.
|
|
14
|
+
"openclaw": ">=2026.8.1-beta.3"
|
|
15
15
|
},
|
|
16
16
|
"peerDependenciesMeta": {
|
|
17
17
|
"openclaw": {
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"minHostVersion": ">=2026.7.2"
|
|
30
30
|
},
|
|
31
31
|
"compat": {
|
|
32
|
-
"pluginApi": ">=2026.8.1-beta.
|
|
32
|
+
"pluginApi": ">=2026.8.1-beta.3"
|
|
33
33
|
},
|
|
34
34
|
"build": {
|
|
35
|
-
"openclawVersion": "2026.8.1-beta.
|
|
35
|
+
"openclawVersion": "2026.8.1-beta.3",
|
|
36
36
|
"bundledDist": false
|
|
37
37
|
},
|
|
38
38
|
"release": {
|