Skip to content

[fix] drain pending Gemini usage metadata before realtime session teardown - #3

Merged
yui0303 merged 1 commit into
pathorsfrom
claude/realtime-usage-metrics-disconnect-5x1xxb
Aug 20, 2026
Merged

[fix] drain pending Gemini usage metadata before realtime session teardown#3
yui0303 merged 1 commit into
pathorsfrom
claude/realtime-usage-metrics-disconnect-5x1xxb

Conversation

@yui0303

@yui0303 yui0303 commented Aug 20, 2026

Copy link
Copy Markdown

修 pathorsAI/pathors#2204:realtime 通話中使用者在 AI 第一句話講完前後掛斷時,該通話的 Gemini usage metrics 完全收不到。

AS IS

Gemini Live 只在 generation 結束時送 usageMetadata。掛斷觸發的 teardown 裡 AgentActivity._close_session() off("metrics_collected")、再 rt_session.aclose() 砍 receive loop——in-flight 的 usage event 永遠到不了 session.usage。單 turn 通話整通 LLM usage 歸零;多 turn 通話固定漏最後一個 turn。

TO BE

兩層修正:

  1. SDK corellm/realtime.py + voice/agent_activity.py):RealtimeSession 新增 drain_pending_metrics() hook(預設 no-op;fallback adapter 委派給 active child),_close_session() 在拆 listener 之前 await 它——drain 出來的 usage event 因此仍會被收進 session.usage
  2. Gemini pluginrealtime_api.py):_ResponseGeneration 追蹤 _usage_receiveddrain_pending_metrics() 在「當前 generation 的 usage 還沒到、連線還活著」時最多等 LK_GOOGLE_USAGE_DRAIN_TIMEOUT(預設 2s,≤0 可關閉)。已收到 / 未連線 / 正在關閉時直接 return——正常結束的通話零額外延遲。timeout 時留 warning log,該 turn usage 維持缺失(同修正前),可觀測。

掛斷時 SDK 會先送 interrupt(activity_start),Gemini 隨即 flush turnComplete + usage,2s 的 window 足以涵蓋絕大多數 case。

測試

  • 新增 tests/test_realtime_usage_drain.py(unit ×8):drain 的各 no-op guard、等到 usage、timeout、LK_GOOGLE_USAGE_DRAIN_TIMEOUT=0 關閉,以及 activity 層的順序測試(drain hook emit 的 metric 必須進 session.usage——沒有 _close_session 的修改該測試會 fail)
  • pytest --unit:1016 passed(base commit 對照跑,僅有的 1 failed + 9 errors 在 base 上完全相同,是測試環境 egress proxy 擋 test.livekit.cloud 造成,與本 PR 無關)
  • ruff check / ruff format --check 全 repo 過;scripts/check_types.py(mypy strict)618 檔全過

對應的主 repo submodule bump:pathorsAI/pathors 的 claude/realtime-usage-metrics-disconnect-5x1xxb branch。

🤖 Generated with Claude Code

https://claude.ai/code/session_01LLsDzcMV2NVcF9o8rN52u4


Generated by Claude Code

…rdown

## AS IS
- Gemini Live 只在 generation 結束時送 usageMetadata;caller 在第一句話
  講完前後掛斷時,close_on_disconnect 的 teardown 立刻 off 掉
  metrics_collected listener 並 cancel receive loop,in-flight 的 usage
  event 永遠收不到 —— 單 turn 通話的 LLM token usage 直接歸零
- 每通 realtime 通話的最後一個 turn 都有同樣的 race

## TO BE
- RealtimeSession 新增 drain_pending_metrics() hook(base 預設 no-op,
  fallback adapter 委派給 active child)
- AgentActivity._close_session 在拆 listener 之前先 await 這個 hook,
  drain 出來的 usage event 仍會進 session.usage
- Gemini plugin 實作:當前 generation 尚未收到 usageMetadata 時,最多等
  LK_GOOGLE_USAGE_DRAIN_TIMEOUT(預設 2s);已收到 / 未連線 / 正在關閉
  時不等,正常結束的通話零額外延遲

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LLsDzcMV2NVcF9o8rN52u4
@yui0303
yui0303 merged commit d088d7e into pathors Aug 20, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant