From d5ecee2cf332b49335a7e92a97564f4567a4e2b2 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 3 May 2026 17:56:05 -0700 Subject: [PATCH] fix(google-meet): tighten realtime echo overlap --- CHANGELOG.md | 1 + extensions/google-meet/index.test.ts | 7 +++++++ extensions/google-meet/src/realtime.ts | 8 ++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55a70ee2efb..c58b9d4160e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ Docs: https://docs.openclaw.ai - Plugin tools: keep auth-unavailable optional tools hidden even when another default tool from the same plugin is available and `tools.alsoAllow` names the optional tool. Thanks @vincentkoc. - Realtime transcription: report socket closes before provider readiness as closed-before-ready failures instead of mislabeling them as connection timeouts for OpenAI, xAI, and Deepgram streaming transcription. Thanks @vincentkoc. - OpenAI/Google Meet: fail realtime voice connection attempts when the socket closes before `session.updated`, avoiding stuck Meet joins waiting on a bridge that never became ready. Thanks @vincentkoc. +- Google Meet: avoid treating repeated participant words as multiple assistant-overlap matches when suppressing realtime echo transcripts. Thanks @vincentkoc. - QA/cache: require the full `CACHE-OK ` marker before live cache probes stop retrying, so suffix-only prose cannot hide a broken probe response. Thanks @vincentkoc. - Slack/Matrix: avoid creating blank progress-draft messages when `streaming.progress.label=false` and progress tool lines are disabled. Thanks @vincentkoc. - QA/Matrix: keep the mock OpenAI tool-progress provider aligned with exact-marker Matrix prompts so the hardened live preview scenario still forces a deterministic read before final delivery. Thanks @vincentkoc. diff --git a/extensions/google-meet/index.test.ts b/extensions/google-meet/index.test.ts index 5f1ccbc3bee..9508d37a0bc 100644 --- a/extensions/google-meet/index.test.ts +++ b/extensions/google-meet/index.test.ts @@ -3857,6 +3857,13 @@ describe("google-meet plugin", () => { nowMs, }), ).toBe(false); + expect( + isGoogleMeetLikelyAssistantEchoTranscript({ + transcript, + text: "yes yes yes yes", + nowMs, + }), + ).toBe(false); }); it("uses a local barge-in input command to clear active Chrome playback", async () => { diff --git a/extensions/google-meet/src/realtime.ts b/extensions/google-meet/src/realtime.ts index 33deff1a892..872f4b5f357 100644 --- a/extensions/google-meet/src/realtime.ts +++ b/extensions/google-meet/src/realtime.ts @@ -173,9 +173,13 @@ function hasMeaningfulEchoOverlap(userTokens: string[], assistantTokens: string[ if (userTokens.length < 4 || assistantTokens.length < 4) { return false; } + const uniqueUserTokens = [...new Set(userTokens)]; + if (uniqueUserTokens.length < 4) { + return false; + } const assistantTokenSet = new Set(assistantTokens); - const overlap = userTokens.filter((token) => assistantTokenSet.has(token)).length; - return overlap / userTokens.length >= 0.58; + const overlap = uniqueUserTokens.filter((token) => assistantTokenSet.has(token)).length; + return overlap / uniqueUserTokens.length >= 0.58; } export function isGoogleMeetLikelyAssistantEchoTranscript(params: {