Skip to content

fix(google-meet): handle stdout/stderr stream errors in local audio bridge#101596

Merged
vincentkoc merged 2 commits into
openclaw:mainfrom
Alix-007:alix/google-meet-stream-errors
Jul 8, 2026
Merged

fix(google-meet): handle stdout/stderr stream errors in local audio bridge#101596
vincentkoc merged 2 commits into
openclaw:mainfrom
Alix-007:alix/google-meet-stream-errors

Conversation

@Alix-007

@Alix-007 Alix-007 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add stdout/stderr error handlers for Google Meet command audio bridge child streams
  • stop the bridge through the existing failure path when primary audio input/output streams error; the stop path is idempotent (stopped guard), so duplicate stream errors cannot tear down twice or kill twice
  • cover agent and realtime bridge stream errors with focused regressions, plus a real spawned local command-pair substitute driven through the real exported startCommandAgentAudioBridge
  • collision check: no open PR found for the Google Meet local audio bridge stream-error issue or extensions/google-meet/src/realtime.ts

Verification

  • node scripts/run-vitest.mjs run --config test/vitest/vitest.extensions.config.ts extensions/google-meet/index.test.ts -t "stops the Chrome agent audio bridge|stops the Chrome realtime audio bridge|pipes Chrome command-pair audio through the realtime provider" — passed; 1 file, 3 tests passed, 100 skipped
  • node scripts/run-vitest.mjs extensions/google-meet/src/realtime.process.test.ts -- --reporter=verbose — passed; 1 file, 1 test passed (real local child-process proof)
  • node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.extensions.json extensions/google-meet/src/realtime.process.test.ts — passed
  • git diff --check — passed
  • mutation check: removing the stdout error handler made the real-process test fail with an unhandled EPIPE from real bridge input stdout; restoring the handler made it pass

Real behavior proof

Behavior addressed: Google Meet local command-pair audio bridge stdout stream errors are contained by the existing bridge fail/stop path, without an unhandled stream error or repeated teardown.
Real environment tested: local Linux Node source checkout; the proof wires two real local substitute command processes through startCommandAgentAudioBridge with real child pipes. It is not a live Google Meet call and not the default SoX/CoreAudio/BlackHole device chain.
Exact steps or command run after this patch: node scripts/run-vitest.mjs extensions/google-meet/src/realtime.process.test.ts -- --reporter=verbose.
Evidence after fix: [proof] local command-pair substitute stopped after forced input stdout stream error; inputPid=3847906 outputPid=3847905; Test Files 1 passed (1); Tests 1 passed (1).
Observed result after fix: a forced stdout stream error on the real spawned input command logs through audio input command stdout failed, bridge health reports bridgeClosed=true, the STT session closes exactly once, and both input/output command processes emit close after a single SIGTERM each.
What was not tested: a live Google Meet/Chrome audio device run and the default macOS SoX/CoreAudio BlackHole 2ch commands — this Linux environment has no sox binary and no CoreAudio/BlackHole device, so the closest honest local proof is a real substitute command pair driving the real exported bridge function.

@clawsweeper

clawsweeper Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 7, 2026, 9:04 PM ET / 01:04 UTC.

Summary
The PR adds stdout/stderr error handling for Google Meet command-pair audio bridge child streams and adds mocked plus spawned-process regression coverage.

PR surface: Source +27, Tests +288. Total +315 across 3 files.

Reproducibility: yes. at source level: current main attaches data listeners to child stdout/stderr streams in the Google Meet command-pair bridge without matching error listeners, and Node streams raise unhandled error events unless handled. I did not reproduce it in a live Meet call.

Review metrics: none identified.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • none.

Risk before merge

  • [P1] The proof uses a spawned local command-pair substitute rather than a live macOS SoX/CoreAudio/BlackHole Google Meet call, so it validates the stream-error path but not the full audio-device environment.

Maintainer options:

  1. Decide the mitigation before merge
    Merge the narrow plugin-owned stream-handler fix after exact-head CI and maintainer review, treating full live Meet audio-device validation as optional release smoke rather than a blocker for this stream-handling patch.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • No ClawSweeper repair is needed; the PR has no actionable code findings and should proceed through normal maintainer review and exact-head CI.

Security
Cleared: The diff only adds plugin-local child stream error handlers and tests; it does not change dependencies, workflows, secrets, package resolution, or other security-sensitive surfaces.

Review details

Best possible solution:

Merge the narrow plugin-owned stream-handler fix after exact-head CI and maintainer review, treating full live Meet audio-device validation as optional release smoke rather than a blocker for this stream-handling patch.

Do we have a high-confidence way to reproduce the issue?

Yes at source level: current main attaches data listeners to child stdout/stderr streams in the Google Meet command-pair bridge without matching error listeners, and Node streams raise unhandled error events unless handled. I did not reproduce it in a live Meet call.

Is this the best way to solve the issue?

Yes: the PR reuses the existing fail/stop path for primary bridge stream failures and logs optional barge-in stream errors instead of adding a parallel recovery path. A live audio-device E2E would add confidence but is not necessary to validate this stream-handler fix.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 81d0f3f37291.

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The updated PR body includes terminal output from a real spawned local command-pair substitute driven through the exported bridge function, which is sufficient for this non-visual stream-error path.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The updated PR body includes terminal output from a real spawned local command-pair substitute driven through the exported bridge function, which is sufficient for this non-visual stream-error path.
  • remove rating: 🦪 silver shellfish: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove status: 📣 needs proof: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P2: This is a normal bundled Google Meet plugin robustness bug fix with limited blast radius.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The updated PR body includes terminal output from a real spawned local command-pair substitute driven through the exported bridge function, which is sufficient for this non-visual stream-error path.
  • proof: sufficient: Contributor real behavior proof is sufficient. The updated PR body includes terminal output from a real spawned local command-pair substitute driven through the exported bridge function, which is sufficient for this non-visual stream-error path.
