Repository navigation
Gemini 3.1 compatibility: deduplicate tools + upgrade SDK - #259
Conversation
- Deduplicate tool declarations in phone server: getCurrentTimeTool appeared in both anyCallerTools and inlineTools. Gemini 3.1 rejects duplicate function declarations with 1011 "Internal error" (2.5 silently accepted them). - Upgrade @google/genai from 1.48.0 to 1.49.0 - Upgrade bodhi-realtime-agent to commit 26992e35 (sendClientContent → sendRealtimeInput migration for 3.1 text injection) Verified: voice agent + phone agent both connect and respond on gemini-3.1-flash-live-preview. Tested with phone call + screen summon. Requires: sonichi/bodhi_realtime_agent fix/sendAudio-media-to-audio (changes sendAudio media→audio to avoid deprecated media_chunks wire format). Without the bodhi fix, audio streaming hits 1007. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sonichi
left a comment
There was a problem hiding this comment.
Reviewed from Mac Mini node. LGTM — the root-cause diagnosis closes yesterday's Gemini 3.1 quota ghost chase. I spent considerable time yesterday thinking the 1011 "exceeded your current quota" error was a billing tier issue; turns out Gemini 3.1 just has strict duplicate-declaration rejection and 2.5 silently accepted dupes. The misleading error text sent us looking in the wrong place.
Verified
- Duplicate confirmed:
getCurrentTimeToolis declared once atsrc/inline-tools.ts:338, then included in BOTHinlineTools(line 1333) ANDanyCallerTools(line 1340). conversation-server atskills/phone-conversation/scripts/conversation-server.ts:517pushes...anyCallerToolsthen later...inlineTools, sogetCurrentTimeToollands in the agent tool array twice. 3.1 rejects, 2.5 doesn't. - Dedup logic is correct —
Set-based filter preservesanyCallerTools-first priority (anyCallerTools version wins on conflict). - Voice-agent tool list is NOT affected:
src/voice-agent.tsuses[workTool, getTaskStatus, ...inlineTools]andworkTool/getTaskStatusare defined inline, not ininline-tools.ts. No duplicates. (Greppedsrc/inline-tools.tsforworkTool|getTaskStatus— zero hits.) - bodhi bump to
26992e35matches the merged fork PR #1 from earlier today. Already installed in ournode_modulesvia this morning'snpm install. - SDK bump 1.48 → 1.49 looks minor, no breaking changes I can see.
@cartesia/cartesia-jsmoved tooptionalDependenciesin package-lock — that's a benign regen side-effect (PR #239 already moved it to optionalDependencies in package.json, lockfile is catching up).
Concerns (non-blocking)
-
Depends on bodhi fork PR #2 (
liususan091219:fix/sendAudio-media-to-audio) — still OPEN. This PR fixes the duplicate-declaration 1011 but thesendAudiopath still uses themediakey instead ofaudio, which 3.1 rejects with 1007. Without bodhi #2 merged + anothernpm install, voice-agent on 3.1 will fire on the first user audio frame. Worth landing both together OR merging #259 now and documenting that 3.1 still needs bodhi #2 before unpinning.env. -
Dedup could live in
inline-tools.tsas aphoneToolListexport that filtersanyCallerToolsfrominlineToolsonce. Caller-side dedup repeats the logic at every consumer. Non-blocking — the 1-liner in conversation-server is fine for now. -
No tests added for the dedup. A simple unit test asserting
no duplicate names in the phone agent tools arraywould catch regressions if a futureinlineToolsaddition overlaps. Not a blocker, just a nice-to-have.
Post-merge to-do (for whoever lands bodhi #2)
- Merge bodhi fork #2 →
cd ~/Desktop/sutando && npm install github:sonichi/bodhi_realtime_agent→ restart voice-agent - Unpin
VOICE_NATIVE_AUDIO_MODELin.envtogemini-3.1-flash-live-preview - Test full audio-in / audio-out / tool-call / end-session cycle on 3.1
LGTM, merging anytime. Mini can merge it if you want — just say the word.
🤖 Sutando Mac Mini node
Scripts the post-merge verification after the 3-PR Gemini 3.1 compat stack lands: - bodhi fork #1 (sendClientContent → sendRealtimeInput text path) - bodhi fork #2 (Susan: sendAudio media → audio) - bodhi fork #3 (me: sendFile mimeType branching) - sutando #259 (Chi: deduplicate tool declarations + SDK bump) Checks the installed bodhi dist for each wire-format fix using awk-scoped extraction (simpler grep would false-positive on the OpenAI realtime transport's sendAudio which also uses `audio:` as a flat field, so the 3.1 gemini-specific check has to be scoped to the Gemini transport's function body). Checks sutando src for the phone conversation-server's tool dedup comment as a PR #259 marker. Checks .env for the 2.5 pin (exits green on 2.5, warns on 3.1 — so the script is safe to run repeatedly before, during, and after the rollout). Exits non-zero with "NOT READY for 3.1 rollout" if any wire-format fix is missing. On success, prints the manual next-steps checklist for unpinning .env, restarting voice-agent, and running the real 3.1 session test. Usage: bash src/verify-gemini-31.sh # check current state bash src/verify-gemini-31.sh --install # npm install + check Tested on the current state: correctly reports PR #1 applied, PR #2 + #3 + #259 not yet. Will flip to "ready" once those merge and an `npm install` pulls the updated bodhi SHA. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Isolates the second voice-agent-specific 3.1 compat issue discovered while landing the Gemini 3.1 stack today. Chi's #259 (dedup) + Susan's bodhi #2 (sendAudio) + my bodhi #3 (sendFile) all merged, npm installed, and 2.5 continued to work fine — but flipping .env to gemini-3.1-flash-live-preview still hit 1011 "exceeded your current quota" within 200ms of WebSocket setup. Misleading error text; the actual cause turned out to be the googleSearch + native-audio combo. Experiment: flipped googleSearch: true → false on an investigation branch, kept everything else identical (.env to 3.1, same dist, same tool list). Result: setup complete in 315ms, no 1011. Flipped back to googleSearch: true + 3.1 and the 1011 returned. Reproducible. So: Gemini 3.1 native audio rejects the googleSearch grounding tool entry. 2.5 silently accepted it. The rejection manifests as the same misleading "quota" close code that caught us on #259's duplicate-declaration bug earlier. Fix: env-var gate. VOICE_GOOGLE_SEARCH defaults to 'true' to preserve existing 2.5 behavior. Users unpinning VOICE_NATIVE_AUDIO_MODEL to 3.1 set VOICE_GOOGLE_SEARCH=false in .env at the same time. Comment at the declaration explains the constraint and points at today's investigation. Voice-agent LOSES google-search grounding on 3.1. Google search was used for "quick factual lookups" per the system instructions; 3.1 users will need to route those queries through the work tool (sutando-core) instead. Acceptable trade-off. Test plan: - ✓ tsc clean - ✓ Default (VOICE_GOOGLE_SEARCH unset, 2.5 pinned): setup complete, googleSearch: true as before - ✓ Investigation: VOICE_GOOGLE_SEARCH=false + 3.1 pinned → Gemini setup complete in 315ms, no 1011 - Live: user needs to test the full 3.1 session (greeting, tool call, voice goodbye, reconnect) before we can call 3.1 "ready" Follow-up: consider auto-inferring googleSearch=false when VOICE_NATIVE_AUDIO_MODEL contains "3.1" — would remove the need for users to set two env vars together. Not doing it here because the explicit config is more discoverable and easier to revert. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Scripts the post-merge verification after the 3-PR Gemini 3.1 compat stack lands: - bodhi fork #1 (sendClientContent → sendRealtimeInput text path) - bodhi fork #2 (Susan: sendAudio media → audio) - bodhi fork #3 (me: sendFile mimeType branching) - sutando #259 (Chi: deduplicate tool declarations + SDK bump) Checks the installed bodhi dist for each wire-format fix using awk-scoped extraction (simpler grep would false-positive on the OpenAI realtime transport's sendAudio which also uses `audio:` as a flat field, so the 3.1 gemini-specific check has to be scoped to the Gemini transport's function body). Checks sutando src for the phone conversation-server's tool dedup comment as a PR #259 marker. Checks .env for the 2.5 pin (exits green on 2.5, warns on 3.1 — so the script is safe to run repeatedly before, during, and after the rollout). Exits non-zero with "NOT READY for 3.1 rollout" if any wire-format fix is missing. On success, prints the manual next-steps checklist for unpinning .env, restarting voice-agent, and running the real 3.1 session test. Usage: bash src/verify-gemini-31.sh # check current state bash src/verify-gemini-31.sh --install # npm install + check Tested on the current state: correctly reports PR #1 applied, PR #2 + #3 + #259 not yet. Will flip to "ready" once those merge and an `npm install` pulls the updated bodhi SHA. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Fixes a false positive in the voice-transport probe (#258). Observed live 2026-04-09 at 03:30: voice-agent sat idle for ~10 minutes, then: 03:29:46 [VoiceSession] GoAway from Gemini (timeLeft=50s) 03:30:46 [VoiceSession] Transport closed (state=ACTIVE code=1011 reason="The service is currently unavailable.") 03:30:46 [VoiceSession] Gemini disconnected — will reconnect fresh when client connects That's Google's normal idle-timeout path: Gemini Live fires a GoAway 60s warning, then closes the transport with code=1011 and a "service is currently unavailable" reason. The bodhi session transitions to CLOSED and waits for the next client connect. When a client comes back, `handleClientConnected` reconnects fresh. Not a failure, just the expected lifecycle for an idle voice-agent. The probe was flagging every 1011-after-idle as `fail` with "unrecovered transport close" — which trains users to ignore the signal exactly when we need them to trust it (real 1011s from #259 duplicate-tool or #262 googleSearch misconfig get lost in the noise). Fix: track a `goaway_before_close` flag that flips true on GoAway and false on setup complete. Abnormal closes while the flag is true get reclassified as expected idle-timeouts (not flagged). The flag also clears on setup complete so a RECOVERED idle timeout followed by a fresh unrelated 1011 still correctly fails. Test plan: - ✓ Live probe on current log (has idle-timeout 1011 from 03:30): voice-transport ok - ✓ 4-case simulated-log harness: 1. GoAway → 1011 "service unavailable" unrecovered → ok (was fail) 2. Unrecovered 1011 quota, no GoAway preceding → fail (as before) 3. GoAway → 1011 → setup complete (reconnected) → ok 4. Recovered idle-timeout + fresh 1011 with no new GoAway → fail (proves the flag correctly resets on setup complete) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
PR #262 branched before #259 merged, so the branch's package-lock still had @google/genai@1.48 while package.json had 1.49 (inherited from the rebase pull). CI failed with: npm error Invalid: lock file's @google/genai@1.48.0 does not satisfy @google/genai@1.49.0 Regenerated lockfile via `npm install` (no args). No other changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
) Fixes a false positive in the voice-transport probe (#258). Observed live 2026-04-09 at 03:30: voice-agent sat idle for ~10 minutes, then: 03:29:46 [VoiceSession] GoAway from Gemini (timeLeft=50s) 03:30:46 [VoiceSession] Transport closed (state=ACTIVE code=1011 reason="The service is currently unavailable.") 03:30:46 [VoiceSession] Gemini disconnected — will reconnect fresh when client connects That's Google's normal idle-timeout path: Gemini Live fires a GoAway 60s warning, then closes the transport with code=1011 and a "service is currently unavailable" reason. The bodhi session transitions to CLOSED and waits for the next client connect. When a client comes back, `handleClientConnected` reconnects fresh. Not a failure, just the expected lifecycle for an idle voice-agent. The probe was flagging every 1011-after-idle as `fail` with "unrecovered transport close" — which trains users to ignore the signal exactly when we need them to trust it (real 1011s from #259 duplicate-tool or #262 googleSearch misconfig get lost in the noise). Fix: track a `goaway_before_close` flag that flips true on GoAway and false on setup complete. Abnormal closes while the flag is true get reclassified as expected idle-timeouts (not flagged). The flag also clears on setup complete so a RECOVERED idle timeout followed by a fresh unrelated 1011 still correctly fails. Test plan: - ✓ Live probe on current log (has idle-timeout 1011 from 03:30): voice-transport ok - ✓ 4-case simulated-log harness: 1. GoAway → 1011 "service unavailable" unrecovered → ok (was fail) 2. Unrecovered 1011 quota, no GoAway preceding → fail (as before) 3. GoAway → 1011 → setup complete (reconnected) → ok 4. Recovered idle-timeout + fresh 1011 with no new GoAway → fail (proves the flag correctly resets on setup complete) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…mpat) (#262) * voice-agent: gate googleSearch on VOICE_GOOGLE_SEARCH env var Isolates the second voice-agent-specific 3.1 compat issue discovered while landing the Gemini 3.1 stack today. Chi's #259 (dedup) + Susan's bodhi #2 (sendAudio) + my bodhi #3 (sendFile) all merged, npm installed, and 2.5 continued to work fine — but flipping .env to gemini-3.1-flash-live-preview still hit 1011 "exceeded your current quota" within 200ms of WebSocket setup. Misleading error text; the actual cause turned out to be the googleSearch + native-audio combo. Experiment: flipped googleSearch: true → false on an investigation branch, kept everything else identical (.env to 3.1, same dist, same tool list). Result: setup complete in 315ms, no 1011. Flipped back to googleSearch: true + 3.1 and the 1011 returned. Reproducible. So: Gemini 3.1 native audio rejects the googleSearch grounding tool entry. 2.5 silently accepted it. The rejection manifests as the same misleading "quota" close code that caught us on #259's duplicate-declaration bug earlier. Fix: env-var gate. VOICE_GOOGLE_SEARCH defaults to 'true' to preserve existing 2.5 behavior. Users unpinning VOICE_NATIVE_AUDIO_MODEL to 3.1 set VOICE_GOOGLE_SEARCH=false in .env at the same time. Comment at the declaration explains the constraint and points at today's investigation. Voice-agent LOSES google-search grounding on 3.1. Google search was used for "quick factual lookups" per the system instructions; 3.1 users will need to route those queries through the work tool (sutando-core) instead. Acceptable trade-off. Test plan: - ✓ tsc clean - ✓ Default (VOICE_GOOGLE_SEARCH unset, 2.5 pinned): setup complete, googleSearch: true as before - ✓ Investigation: VOICE_GOOGLE_SEARCH=false + 3.1 pinned → Gemini setup complete in 315ms, no 1011 - Live: user needs to test the full 3.1 session (greeting, tool call, voice goodbye, reconnect) before we can call 3.1 "ready" Follow-up: consider auto-inferring googleSearch=false when VOICE_NATIVE_AUDIO_MODEL contains "3.1" — would remove the need for users to set two env vars together. Not doing it here because the explicit config is more discoverable and easier to revert. 🤖 Generated with [Claude Code](https://claude.com/claude-code) * sync package-lock.json to @google/genai 1.49 from #259 PR #262 branched before #259 merged, so the branch's package-lock still had @google/genai@1.48 while package.json had 1.49 (inherited from the rebase pull). CI failed with: npm error Invalid: lock file's @google/genai@1.48.0 does not satisfy @google/genai@1.49.0 Regenerated lockfile via `npm install` (no args). No other changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…261) * Add src/verify-gemini-31.sh — pre-rollout gate for Gemini 3.1 stack Scripts the post-merge verification after the 3-PR Gemini 3.1 compat stack lands: - bodhi fork #1 (sendClientContent → sendRealtimeInput text path) - bodhi fork #2 (Susan: sendAudio media → audio) - bodhi fork #3 (me: sendFile mimeType branching) - sutando #259 (Chi: deduplicate tool declarations + SDK bump) Checks the installed bodhi dist for each wire-format fix using awk-scoped extraction (simpler grep would false-positive on the OpenAI realtime transport's sendAudio which also uses `audio:` as a flat field, so the 3.1 gemini-specific check has to be scoped to the Gemini transport's function body). Checks sutando src for the phone conversation-server's tool dedup comment as a PR #259 marker. Checks .env for the 2.5 pin (exits green on 2.5, warns on 3.1 — so the script is safe to run repeatedly before, during, and after the rollout). Exits non-zero with "NOT READY for 3.1 rollout" if any wire-format fix is missing. On success, prints the manual next-steps checklist for unpinning .env, restarting voice-agent, and running the real 3.1 session test. Usage: bash src/verify-gemini-31.sh # check current state bash src/verify-gemini-31.sh --install # npm install + check Tested on the current state: correctly reports PR #1 applied, PR #2 + #3 + #259 not yet. Will flip to "ready" once those merge and an `npm install` pulls the updated bodhi SHA. 🤖 Generated with [Claude Code](https://claude.com/claude-code) * verify-gemini-31: check VOICE_GOOGLE_SEARCH pin in .env Extends the script to enforce the second 3.1 compat requirement discovered in #262: VOICE_GOOGLE_SEARCH must be 'false' when VOICE_NATIVE_AUDIO_MODEL is pinned to 3.1. Without it, voice-agent hits a misleading 1011 close on connect. Check matrix: 2.5 + default (googleSearch=true) → pass 2.5 + VOICE_GOOGLE_SEARCH=false → warn (unnecessarily losing search) 3.1 + VOICE_GOOGLE_SEARCH=false → pass 3.1 + default (googleSearch=true) → fail (1011 on connect) 3.1 + unset VOICE_GOOGLE_SEARCH → fail (defaults to true → 1011) Also updates the 'Manual next steps' tail to tell users to set BOTH env vars together when flipping to 3.1. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Deduplicate tool declarations in phone server: getCurrentTimeTool appeared in both anyCallerTools and inlineTools. Gemini 3.1 rejects duplicate function declarations with 1011 "Internal error" (2.5 silently accepted them). - Upgrade @google/genai from 1.48.0 to 1.49.0 - Upgrade bodhi-realtime-agent to commit 26992e35 (sendClientContent → sendRealtimeInput migration for 3.1 text injection) Verified: voice agent + phone agent both connect and respond on gemini-3.1-flash-live-preview. Tested with phone call + screen summon. Requires: sonichi/bodhi_realtime_agent fix/sendAudio-media-to-audio (changes sendAudio media→audio to avoid deprecated media_chunks wire format). Without the bodhi fix, audio streaming hits 1007. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…onichi#263) Fixes a false positive in the voice-transport probe (sonichi#258). Observed live 2026-04-09 at 03:30: voice-agent sat idle for ~10 minutes, then: 03:29:46 [VoiceSession] GoAway from Gemini (timeLeft=50s) 03:30:46 [VoiceSession] Transport closed (state=ACTIVE code=1011 reason="The service is currently unavailable.") 03:30:46 [VoiceSession] Gemini disconnected — will reconnect fresh when client connects That's Google's normal idle-timeout path: Gemini Live fires a GoAway 60s warning, then closes the transport with code=1011 and a "service is currently unavailable" reason. The bodhi session transitions to CLOSED and waits for the next client connect. When a client comes back, `handleClientConnected` reconnects fresh. Not a failure, just the expected lifecycle for an idle voice-agent. The probe was flagging every 1011-after-idle as `fail` with "unrecovered transport close" — which trains users to ignore the signal exactly when we need them to trust it (real 1011s from sonichi#259 duplicate-tool or sonichi#262 googleSearch misconfig get lost in the noise). Fix: track a `goaway_before_close` flag that flips true on GoAway and false on setup complete. Abnormal closes while the flag is true get reclassified as expected idle-timeouts (not flagged). The flag also clears on setup complete so a RECOVERED idle timeout followed by a fresh unrelated 1011 still correctly fails. Test plan: - ✓ Live probe on current log (has idle-timeout 1011 from 03:30): voice-transport ok - ✓ 4-case simulated-log harness: 1. GoAway → 1011 "service unavailable" unrecovered → ok (was fail) 2. Unrecovered 1011 quota, no GoAway preceding → fail (as before) 3. GoAway → 1011 → setup complete (reconnected) → ok 4. Recovered idle-timeout + fresh 1011 with no new GoAway → fail (proves the flag correctly resets on setup complete) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…mpat) (sonichi#262) * voice-agent: gate googleSearch on VOICE_GOOGLE_SEARCH env var Isolates the second voice-agent-specific 3.1 compat issue discovered while landing the Gemini 3.1 stack today. Chi's sonichi#259 (dedup) + Susan's bodhi sonichi#2 (sendAudio) + my bodhi sonichi#3 (sendFile) all merged, npm installed, and 2.5 continued to work fine — but flipping .env to gemini-3.1-flash-live-preview still hit 1011 "exceeded your current quota" within 200ms of WebSocket setup. Misleading error text; the actual cause turned out to be the googleSearch + native-audio combo. Experiment: flipped googleSearch: true → false on an investigation branch, kept everything else identical (.env to 3.1, same dist, same tool list). Result: setup complete in 315ms, no 1011. Flipped back to googleSearch: true + 3.1 and the 1011 returned. Reproducible. So: Gemini 3.1 native audio rejects the googleSearch grounding tool entry. 2.5 silently accepted it. The rejection manifests as the same misleading "quota" close code that caught us on sonichi#259's duplicate-declaration bug earlier. Fix: env-var gate. VOICE_GOOGLE_SEARCH defaults to 'true' to preserve existing 2.5 behavior. Users unpinning VOICE_NATIVE_AUDIO_MODEL to 3.1 set VOICE_GOOGLE_SEARCH=false in .env at the same time. Comment at the declaration explains the constraint and points at today's investigation. Voice-agent LOSES google-search grounding on 3.1. Google search was used for "quick factual lookups" per the system instructions; 3.1 users will need to route those queries through the work tool (sutando-core) instead. Acceptable trade-off. Test plan: - ✓ tsc clean - ✓ Default (VOICE_GOOGLE_SEARCH unset, 2.5 pinned): setup complete, googleSearch: true as before - ✓ Investigation: VOICE_GOOGLE_SEARCH=false + 3.1 pinned → Gemini setup complete in 315ms, no 1011 - Live: user needs to test the full 3.1 session (greeting, tool call, voice goodbye, reconnect) before we can call 3.1 "ready" Follow-up: consider auto-inferring googleSearch=false when VOICE_NATIVE_AUDIO_MODEL contains "3.1" — would remove the need for users to set two env vars together. Not doing it here because the explicit config is more discoverable and easier to revert. 🤖 Generated with [Claude Code](https://claude.com/claude-code) * sync package-lock.json to @google/genai 1.49 from sonichi#259 PR sonichi#262 branched before sonichi#259 merged, so the branch's package-lock still had @google/genai@1.48 while package.json had 1.49 (inherited from the rebase pull). CI failed with: npm error Invalid: lock file's @google/genai@1.48.0 does not satisfy @google/genai@1.49.0 Regenerated lockfile via `npm install` (no args). No other changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…onichi#261) * Add src/verify-gemini-31.sh — pre-rollout gate for Gemini 3.1 stack Scripts the post-merge verification after the 3-PR Gemini 3.1 compat stack lands: - bodhi fork sonichi#1 (sendClientContent → sendRealtimeInput text path) - bodhi fork sonichi#2 (Susan: sendAudio media → audio) - bodhi fork sonichi#3 (me: sendFile mimeType branching) - sutando sonichi#259 (Chi: deduplicate tool declarations + SDK bump) Checks the installed bodhi dist for each wire-format fix using awk-scoped extraction (simpler grep would false-positive on the OpenAI realtime transport's sendAudio which also uses `audio:` as a flat field, so the 3.1 gemini-specific check has to be scoped to the Gemini transport's function body). Checks sutando src for the phone conversation-server's tool dedup comment as a PR sonichi#259 marker. Checks .env for the 2.5 pin (exits green on 2.5, warns on 3.1 — so the script is safe to run repeatedly before, during, and after the rollout). Exits non-zero with "NOT READY for 3.1 rollout" if any wire-format fix is missing. On success, prints the manual next-steps checklist for unpinning .env, restarting voice-agent, and running the real 3.1 session test. Usage: bash src/verify-gemini-31.sh # check current state bash src/verify-gemini-31.sh --install # npm install + check Tested on the current state: correctly reports PR sonichi#1 applied, PR sonichi#2 + sonichi#3 + sonichi#259 not yet. Will flip to "ready" once those merge and an `npm install` pulls the updated bodhi SHA. 🤖 Generated with [Claude Code](https://claude.com/claude-code) * verify-gemini-31: check VOICE_GOOGLE_SEARCH pin in .env Extends the script to enforce the second 3.1 compat requirement discovered in sonichi#262: VOICE_GOOGLE_SEARCH must be 'false' when VOICE_NATIVE_AUDIO_MODEL is pinned to 3.1. Without it, voice-agent hits a misleading 1011 close on connect. Check matrix: 2.5 + default (googleSearch=true) → pass 2.5 + VOICE_GOOGLE_SEARCH=false → warn (unnecessarily losing search) 3.1 + VOICE_GOOGLE_SEARCH=false → pass 3.1 + default (googleSearch=true) → fail (1011 on connect) 3.1 + unset VOICE_GOOGLE_SEARCH → fail (defaults to true → 1011) Also updates the 'Manual next steps' tail to tell users to set BOTH env vars together when flipping to 3.1. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Summary
getCurrentTimeToolappeared in bothanyCallerToolsandinlineTools, causing Gemini 3.1 to reject with 1011 "Internal error" (2.5 silently accepted duplicates)@google/genaifrom 1.48.0 to 1.49.0bodhi-realtime-agentto commit26992e35(sendClientContent → sendRealtimeInput migration)Root cause
Gemini 3.1 is stricter than 2.5:
media_chunkswire format → 1007 (requiresaudiokey in sendRealtimeInput)sendClientContentfor text → 1011 (requiressendRealtimeInput({ text }))Items 2-3 fixed in bodhi fork. This PR fixes item 1 in sutando.
Depends on
fix/sendAudio-media-to-audio(1-line:media→audioin sendAudio)Test plan
🤖 Generated with Claude Code