Evidence reviewed

PR surface:

Source +27, Tests +288. Total +315 across 3 files.

View PR surface stats
Area Files Added Removed Net
Source 1 29 2 +27
Tests 2 293 5 +288
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 3 322 7 +315

What I checked:

  • Repository policy read: Root and scoped extension policy were read and applied; the relevant guidance is to review plugin code beyond the diff, keep plugin-owned behavior inside the plugin, and require source/test/proof evidence for fixes. (AGENTS.md:1, 81d0f3f37291)
  • Current main behavior: Current main registers process and stdin failures but only data listeners on the Google Meet bridge child stdout/stderr streams, leaving stream error events uncovered on the command-pair paths. (extensions/google-meet/src/realtime.ts:613, 81d0f3f37291)
  • Caller path: Chrome talk-back mode starts startCommandAgentAudioBridge or startCommandRealtimeAudioBridge with configured audio input/output commands, so the changed code is on the local Google Meet audio bridge runtime path. (extensions/google-meet/src/transports/chrome.ts:157, 81d0f3f37291)
  • PR implementation: At the PR head, primary agent and realtime bridge stream errors are handled with the existing fail/stop path, stale realtime output stderr errors are guarded, and optional barge-in stream errors are logged without tearing down the bridge. (extensions/google-meet/src/realtime.ts:622, 19e6f153a5e7)
  • Regression coverage: The new test spawns real local substitute command processes through startCommandAgentAudioBridge, destroys the input stdout stream with an error, and asserts one clean close path with SIGTERM for both child processes. (extensions/google-meet/src/realtime.process.test.ts:82, 19e6f153a5e7)
  • Node stream contract check: A local PassThrough emits an error without a listener as an unhandled error, and the same error is contained when an error listener is registered, matching the bug and fix shape.

Likely related people:

  • steipete: Authored the original Google Meet participant plugin PR and a later Google Meet realtime output activity refactor touching realtime.ts and adjacent tests. (role: feature owner and recent area contributor; confidence: high; commits: 8129ac0f269a, bef0ba8f5a7e; files: extensions/google-meet/src/realtime.ts, extensions/google-meet/src/transports/chrome.ts, extensions/google-meet/index.test.ts)
  • shhtheonlyperson: Authored the merged Google Meet realtime barge-in playback work touching the same realtime bridge and Google Meet tests. (role: adjacent realtime audio contributor; confidence: medium; commits: 0c3d1892cd5a; files: extensions/google-meet/src/realtime.ts, extensions/google-meet/index.test.ts)
  • Solvely-Colin: Authored merged OAuth-backed realtime voice controls work that touched Google Meet realtime/plugin surfaces and the provider path reviewed here. (role: related realtime voice contributor; confidence: medium; commits: 6481021763f9; files: extensions/google-meet/src/realtime.ts, extensions/google-meet/index.test.ts)
  • Shakker: The available checkout blame for the command-pair bridge implementation points to commit 476017d, though the shallow history makes this a weaker routing signal. (role: current-line history signal; confidence: low; commits: 476017d775ba; files: extensions/google-meet/src/realtime.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (1 earlier review cycle)
  • reviewed 2026-07-07T11:44:40.043Z sha d7837a5 :: needs real behavior proof before merge. :: none

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. labels Jul 7, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 8, 2026
@vincentkoc vincentkoc self-assigned this Jul 8, 2026
@vincentkoc

Copy link
Copy Markdown
Member

Maintainer validation is complete for exact head 19e6f153a5e708dc441dfe364533009d09f335c6.

What I verified:

  • Read the full Google Meet command-pair bridge, Chrome transport caller, current/stale output process lifecycle, optional barge-in path, and adjacent tests.
  • Confirmed this is the best bounded fix: owned child streams get error listeners; primary failures reuse the existing idempotent fail/stop path; stale replaced-output failures are identity-guarded; optional barge-in failures log without killing the call.
  • node scripts/run-vitest.mjs extensions/google-meet/index.test.ts extensions/google-meet/src/realtime.process.test.ts - 104/104 passed.
  • node_modules/.bin/oxfmt --check extensions/google-meet/src/realtime.ts extensions/google-meet/src/realtime.process.test.ts extensions/google-meet/index.test.ts - passed.
  • git diff --check origin/main...HEAD - passed.
  • Fresh Codex gpt-5.5 high autoreview - no accepted/actionable findings.
  • Native review artifacts - validated, READY FOR /prepare-pr, zero findings.
  • Exact-head CI run 28909525984 - success, 48 successful jobs, 9 skipped, zero failures.

Proof gap: no live macOS SoX/CoreAudio/BlackHole Google Meet call was run. The changed Node stream contract is covered by the real spawned command-pair process test, so this is an optional environment smoke rather than a landing blocker.

Ready for squash merge.

@vincentkoc
vincentkoc merged commit 5fd5bf2 into openclaw:main Jul 8, 2026
141 of 149 checks passed
@vincentkoc

Copy link
Copy Markdown
Member

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 8, 2026
…ridge (openclaw#101596)

* fix(google-meet): handle stdout/stderr stream errors in local audio bridge

* test(google-meet): prove command bridge stream errors
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
…ridge (openclaw#101596)

* fix(google-meet): handle stdout/stderr stream errors in local audio bridge

* test(google-meet): prove command bridge stream errors
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal backlog priority with limited blast radius. plugin: google-meet proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants