roomkit 0.7.2__tar.gz → 0.9.0__tar.gz

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.
Files changed (809) hide show
  1. {roomkit-0.7.2 → roomkit-0.9.0}/PKG-INFO +6 -5
  2. {roomkit-0.7.2 → roomkit-0.9.0}/README.md +2 -2
  3. {roomkit-0.7.2 → roomkit-0.9.0}/pyproject.toml +2 -2
  4. roomkit-0.9.0/src/roomkit/_version.py +1 -0
  5. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_ai_context.py +13 -7
  6. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_ai_events.py +6 -1
  7. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_ai_generation.py +33 -6
  8. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_ai_streaming.py +142 -27
  9. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_realtime_audio.py +152 -81
  10. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_realtime_response.py +37 -25
  11. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_realtime_speech.py +16 -12
  12. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_realtime_tools.py +45 -0
  13. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_realtime_transcription.py +6 -0
  14. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_tool_eviction.py +22 -7
  15. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/ai.py +60 -1
  16. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/base.py +11 -0
  17. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/realtime_voice.py +42 -10
  18. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/event_router.py +7 -14
  19. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/framework.py +17 -10
  20. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/__init__.py +2 -0
  21. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/helpers.py +36 -4
  22. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/inbound.py +16 -0
  23. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/inbound_locked.py +158 -64
  24. roomkit-0.9.0/src/roomkit/core/mixins/regenerate.py +143 -0
  25. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/memory/base.py +18 -0
  26. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/memory/sliding_window.py +5 -0
  27. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/channel.py +10 -0
  28. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/delivery.py +5 -0
  29. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/telegram/bot.py +36 -0
  30. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tools/__init__.py +3 -0
  31. roomkit-0.9.0/src/roomkit/tools/context.py +48 -0
  32. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/_mulaw.py +14 -8
  33. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/local.py +149 -24
  34. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/sip.py +10 -0
  35. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/sip_audio.py +4 -0
  36. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/aec/webrtc.py +33 -13
  37. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/realtime/fastrtc_transport.py +14 -4
  38. roomkit-0.9.0/src/roomkit/voice/utils.py +44 -0
  39. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_ai_streaming_thinking.py +126 -0
  40. roomkit-0.9.0/tests/test_channels/test_ai_empty_retry.py +137 -0
  41. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_ai_skill_gating.py +52 -0
  42. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_ai_tool_loop.py +3 -2
  43. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_fastrtc_realtime_transport.py +25 -0
  44. roomkit-0.9.0/tests/test_inbound_visibility.py +58 -0
  45. roomkit-0.9.0/tests/test_integration/test_regenerate.py +132 -0
  46. roomkit-0.9.0/tests/test_realtime_resample_offload.py +265 -0
  47. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_realtime_voice.py +147 -1
  48. roomkit-0.9.0/tests/test_recent_events_window.py +83 -0
  49. roomkit-0.9.0/tests/test_rfc_conformance.py +230 -0
  50. roomkit-0.9.0/tests/test_tool_context.py +159 -0
  51. roomkit-0.9.0/tests/test_tool_eviction_room_scope.py +71 -0
  52. roomkit-0.9.0/tests/test_voice_dsp_vectorized.py +73 -0
  53. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_local.py +173 -0
  54. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/backends/test_sip.py +41 -0
  55. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/pipeline/test_webrtc_aec.py +19 -0
  56. roomkit-0.7.2/src/roomkit/_version.py +0 -1
  57. roomkit-0.7.2/src/roomkit/voice/utils.py +0 -22
  58. {roomkit-0.7.2 → roomkit-0.9.0}/.gitignore +0 -0
  59. {roomkit-0.7.2 → roomkit-0.9.0}/AGENTS.md +0 -0
  60. {roomkit-0.7.2 → roomkit-0.9.0}/LICENSE +0 -0
  61. {roomkit-0.7.2 → roomkit-0.9.0}/docs/README.md +0 -0
  62. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/ai-channels.md +0 -0
  63. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/api-reference.md +0 -0
  64. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/architecture.md +0 -0
  65. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/hooks.md +0 -0
  66. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/identity-and-realtime.md +0 -0
  67. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/installation.md +0 -0
  68. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/ollama-provider.md +0 -0
  69. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/orchestration.md +0 -0
  70. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/overview.md +0 -0
  71. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/quickstart.md +0 -0
  72. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/realtime-voice.md +0 -0
  73. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/resilience.md +0 -0
  74. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/rooms-and-channels.md +0 -0
  75. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/storage.md +0 -0
  76. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/testing.md +0 -0
  77. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/transport-providers.md +0 -0
  78. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/voice-channels.md +0 -0
  79. {roomkit-0.7.2 → roomkit-0.9.0}/docs/c7/voice-pipeline.md +0 -0
  80. {roomkit-0.7.2 → roomkit-0.9.0}/docs/diagrams/architecture.svg +0 -0
  81. {roomkit-0.7.2 → roomkit-0.9.0}/docs/diagrams/avatar-pipeline.svg +0 -0
  82. {roomkit-0.7.2 → roomkit-0.9.0}/docs/diagrams/message-flow.svg +0 -0
  83. {roomkit-0.7.2 → roomkit-0.9.0}/docs/diagrams/orchestration.svg +0 -0
  84. {roomkit-0.7.2 → roomkit-0.9.0}/docs/diagrams/room-lifecycle.svg +0 -0
  85. {roomkit-0.7.2 → roomkit-0.9.0}/docs/diagrams/video-pipeline.svg +0 -0
  86. {roomkit-0.7.2 → roomkit-0.9.0}/docs/diagrams/voice-orchestration.svg +0 -0
  87. {roomkit-0.7.2 → roomkit-0.9.0}/docs/diagrams/voice-pipeline.svg +0 -0
  88. {roomkit-0.7.2 → roomkit-0.9.0}/llms-full.txt +0 -0
  89. {roomkit-0.7.2 → roomkit-0.9.0}/llms.txt +0 -0
  90. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/__init__.py +0 -0
  91. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/ai_docs.py +0 -0
  92. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/__init__.py +0 -0
  93. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_ai_policy.py +0 -0
  94. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_ai_resilience.py +0 -0
  95. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_ai_steering.py +0 -0
  96. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_ai_tools.py +0 -0
  97. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_dangling_recovery.py +0 -0
  98. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_realtime_context.py +0 -0
  99. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_realtime_skills.py +0 -0
  100. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_realtime_tool_recovery.py +0 -0
  101. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_realtime_tool_search.py +0 -0
  102. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_sandbox_handlers.py +0 -0
  103. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_skill_constants.py +0 -0
  104. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_skill_handlers.py +0 -0
  105. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_task_planner.py +0 -0
  106. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_tool_search_constants.py +0 -0
  107. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_turn_config.py +0 -0
  108. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_video_hooks.py +0 -0
  109. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_voice_hooks.py +0 -0
  110. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_voice_pipeline.py +0 -0
  111. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_voice_stt.py +0 -0
  112. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_voice_tts.py +0 -0
  113. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/_voice_turn.py +0 -0
  114. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/agent.py +0 -0
  115. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/av.py +0 -0
  116. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/cli.py +0 -0
  117. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/realtime_av.py +0 -0
  118. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/transport.py +0 -0
  119. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/video.py +0 -0
  120. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/voice.py +0 -0
  121. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/channels/websocket.py +0 -0
  122. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/console/__init__.py +0 -0
  123. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/console/_display.py +0 -0
  124. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/console/_hooks.py +0 -0
  125. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/console/_state.py +0 -0
  126. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/__init__.py +0 -0
  127. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/circuit_breaker.py +0 -0
  128. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/delivery.py +0 -0
  129. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/exceptions.py +0 -0
  130. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/hooks.py +0 -0
  131. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/inbound_router.py +0 -0
  132. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/locks.py +0 -0
  133. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/channel_ops.py +0 -0
  134. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/delegation.py +0 -0
  135. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/deliver.py +0 -0
  136. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/greeting.py +0 -0
  137. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/hooks_api.py +0 -0
  138. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/inbound_identity.py +0 -0
  139. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/inbound_streaming.py +0 -0
  140. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/realtime_ops.py +0 -0
  141. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/recording.py +0 -0
  142. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/room_lifecycle.py +0 -0
  143. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/source_ops.py +0 -0
  144. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/mixins/voice_ops.py +0 -0
  145. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/rate_limiter.py +0 -0
  146. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/retry.py +0 -0
  147. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/router.py +0 -0
  148. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/task_utils.py +0 -0
  149. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/core/transcoder.py +0 -0
  150. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/delivery/__init__.py +0 -0
  151. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/delivery/base.py +0 -0
  152. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/delivery/memory.py +0 -0
  153. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/delivery/redis.py +0 -0
  154. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/delivery/serialization.py +0 -0
  155. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/delivery/worker.py +0 -0
  156. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/identity/__init__.py +0 -0
  157. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/identity/base.py +0 -0
  158. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/identity/mock.py +0 -0
  159. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/knowledge/__init__.py +0 -0
  160. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/knowledge/base.py +0 -0
  161. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/knowledge/mock.py +0 -0
  162. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/knowledge/postgres.py +0 -0
  163. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/memory/__init__.py +0 -0
  164. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/memory/budget_aware.py +0 -0
  165. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/memory/compacting.py +0 -0
  166. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/memory/mock.py +0 -0
  167. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/memory/retrieval.py +0 -0
  168. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/memory/summarizing.py +0 -0
  169. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/memory/token_estimator.py +0 -0
  170. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/__init__.py +0 -0
  171. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/context.py +0 -0
  172. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/enums.py +0 -0
  173. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/event.py +0 -0
  174. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/framework_event.py +0 -0
  175. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/hook.py +0 -0
  176. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/identity.py +0 -0
  177. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/participant.py +0 -0
  178. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/pending_input.py +0 -0
  179. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/room.py +0 -0
  180. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/session_event.py +0 -0
  181. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/steering.py +0 -0
  182. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/store_filter.py +0 -0
  183. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/streaming.py +0 -0
  184. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/task.py +0 -0
  185. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/tool_call.py +0 -0
  186. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/trace.py +0 -0
  187. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/models/vision_event.py +0 -0
  188. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/__init__.py +0 -0
  189. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/base.py +0 -0
  190. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/handoff.py +0 -0
  191. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/pipeline.py +0 -0
  192. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/router.py +0 -0
  193. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/session_audit.py +0 -0
  194. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/state.py +0 -0
  195. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/status_bus.py +0 -0
  196. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/strategies/__init__.py +0 -0
  197. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/strategies/loop.py +0 -0
  198. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/strategies/pipeline.py +0 -0
  199. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/strategies/supervisor.py +0 -0
  200. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/strategies/swarm.py +0 -0
  201. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/orchestration/tool_audit.py +0 -0
  202. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/__init__.py +0 -0
  203. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/ai/__init__.py +0 -0
  204. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/ai/base.py +0 -0
  205. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/ai/mock.py +0 -0
  206. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/anam/__init__.py +0 -0
  207. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/anam/_convert.py +0 -0
  208. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/anam/avatar.py +0 -0
  209. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/anam/config.py +0 -0
  210. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/anam/realtime.py +0 -0
  211. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/anthropic/__init__.py +0 -0
  212. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/anthropic/ai.py +0 -0
  213. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/anthropic/config.py +0 -0
  214. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/azure/__init__.py +0 -0
  215. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/azure/ai.py +0 -0
  216. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/azure/config.py +0 -0
  217. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/elasticemail/__init__.py +0 -0
  218. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/elasticemail/config.py +0 -0
  219. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/elasticemail/email.py +0 -0
  220. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/elevenlabs/__init__.py +0 -0
  221. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/elevenlabs/config.py +0 -0
  222. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/elevenlabs/realtime.py +0 -0
  223. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/email/__init__.py +0 -0
  224. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/email/base.py +0 -0
  225. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/email/mock.py +0 -0
  226. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/gemini/__init__.py +0 -0
  227. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/gemini/ai.py +0 -0
  228. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/gemini/config.py +0 -0
  229. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/gemini/realtime.py +0 -0
  230. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/gemini/schema.py +0 -0
  231. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/http/__init__.py +0 -0
  232. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/http/base.py +0 -0
  233. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/http/config.py +0 -0
  234. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/http/mock.py +0 -0
  235. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/http/provider.py +0 -0
  236. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/http/webhook.py +0 -0
  237. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/http_errors.py +0 -0
  238. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/messenger/__init__.py +0 -0
  239. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/messenger/base.py +0 -0
  240. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/messenger/config.py +0 -0
  241. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/messenger/facebook.py +0 -0
  242. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/messenger/mock.py +0 -0
  243. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/messenger/webhook.py +0 -0
  244. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/mistral/__init__.py +0 -0
  245. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/mistral/ai.py +0 -0
  246. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/mistral/config.py +0 -0
  247. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/ollama/__init__.py +0 -0
  248. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/ollama/ai.py +0 -0
  249. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/ollama/config.py +0 -0
  250. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/openai/__init__.py +0 -0
  251. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/openai/ai.py +0 -0
  252. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/openai/config.py +0 -0
  253. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/openai/realtime.py +0 -0
  254. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/personaplex/__init__.py +0 -0
  255. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/personaplex/config.py +0 -0
  256. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/personaplex/realtime.py +0 -0
  257. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/rcs/__init__.py +0 -0
  258. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/rcs/base.py +0 -0
  259. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/rcs/mock.py +0 -0
  260. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/sendgrid/__init__.py +0 -0
  261. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/sendgrid/config.py +0 -0
  262. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/sendgrid/email.py +0 -0
  263. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/sinch/__init__.py +0 -0
  264. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/sinch/config.py +0 -0
  265. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/sinch/sms.py +0 -0
  266. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/sms/__init__.py +0 -0
  267. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/sms/base.py +0 -0
  268. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/sms/meta.py +0 -0
  269. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/sms/mock.py +0 -0
  270. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/sms/phone.py +0 -0
  271. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/teams/__init__.py +0 -0
  272. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/teams/base.py +0 -0
  273. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/teams/bot_framework.py +0 -0
  274. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/teams/config.py +0 -0
  275. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/teams/conversation_store.py +0 -0
  276. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/teams/mock.py +0 -0
  277. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/teams/models.py +0 -0
  278. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/teams/webhook.py +0 -0
  279. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/telegram/__init__.py +0 -0
  280. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/telegram/base.py +0 -0
  281. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/telegram/config.py +0 -0
  282. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/telegram/mock.py +0 -0
  283. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/telegram/webhook.py +0 -0
  284. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/telnyx/__init__.py +0 -0
  285. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/telnyx/_signature.py +0 -0
  286. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/telnyx/config.py +0 -0
  287. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/telnyx/rcs.py +0 -0
  288. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/telnyx/sms.py +0 -0
  289. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/twilio/__init__.py +0 -0
  290. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/twilio/config.py +0 -0
  291. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/twilio/rcs.py +0 -0
  292. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/twilio/sms.py +0 -0
  293. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/twilio/webhook.py +0 -0
  294. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/url_safety.py +0 -0
  295. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/utils.py +0 -0
  296. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/vllm/__init__.py +0 -0
  297. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/vllm/config.py +0 -0
  298. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/voicemeup/__init__.py +0 -0
  299. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/voicemeup/config.py +0 -0
  300. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/voicemeup/sms.py +0 -0
  301. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/whatsapp/__init__.py +0 -0
  302. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/whatsapp/base.py +0 -0
  303. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/whatsapp/mock.py +0 -0
  304. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/whatsapp/personal.py +0 -0
  305. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/xai/__init__.py +0 -0
  306. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/xai/config.py +0 -0
  307. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/providers/xai/realtime.py +0 -0
  308. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/py.typed +0 -0
  309. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/realtime/__init__.py +0 -0
  310. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/realtime/base.py +0 -0
  311. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/realtime/memory.py +0 -0
  312. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/recorder/__init__.py +0 -0
  313. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/recorder/_pyav_mux.py +0 -0
  314. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/recorder/_room_recorder_manager.py +0 -0
  315. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/recorder/base.py +0 -0
  316. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/recorder/mock.py +0 -0
  317. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/recorder/pyav.py +0 -0
  318. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/sandbox/__init__.py +0 -0
  319. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/sandbox/executor.py +0 -0
  320. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/sandbox/models.py +0 -0
  321. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/sandbox/tools.py +0 -0
  322. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/scoring/__init__.py +0 -0
  323. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/scoring/base.py +0 -0
  324. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/scoring/hook.py +0 -0
  325. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/scoring/mock.py +0 -0
  326. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/scoring/tracker.py +0 -0
  327. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/skills/__init__.py +0 -0
  328. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/skills/executor.py +0 -0
  329. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/skills/models.py +0 -0
  330. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/skills/parser.py +0 -0
  331. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/skills/registry.py +0 -0
  332. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/sources/__init__.py +0 -0
  333. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/sources/base.py +0 -0
  334. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/sources/neonize.py +0 -0
  335. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/sources/sse.py +0 -0
  336. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/sources/websocket.py +0 -0
  337. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/store/__init__.py +0 -0
  338. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/store/base.py +0 -0
  339. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/store/memory.py +0 -0
  340. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/store/postgres.py +0 -0
  341. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tasks/__init__.py +0 -0
  342. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tasks/base.py +0 -0
  343. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tasks/cache.py +0 -0
  344. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tasks/delegate.py +0 -0
  345. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tasks/memory.py +0 -0
  346. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tasks/models.py +0 -0
  347. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/telemetry/__init__.py +0 -0
  348. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/telemetry/base.py +0 -0
  349. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/telemetry/config.py +0 -0
  350. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/telemetry/console.py +0 -0
  351. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/telemetry/context.py +0 -0
  352. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/telemetry/mock.py +0 -0
  353. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/telemetry/noop.py +0 -0
  354. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/telemetry/opentelemetry.py +0 -0
  355. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/telemetry/pyroscope.py +0 -0
  356. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tools/base.py +0 -0
  357. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tools/compose.py +0 -0
  358. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tools/external.py +0 -0
  359. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tools/human_input.py +0 -0
  360. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tools/mcp.py +0 -0
  361. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/tools/policy.py +0 -0
  362. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/__init__.py +0 -0
  363. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/ai_integration.py +0 -0
  364. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/avatar/__init__.py +0 -0
  365. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/avatar/base.py +0 -0
  366. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/avatar/mock.py +0 -0
  367. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/avatar/musetalk.py +0 -0
  368. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/avatar/websocket.py +0 -0
  369. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/backends/__init__.py +0 -0
  370. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/backends/base.py +0 -0
  371. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/backends/fastrtc.py +0 -0
  372. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/backends/local.py +0 -0
  373. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/backends/mock.py +0 -0
  374. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/backends/rtp.py +0 -0
  375. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/backends/screen.py +0 -0
  376. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/backends/sip.py +0 -0
  377. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/backends/websocket.py +0 -0
  378. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/base.py +0 -0
  379. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/bridge.py +0 -0
  380. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/events.py +0 -0
  381. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/__init__.py +0 -0
  382. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/config.py +0 -0
  383. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/decoder/__init__.py +0 -0
  384. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/decoder/base.py +0 -0
  385. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/decoder/mock.py +0 -0
  386. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/decoder/pyav.py +0 -0
  387. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/encoder/__init__.py +0 -0
  388. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/encoder/base.py +0 -0
  389. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/encoder/pyav.py +0 -0
  390. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/engine.py +0 -0
  391. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/filter/__init__.py +0 -0
  392. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/filter/base.py +0 -0
  393. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/filter/censor.py +0 -0
  394. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/filter/mediapipe_face_touch.py +0 -0
  395. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/filter/mock.py +0 -0
  396. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/filter/mock_face_touch.py +0 -0
  397. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/filter/watermark.py +0 -0
  398. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/filter/yolo.py +0 -0
  399. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/overlay/__init__.py +0 -0
  400. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/overlay/base.py +0 -0
  401. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/overlay/filter.py +0 -0
  402. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/overlay/image.py +0 -0
  403. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/overlay/mock.py +0 -0
  404. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/overlay/rich.py +0 -0
  405. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/overlay/subtitle.py +0 -0
  406. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/overlay/text.py +0 -0
  407. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/resizer/__init__.py +0 -0
  408. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/resizer/base.py +0 -0
  409. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/resizer/mock.py +0 -0
  410. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/resizer/pyav.py +0 -0
  411. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/transform/__init__.py +0 -0
  412. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/transform/base.py +0 -0
  413. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/transform/effects.py +0 -0
  414. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/pipeline/transform/mock.py +0 -0
  415. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/recorder/__init__.py +0 -0
  416. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/recorder/base.py +0 -0
  417. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/recorder/mock.py +0 -0
  418. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/recorder/opencv.py +0 -0
  419. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/recorder/pyav.py +0 -0
  420. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/utils.py +0 -0
  421. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/video_frame.py +0 -0
  422. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/vision/__init__.py +0 -0
  423. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/vision/base.py +0 -0
  424. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/vision/encode.py +0 -0
  425. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/vision/gemini.py +0 -0
  426. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/vision/mock.py +0 -0
  427. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/vision/openai.py +0 -0
  428. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/vision/screen_input.py +0 -0
  429. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/vision/screen_tool.py +0 -0
  430. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/video/vision/webcam_tool.py +0 -0
  431. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/__init__.py +0 -0
  432. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/audio_frame.py +0 -0
  433. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/auth.py +0 -0
  434. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/__init__.py +0 -0
  435. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/_sip_types.py +0 -0
  436. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/base.py +0 -0
  437. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/fastrtc.py +0 -0
  438. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/mock.py +0 -0
  439. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/rtp.py +0 -0
  440. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/sip_auth.py +0 -0
  441. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/sip_calling.py +0 -0
  442. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/twilio_ws.py +0 -0
  443. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/backends/webtransport.py +0 -0
  444. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/base.py +0 -0
  445. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/bridge.py +0 -0
  446. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/events.py +0 -0
  447. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/inbound.py +0 -0
  448. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/interruption.py +0 -0
  449. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/__init__.py +0 -0
  450. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/aec/__init__.py +0 -0
  451. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/aec/base.py +0 -0
  452. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/aec/mock.py +0 -0
  453. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/aec/speex.py +0 -0
  454. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/agc/__init__.py +0 -0
  455. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/agc/base.py +0 -0
  456. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/agc/mock.py +0 -0
  457. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/backchannel/__init__.py +0 -0
  458. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/backchannel/base.py +0 -0
  459. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/backchannel/mock.py +0 -0
  460. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/config.py +0 -0
  461. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/debug_taps.py +0 -0
  462. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/denoiser/__init__.py +0 -0
  463. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/denoiser/aicoustics.py +0 -0
  464. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/denoiser/base.py +0 -0
  465. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/denoiser/mock.py +0 -0
  466. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/denoiser/rnnoise.py +0 -0
  467. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/denoiser/sherpa_onnx.py +0 -0
  468. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/diarization/__init__.py +0 -0
  469. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/diarization/base.py +0 -0
  470. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/diarization/mock.py +0 -0
  471. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/diarization/sherpa_onnx.py +0 -0
  472. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/dtmf/__init__.py +0 -0
  473. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/dtmf/base.py +0 -0
  474. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/dtmf/mock.py +0 -0
  475. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/engine.py +0 -0
  476. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/mixer/__init__.py +0 -0
  477. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/mixer/base.py +0 -0
  478. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/mixer/numpy.py +0 -0
  479. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/mixer/python.py +0 -0
  480. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/postprocessor/__init__.py +0 -0
  481. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/postprocessor/base.py +0 -0
  482. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/recorder/__init__.py +0 -0
  483. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/recorder/base.py +0 -0
  484. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/recorder/mock.py +0 -0
  485. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/recorder/wav.py +0 -0
  486. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/resampler/__init__.py +0 -0
  487. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/resampler/base.py +0 -0
  488. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/resampler/linear.py +0 -0
  489. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/resampler/mock.py +0 -0
  490. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/resampler/numpy.py +0 -0
  491. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/resampler/sinc.py +0 -0
  492. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/turn/__init__.py +0 -0
  493. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/turn/base.py +0 -0
  494. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/turn/mock.py +0 -0
  495. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/turn/smart_turn.py +0 -0
  496. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/vad/__init__.py +0 -0
  497. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/vad/base.py +0 -0
  498. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/vad/energy.py +0 -0
  499. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/vad/mock.py +0 -0
  500. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/pipeline/vad/sherpa_onnx.py +0 -0
  501. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/realtime/__init__.py +0 -0
  502. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/realtime/bridge.py +0 -0
  503. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/realtime/events.py +0 -0
  504. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/realtime/mock.py +0 -0
  505. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/realtime/pacer.py +0 -0
  506. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/realtime/provider.py +0 -0
  507. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/realtime/sip_transport.py +0 -0
  508. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/realtime/ws_transport.py +0 -0
  509. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/stt/__init__.py +0 -0
  510. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/stt/base.py +0 -0
  511. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/stt/deepgram.py +0 -0
  512. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/stt/gradium.py +0 -0
  513. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/stt/mock.py +0 -0
  514. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/stt/qwen3.py +0 -0
  515. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/stt/sherpa_onnx.py +0 -0
  516. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/tts/__init__.py +0 -0
  517. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/tts/audio_utils.py +0 -0
  518. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/tts/base.py +0 -0
  519. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/tts/elevenlabs.py +0 -0
  520. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/tts/filters.py +0 -0
  521. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/tts/gradium.py +0 -0
  522. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/tts/grok.py +0 -0
  523. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/tts/mock.py +0 -0
  524. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/tts/neutts.py +0 -0
  525. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/tts/qwen3.py +0 -0
  526. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/tts/sentence_splitter.py +0 -0
  527. {roomkit-0.7.2 → roomkit-0.9.0}/src/roomkit/voice/tts/sherpa_onnx.py +0 -0
  528. {roomkit-0.7.2 → roomkit-0.9.0}/tests/__init__.py +0 -0
  529. {roomkit-0.7.2 → roomkit-0.9.0}/tests/conftest.py +0 -0
  530. {roomkit-0.7.2 → roomkit-0.9.0}/tests/delivery/__init__.py +0 -0
  531. {roomkit-0.7.2 → roomkit-0.9.0}/tests/delivery/test_base.py +0 -0
  532. {roomkit-0.7.2 → roomkit-0.9.0}/tests/delivery/test_integration.py +0 -0
  533. {roomkit-0.7.2 → roomkit-0.9.0}/tests/delivery/test_memory.py +0 -0
  534. {roomkit-0.7.2 → roomkit-0.9.0}/tests/delivery/test_redis.py +0 -0
  535. {roomkit-0.7.2 → roomkit-0.9.0}/tests/delivery/test_serialization.py +0 -0
  536. {roomkit-0.7.2 → roomkit-0.9.0}/tests/delivery/test_worker.py +0 -0
  537. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/__init__.py +0 -0
  538. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_framework_orchestration.py +0 -0
  539. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_handoff.py +0 -0
  540. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_loop_strategy.py +0 -0
  541. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_orchestration_base.py +0 -0
  542. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_pipeline.py +0 -0
  543. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_router.py +0 -0
  544. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_session_audit.py +0 -0
  545. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_state.py +0 -0
  546. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_status_bus.py +0 -0
  547. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_strategy_behavioral.py +0 -0
  548. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_strategy_loop.py +0 -0
  549. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_strategy_pipeline.py +0 -0
  550. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_strategy_supervisor.py +0 -0
  551. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_strategy_swarm.py +0 -0
  552. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_supervisor_inline.py +0 -0
  553. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_supervisor_strategy.py +0 -0
  554. {roomkit-0.7.2 → roomkit-0.9.0}/tests/orchestration/test_tool_audit.py +0 -0
  555. {roomkit-0.7.2 → roomkit-0.9.0}/tests/providers/__init__.py +0 -0
  556. {roomkit-0.7.2 → roomkit-0.9.0}/tests/providers/gemini/__init__.py +0 -0
  557. {roomkit-0.7.2 → roomkit-0.9.0}/tests/providers/gemini/test_reconfigure_preservation.py +0 -0
  558. {roomkit-0.7.2 → roomkit-0.9.0}/tests/providers/gemini/test_schema.py +0 -0
  559. {roomkit-0.7.2 → roomkit-0.9.0}/tests/tasks/__init__.py +0 -0
  560. {roomkit-0.7.2 → roomkit-0.9.0}/tests/tasks/test_cache.py +0 -0
  561. {roomkit-0.7.2 → roomkit-0.9.0}/tests/tasks/test_delegate.py +0 -0
  562. {roomkit-0.7.2 → roomkit-0.9.0}/tests/tasks/test_integration.py +0 -0
  563. {roomkit-0.7.2 → roomkit-0.9.0}/tests/tasks/test_models.py +0 -0
  564. {roomkit-0.7.2 → roomkit-0.9.0}/tests/tasks/test_runner.py +0 -0
  565. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_aec_pipeline.py +0 -0
  566. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_ai_docs.py +0 -0
  567. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_ai_streaming_tool_loop.py +0 -0
  568. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_aicoustics_denoiser.py +0 -0
  569. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_anam_realtime.py +0 -0
  570. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_audio_pipeline.py +0 -0
  571. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_auto_connect.py +0 -0
  572. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_av_channel.py +0 -0
  573. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_avatar.py +0 -0
  574. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_before_ai_generation.py +0 -0
  575. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channel_abc.py +0 -0
  576. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/__init__.py +0 -0
  577. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_agent.py +0 -0
  578. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_ai.py +0 -0
  579. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_ai_retry.py +0 -0
  580. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_ai_steering.py +0 -0
  581. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_email.py +0 -0
  582. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_http.py +0 -0
  583. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_messenger.py +0 -0
  584. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_sms.py +0 -0
  585. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_telegram.py +0 -0
  586. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_turn_config.py +0 -0
  587. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_websocket.py +0 -0
  588. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_channels/test_whatsapp.py +0 -0
  589. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_circuit_breaker.py +0 -0
  590. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_cli_channel.py +0 -0
  591. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_compose_tool_handlers.py +0 -0
  592. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_configs.py +0 -0
  593. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_console.py +0 -0
  594. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_dangling_recovery.py +0 -0
  595. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_delivery_strategies.py +0 -0
  596. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_describe_screen_tool.py +0 -0
  597. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_describe_webcam_tool.py +0 -0
  598. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_drain_barge_in.py +0 -0
  599. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_energy_vad.py +0 -0
  600. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_enums.py +0 -0
  601. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_external_tool_handler.py +0 -0
  602. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_face_touch_filter.py +0 -0
  603. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_framework.py +0 -0
  604. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_framework_events.py +0 -0
  605. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_framework_queries.py +0 -0
  606. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_framework_status_bus.py +0 -0
  607. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_hook_side_effects.py +0 -0
  608. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_hooks.py +0 -0
  609. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_human_input.py +0 -0
  610. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_identity_hooks.py +0 -0
  611. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_identity_pipeline.py +0 -0
  612. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_inbound_rate_limit.py +0 -0
  613. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_inbound_routing.py +0 -0
  614. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_integration/__init__.py +0 -0
  615. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_integration/test_ai_assistant.py +0 -0
  616. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_integration/test_ai_chain_depth.py +0 -0
  617. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_integration/test_cross_channel.py +0 -0
  618. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_integration/test_dynamic_channels.py +0 -0
  619. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_integration/test_human_ai.py +0 -0
  620. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_integration/test_identity_resolution.py +0 -0
  621. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_integration/test_observer.py +0 -0
  622. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_integration/test_sin_scanning.py +0 -0
  623. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_interruption.py +0 -0
  624. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_lifecycle_hooks.py +0 -0
  625. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_local_backend_aec.py +0 -0
  626. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_locks.py +0 -0
  627. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_mcp_tool_provider.py +0 -0
  628. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_mcp_tools.py +0 -0
  629. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_media_recorder.py +0 -0
  630. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_memory.py +0 -0
  631. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_memory_new.py +0 -0
  632. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_mock_providers.py +0 -0
  633. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_models.py +0 -0
  634. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_observability.py +0 -0
  635. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_opencv_recorder.py +0 -0
  636. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_opentelemetry.py +0 -0
  637. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_outbound_audio_pacer.py +0 -0
  638. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_personaplex_realtime.py +0 -0
  639. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_pipeline_debug_taps.py +0 -0
  640. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_pipeline_engine.py +0 -0
  641. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_pipeline_providers.py +0 -0
  642. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_pipeline_resampler.py +0 -0
  643. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_pipeline_resampler_numpy.py +0 -0
  644. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_pipeline_resampler_sinc.py +0 -0
  645. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_postgres_store.py +0 -0
  646. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_protocol_trace.py +0 -0
  647. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/__init__.py +0 -0
  648. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_anam_avatar.py +0 -0
  649. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_anam_realtime.py +0 -0
  650. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_anthropic.py +0 -0
  651. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_azure.py +0 -0
  652. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_elasticemail.py +0 -0
  653. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_gemini.py +0 -0
  654. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_gemini_realtime.py +0 -0
  655. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_http.py +0 -0
  656. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_messenger.py +0 -0
  657. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_mistral.py +0 -0
  658. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_ollama.py +0 -0
  659. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_openai.py +0 -0
  660. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_openai_realtime.py +0 -0
  661. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_personaplex_realtime.py +0 -0
  662. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_phone.py +0 -0
  663. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_rcs.py +0 -0
  664. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_sendgrid.py +0 -0
  665. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_sinch.py +0 -0
  666. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_sms_utils.py +0 -0
  667. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_teams.py +0 -0
  668. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_teams_webhook.py +0 -0
  669. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_telegram_bot.py +0 -0
  670. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_telegram_webhook.py +0 -0
  671. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_telnyx.py +0 -0
  672. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_telnyx_rcs.py +0 -0
  673. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_twilio.py +0 -0
  674. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_vllm.py +0 -0
  675. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_voicemeup.py +0 -0
  676. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_whatsapp_personal.py +0 -0
  677. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_providers/test_xai_realtime.py +0 -0
  678. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_public_api.py +0 -0
  679. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_pyav_media_recorder.py +0 -0
  680. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_pyav_recorder.py +0 -0
  681. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_realtime.py +0 -0
  682. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_realtime_av_channel.py +0 -0
  683. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_realtime_elevenlabs.py +0 -0
  684. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_realtime_skills.py +0 -0
  685. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_realtime_tool_search.py +0 -0
  686. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_realtime_voice_integration.py +0 -0
  687. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_realtime_xai.py +0 -0
  688. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_recording_wiring.py +0 -0
  689. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_reentry_block_side_effects.py +0 -0
  690. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_resilience.py +0 -0
  691. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_response_metadata.py +0 -0
  692. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_response_visibility.py +0 -0
  693. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_retrieval_memory.py +0 -0
  694. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_rnnoise.py +0 -0
  695. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_router.py +0 -0
  696. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_rtp_video_backend.py +0 -0
  697. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_scoring.py +0 -0
  698. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_screen_capture_backend.py +0 -0
  699. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_screen_input.py +0 -0
  700. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_session_started.py +0 -0
  701. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_sherpa_onnx_denoiser.py +0 -0
  702. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_sherpa_onnx_vad.py +0 -0
  703. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_sip_auth.py +0 -0
  704. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_sip_dial.py +0 -0
  705. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_sip_helpers.py +0 -0
  706. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_sip_realtime_transport.py +0 -0
  707. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_sip_video_backend.py +0 -0
  708. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_skills.py +0 -0
  709. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_skills_integration.py +0 -0
  710. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_smart_turn.py +0 -0
  711. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_smoke_quickstart.py +0 -0
  712. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_source_rate_limit.py +0 -0
  713. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_sources.py +0 -0
  714. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_sources_init.py +0 -0
  715. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_sources_neonize.py +0 -0
  716. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_sources_sse.py +0 -0
  717. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_sources_websocket.py +0 -0
  718. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_speex_aec.py +0 -0
  719. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_store_activity.py +0 -0
  720. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_store_memory.py +0 -0
  721. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_store_postgres.py +0 -0
  722. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_stt_qwen3.py +0 -0
  723. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_summarizing_memory.py +0 -0
  724. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_supervisor.py +0 -0
  725. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_task_planner.py +0 -0
  726. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_task_utils.py +0 -0
  727. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_telemetry.py +0 -0
  728. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_telemetry_pyroscope.py +0 -0
  729. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_tool_policy.py +0 -0
  730. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_tool_protocol.py +0 -0
  731. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_transport_auth.py +0 -0
  732. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_tts_elevenlabs.py +0 -0
  733. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_tts_grok.py +0 -0
  734. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_tts_neutts.py +0 -0
  735. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_tts_qwen3.py +0 -0
  736. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_tts_text_split.py +0 -0
  737. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_turn_detection.py +0 -0
  738. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_twilio_ws_backend.py +0 -0
  739. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_unified_tool_call.py +0 -0
  740. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_vad_debug_logging.py +0 -0
  741. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_video.py +0 -0
  742. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_video_ai_integration.py +0 -0
  743. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_video_channel.py +0 -0
  744. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_video_local.py +0 -0
  745. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_video_pipeline.py +0 -0
  746. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_video_pipeline_config.py +0 -0
  747. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_video_recording.py +0 -0
  748. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_video_transform.py +0 -0
  749. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_vision_gemini.py +0 -0
  750. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_vision_openai.py +0 -0
  751. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice.py +0 -0
  752. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_batch_stt.py +0 -0
  753. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_binding_gate.py +0 -0
  754. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_channel_aec.py +0 -0
  755. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_fastrtc.py +0 -0
  756. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_frame_limit.py +0 -0
  757. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_inbound.py +0 -0
  758. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_integration.py +0 -0
  759. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_map.py +0 -0
  760. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_rtp.py +0 -0
  761. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_say_play.py +0 -0
  762. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_sherpa_onnx.py +0 -0
  763. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_streaming_ai_tts.py +0 -0
  764. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_streaming_stt.py +0 -0
  765. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_voice_webtransport.py +0 -0
  766. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_wav_recorder.py +0 -0
  767. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_websocket_lifecycle.py +0 -0
  768. {roomkit-0.7.2 → roomkit-0.9.0}/tests/test_yolo_filter.py +0 -0
  769. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/__init__.py +0 -0
  770. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_av_channel_fastrtc.py +0 -0
  771. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_fastrtc_video_backend.py +0 -0
  772. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_overlay_filter.py +0 -0
  773. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_overlay_image.py +0 -0
  774. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_overlay_rich.py +0 -0
  775. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_overlay_subtitle.py +0 -0
  776. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_overlay_text.py +0 -0
  777. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_screen_input.py +0 -0
  778. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_screen_input_tools.py +0 -0
  779. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_video_bridge.py +0 -0
  780. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_video_effects.py +0 -0
  781. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_watermark_filter.py +0 -0
  782. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_websocket_avatar.py +0 -0
  783. {roomkit-0.7.2 → roomkit-0.9.0}/tests/video/test_websocket_video_backend.py +0 -0
  784. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/__init__.py +0 -0
  785. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/backends/__init__.py +0 -0
  786. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/backends/test_rtp.py +0 -0
  787. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/backends/test_sip_coverage.py +0 -0
  788. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/backends/test_webtransport.py +0 -0
  789. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/pipeline/__init__.py +0 -0
  790. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/pipeline/test_aicoustics_denoiser.py +0 -0
  791. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/pipeline/test_rnnoise_denoiser.py +0 -0
  792. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/pipeline/test_sherpa_diarization.py +0 -0
  793. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/pipeline/test_smart_turn.py +0 -0
  794. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/pipeline/test_speex_aec.py +0 -0
  795. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/realtime/__init__.py +0 -0
  796. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/realtime/test_fastrtc_transport.py +0 -0
  797. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/realtime/test_realtime_bridge.py +0 -0
  798. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/realtime/test_ws_transport.py +0 -0
  799. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/stt/__init__.py +0 -0
  800. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/stt/test_deepgram.py +0 -0
  801. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/stt/test_gradium_stt.py +0 -0
  802. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/stt/test_qwen3_asr.py +0 -0
  803. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/test_bridge.py +0 -0
  804. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/test_tts_filters.py +0 -0
  805. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/test_voice_tts_filter.py +0 -0
  806. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/tts/__init__.py +0 -0
  807. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/tts/test_elevenlabs.py +0 -0
  808. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/tts/test_gradium_tts.py +0 -0
  809. {roomkit-0.7.2 → roomkit-0.9.0}/tests/voice/tts/test_qwen3_tts.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: roomkit
3
- Version: 0.7.2
3
+ Version: 0.9.0
4
4
  Summary: Pure async Python library for multi-channel conversations
5
5
  Project-URL: Homepage, https://roomkit.live
6
6
  Project-URL: Documentation, https://www.roomkit.live/docs/
@@ -25,7 +25,7 @@ Requires-Dist: pydantic>=2.9
25
25
  Provides-Extra: aicoustics
26
26
  Requires-Dist: aic-sdk>=2.1; extra == 'aicoustics'
27
27
  Provides-Extra: all
28
- Requires-Dist: aiortp>=0.3.1; extra == 'all'
28
+ Requires-Dist: aiortp>=0.3.2; extra == 'all'
29
29
  Requires-Dist: aiosipua[rtp]>=0.4.1; extra == 'all'
30
30
  Requires-Dist: anthropic>=0.30; extra == 'all'
31
31
  Requires-Dist: asyncpg>=0.29; extra == 'all'
@@ -162,7 +162,7 @@ Requires-Dist: websockets>=13.0; extra == 'realtime-openai'
162
162
  Provides-Extra: redis
163
163
  Requires-Dist: redis>=5.0; extra == 'redis'
164
164
  Provides-Extra: rtp
165
- Requires-Dist: aiortp>=0.3.1; extra == 'rtp'
165
+ Requires-Dist: aiortp>=0.3.2; extra == 'rtp'
166
166
  Provides-Extra: screen-capture
167
167
  Requires-Dist: mss>=9.0; extra == 'screen-capture'
168
168
  Provides-Extra: screen-input
@@ -170,6 +170,7 @@ Requires-Dist: pyautogui>=0.9; extra == 'screen-input'
170
170
  Provides-Extra: sherpa-onnx
171
171
  Requires-Dist: sherpa-onnx>=1.10; extra == 'sherpa-onnx'
172
172
  Provides-Extra: sip
173
+ Requires-Dist: aiortp>=0.3.2; extra == 'sip'
173
174
  Requires-Dist: aiosipua[rtp]>=0.4.1; extra == 'sip'
174
175
  Provides-Extra: smart-turn
175
176
  Requires-Dist: numpy>=1.26; extra == 'smart-turn'
@@ -350,7 +351,7 @@ For development:
350
351
  git clone https://github.com/roomkit-live/roomkit.git
351
352
  cd roomkit
352
353
  uv sync --extra dev
353
- make all # ruff check + mypy --strict + pytest
354
+ make all # ruff check + ty + pytest
354
355
  ```
355
356
 
356
357
  Requires **Python 3.12+**.
@@ -729,7 +730,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.
729
730
 
730
731
  ```bash
731
732
  uv sync --extra dev
732
- make all # ruff check + mypy --strict + pytest
733
+ make all # ruff check + ty + pytest
733
734
  ```
734
735
 
735
736
  All new code needs tests. Aim for >90% coverage.
@@ -140,7 +140,7 @@ For development:
140
140
  git clone https://github.com/roomkit-live/roomkit.git
141
141
  cd roomkit
142
142
  uv sync --extra dev
143
- make all # ruff check + mypy --strict + pytest
143
+ make all # ruff check + ty + pytest
144
144
  ```
145
145
 
146
146
  Requires **Python 3.12+**.
@@ -519,7 +519,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.
519
519
 
520
520
  ```bash
521
521
  uv sync --extra dev
522
- make all # ruff check + mypy --strict + pytest
522
+ make all # ruff check + ty + pytest
523
523
  ```
524
524
 
525
525
  All new code needs tests. Aim for >90% coverage.
@@ -52,8 +52,8 @@ video = ["av>=12.0.0", "numpy>=1.26"]
52
52
  video-overlay = ["Pillow>=10.0"]
53
53
  yolo = ["ultralytics>=8.3"]
54
54
  mediapipe = ["mediapipe>=0.10"]
55
- rtp = ["aiortp>=0.3.1"]
56
- sip = ["aiosipua[rtp]>=0.4.1"]
55
+ rtp = ["aiortp>=0.3.2"]
56
+ sip = ["aiosipua[rtp]>=0.4.1", "aiortp>=0.3.2"]
57
57
  webtransport = ["aioquic>=1.0"]
58
58
  twilio = ["twilio>=9.0"]
59
59
  phonenumbers = ["phonenumbers>=8.13"]
@@ -0,0 +1 @@
1
+ __version__ = "0.9.0"
@@ -53,6 +53,7 @@ class AIContextHost(Protocol):
53
53
  _max_tokens: Default max tokens (overridable per room).
54
54
  _thinking_budget: Optional thinking budget for extended thinking.
55
55
  _skills: Skill registry for tool injection.
56
+ _skills_in_prompt: Whether to auto-inject the skills manifest into the prompt.
56
57
  _script_executor: Script executor for skill scripts.
57
58
  _sandbox: Sandbox executor for ad-hoc command execution.
58
59
  _memory: Memory provider for conversation retrieval.
@@ -75,6 +76,7 @@ class AIContextHost(Protocol):
75
76
  _max_tokens: int
76
77
  _thinking_budget: int | None
77
78
  _skills: SkillRegistry | None
79
+ _skills_in_prompt: bool
78
80
  _script_executor: ScriptExecutor | None
79
81
  _sandbox: SandboxExecutor | None
80
82
  _human_input_handler: HumanInputToolHandler | None
@@ -105,6 +107,7 @@ class AIContextMixin:
105
107
  _max_tokens: int
106
108
  _thinking_budget: int | None
107
109
  _skills: SkillRegistry | None
110
+ _skills_in_prompt: bool
108
111
  _script_executor: ScriptExecutor | None
109
112
  _sandbox: SandboxExecutor | None
110
113
  _human_input_handler: HumanInputToolHandler | None
@@ -183,15 +186,18 @@ class AIContextMixin:
183
186
  existing_names = {t.name for t in tools}
184
187
  tools.extend(t for t in hi_tools if t.name not in existing_names)
185
188
 
186
- # Inject skill tools and prompt (infra tools added here, gated tools later)
189
+ # Inject skill tools and prompt (infra tools added here, gated tools later).
190
+ # The prompt block is skipped when the host renders its own skills
191
+ # manifest inside ``system_prompt`` (``skills_in_prompt=False``).
187
192
  if self._skills and self._skills.skill_count > 0:
188
193
  tools.extend(self._skill_tools())
189
- preamble = _SKILLS_PREAMBLE
190
- if not self._script_executor:
191
- preamble += _SKILLS_NO_SCRIPTS_NOTE
192
- skills_xml = self._skills.to_prompt_xml()
193
- skill_block = f"\n\n{preamble}\n\n{skills_xml}"
194
- system_prompt = (system_prompt or "") + skill_block
194
+ if self._skills_in_prompt:
195
+ preamble = _SKILLS_PREAMBLE
196
+ if not self._script_executor:
197
+ preamble += _SKILLS_NO_SCRIPTS_NOTE
198
+ skills_xml = self._skills.to_prompt_xml()
199
+ skill_block = f"\n\n{preamble}\n\n{skills_xml}"
200
+ system_prompt = (system_prompt or "") + skill_block
195
201
 
196
202
  # Inject sandbox tools and preamble
197
203
  if self._sandbox is not None:
@@ -13,6 +13,11 @@ if TYPE_CHECKING:
13
13
 
14
14
  logger = logging.getLogger("roomkit.channels.ai")
15
15
 
16
+ # Per-event cap on the ``thinking`` payload published to the realtime bus.
17
+ # Producers that must deliver longer text without loss (e.g. the streaming
18
+ # coalescer) split it into multiple events of at most this size.
19
+ THINKING_PREVIEW_LIMIT = 1000
20
+
16
21
 
17
22
  class AIEventsMixin:
18
23
  """Publishes tool-call and thinking ephemeral events over the realtime backend."""
@@ -80,7 +85,7 @@ class AIEventsMixin:
80
85
  """Publish a thinking ephemeral event. Best-effort, never breaks the loop."""
81
86
  if self._realtime is None or not room_id:
82
87
  return
83
- preview_limit = 1000
88
+ preview_limit = THINKING_PREVIEW_LIMIT
84
89
  data: dict[str, Any] = {
85
90
  "thinking": thinking[:preview_limit] if len(thinking) > preview_limit else thinking,
86
91
  "thinking_length": len(thinking),
@@ -87,6 +87,7 @@ class AIGenerationHost(Protocol):
87
87
  _max_tool_rounds: int
88
88
  _tool_loop_timeout_seconds: float | None
89
89
  _tool_loop_warn_after: int
90
+ _max_empty_retries: int
90
91
  _tool_handler: Any
91
92
  _active_loops: dict[str, _ToolLoopContext]
92
93
  _after_response_hook: Any
@@ -143,6 +144,7 @@ class AIGenerationMixin:
143
144
  _max_tool_rounds: int
144
145
  _tool_loop_timeout_seconds: float | None
145
146
  _tool_loop_warn_after: int
147
+ _max_empty_retries: int
146
148
  _tool_handler: Any
147
149
  _active_loops: dict[str, _ToolLoopContext]
148
150
  _after_response_hook: Any
@@ -429,16 +431,19 @@ class AIGenerationMixin:
429
431
  self, context: AIContext, *, parent_span_id: str | None = None
430
432
  ) -> ToolLoopResult:
431
433
  """Generate -> execute tools -> re-generate until a text response."""
432
- from roomkit.channels.ai import _current_loop_ctx, _ToolLoopContext
434
+ from roomkit.channels.ai import (
435
+ _EMPTY_RETRY_NUDGE,
436
+ _current_loop_ctx,
437
+ _ToolLoopContext,
438
+ )
433
439
 
434
- loop_ctx = _ToolLoopContext()
435
- loop_ctx.loop_id = str(id(loop_ctx))
436
- parent_lctx = _current_loop_ctx.get()
437
- if parent_lctx is not None:
438
- loop_ctx.current_participant_role = parent_lctx.current_participant_role
440
+ loop_ctx = _ToolLoopContext.for_loop(
441
+ _current_loop_ctx.get(), context.room.room.id if context.room else None
442
+ )
439
443
  _current_loop_ctx.set(loop_ctx)
440
444
  self._active_loops[loop_ctx.loop_id] = loop_ctx
441
445
  rounds: list[ToolRound] = []
446
+ empty_retries = 0
442
447
  try:
443
448
  context, should_cancel = self._drain_steering_queue(context, loop_ctx)
444
449
  if should_cancel:
@@ -462,6 +467,28 @@ class AIGenerationMixin:
462
467
 
463
468
  for round_idx in range(self._max_tool_rounds):
464
469
  if not response.tool_calls or self._tool_handler is None:
470
+ # Final answer reached. If it is empty *after* we ran tools,
471
+ # the model skipped verbalizing the result — re-prompt once
472
+ # (bounded) for the final answer instead of returning nothing.
473
+ if (
474
+ self._tool_handler is not None
475
+ and rounds
476
+ and not (response.content or "").strip()
477
+ and empty_retries < self._max_empty_retries
478
+ and not loop_ctx.cancel_event.is_set()
479
+ and not (deadline and asyncio.get_running_loop().time() >= deadline)
480
+ ):
481
+ empty_retries += 1
482
+ logger.warning(
483
+ "Empty response after %d tool round(s); re-prompting for "
484
+ "final answer (retry %d/%d)",
485
+ len(rounds),
486
+ empty_retries,
487
+ self._max_empty_retries,
488
+ )
489
+ context.messages.append(AIMessage(role="user", content=_EMPTY_RETRY_NUDGE))
490
+ response = await self._generate_with_retry(context)
491
+ continue
465
492
  break
466
493
 
467
494
  if loop_ctx.cancel_event.is_set():
@@ -8,6 +8,7 @@ import time
8
8
  from collections.abc import AsyncIterator
9
9
  from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
10
10
 
11
+ from roomkit.channels._ai_events import THINKING_PREVIEW_LIMIT
11
12
  from roomkit.models.channel import ChannelOutput
12
13
  from roomkit.models.enums import ChannelType
13
14
  from roomkit.models.event import RoomEvent
@@ -41,6 +42,69 @@ if TYPE_CHECKING:
41
42
  logger = logging.getLogger("roomkit.channels.ai")
42
43
 
43
44
 
45
+ class _ThinkingCoalescer:
46
+ """Batches per-token thinking deltas into one ``THINKING_DELTA`` publish per window.
47
+
48
+ Reasoning models emit one ``StreamThinkingDelta`` per token, and publishing
49
+ each on the realtime bus is one ephemeral event + fan-out + WS serialise per
50
+ token — thousands for a long trace, all on the shared event loop. Buffering
51
+ and publishing once per time/size window (~80 ms / ~256 chars) cuts that
52
+ 10-100x while keeping the reasoning visibly real-time: the UI appends deltas,
53
+ so a coalesced delta renders identically to many small ones. The complete
54
+ trace is still published verbatim at ``THINKING_END``.
55
+
56
+ A window of ``0`` ms disables batching — every delta publishes immediately.
57
+ Flushes larger than ``_publish_thinking_event``'s preview cap are split
58
+ into multiple publishes so a coalesced delta is never truncated, whatever
59
+ the configured size threshold.
60
+ """
61
+
62
+ def __init__(
63
+ self,
64
+ publish: Any,
65
+ room_id: str | None,
66
+ round_idx: int,
67
+ *,
68
+ flush_ms: float,
69
+ flush_chars: int,
70
+ ) -> None:
71
+ self._publish = publish
72
+ self._room_id = room_id
73
+ self._round_idx = round_idx
74
+ self._flush_ms = flush_ms
75
+ self._flush_chars = flush_chars
76
+ self._pending: list[str] = []
77
+ self._pending_len = 0
78
+ self._last_publish = time.monotonic()
79
+
80
+ async def add(self, delta: str) -> None:
81
+ """Buffer a delta; publish the batch once the window is exceeded."""
82
+ self._pending.append(delta)
83
+ self._pending_len += len(delta)
84
+ if self._flush_ms <= 0:
85
+ await self.flush()
86
+ return
87
+ elapsed_ms = (time.monotonic() - self._last_publish) * 1000.0
88
+ if self._pending_len >= self._flush_chars or elapsed_ms >= self._flush_ms:
89
+ await self.flush()
90
+
91
+ async def flush(self) -> None:
92
+ """Publish whatever is buffered, then reset the window."""
93
+ if not self._pending:
94
+ return
95
+ text = "".join(self._pending)
96
+ self._pending.clear()
97
+ self._pending_len = 0
98
+ self._last_publish = time.monotonic()
99
+ for i in range(0, len(text), THINKING_PREVIEW_LIMIT):
100
+ await self._publish(
101
+ EphemeralEventType.THINKING_DELTA,
102
+ self._room_id,
103
+ text[i : i + THINKING_PREVIEW_LIMIT],
104
+ self._round_idx,
105
+ )
106
+
107
+
44
108
  @runtime_checkable
45
109
  class AIStreamingHost(Protocol):
46
110
  """Contract: capabilities a host class must provide for AIStreamingMixin.
@@ -70,6 +134,9 @@ class AIStreamingHost(Protocol):
70
134
  _max_tool_rounds: int
71
135
  _tool_loop_timeout_seconds: float | None
72
136
  _tool_loop_warn_after: int
137
+ _max_empty_retries: int
138
+ _thinking_coalesce_ms: float
139
+ _thinking_coalesce_chars: int
73
140
  _tool_handler: Any
74
141
  _active_loops: dict[str, _ToolLoopContext]
75
142
  _after_response_hook: Any
@@ -126,6 +193,9 @@ class AIStreamingMixin:
126
193
  _max_tool_rounds: int
127
194
  _tool_loop_timeout_seconds: float | None
128
195
  _tool_loop_warn_after: int
196
+ _max_empty_retries: int
197
+ _thinking_coalesce_ms: float
198
+ _thinking_coalesce_chars: int
129
199
  _tool_handler: Any
130
200
  _active_loops: dict[str, Any]
131
201
  _after_response_hook: Any
@@ -147,6 +217,16 @@ class AIStreamingMixin:
147
217
  _publish_tool_event: Any # see AIStreamingHost
148
218
  _telemetry_provider: Any # see AIStreamingHost
149
219
 
220
+ def _new_thinking_coalescer(self, room_id: str | None, round_idx: int) -> _ThinkingCoalescer:
221
+ """Coalescer bound to this channel's publish hook and window config."""
222
+ return _ThinkingCoalescer(
223
+ self._publish_thinking_event,
224
+ room_id,
225
+ round_idx,
226
+ flush_ms=self._thinking_coalesce_ms,
227
+ flush_chars=self._thinking_coalesce_chars,
228
+ )
229
+
150
230
  async def _start_streaming_response(
151
231
  self, event: RoomEvent, binding: ChannelBinding, context: RoomContext
152
232
  ) -> ChannelOutput:
@@ -190,6 +270,7 @@ class AIStreamingMixin:
190
270
  room_id = ai_context.room.room.id if ai_context.room else None
191
271
  thinking_parts: list[str] = []
192
272
  thinking_started = False
273
+ coalescer = self._new_thinking_coalescer(room_id, round_idx=0)
193
274
 
194
275
  async for ev in self._provider.generate_structured_stream(ai_context):
195
276
  if isinstance(ev, StreamThinkingDelta):
@@ -199,19 +280,17 @@ class AIStreamingMixin:
199
280
  EphemeralEventType.THINKING_START, room_id, "", 0
200
281
  )
201
282
  thinking_parts.append(ev.thinking)
202
- # Publish each delta on the realtime bus so remote subscribers
203
- # (browser WS clients, etc.) see the reasoning stream as it
204
- # arrives, not only the buffered text at THINKING_END. The
205
- # ``thinking`` field carries the per-chunk delta, not the
283
+ # Buffer each delta and publish in windows on the realtime bus so
284
+ # remote subscribers (browser WS clients, etc.) stream the
285
+ # reasoning as it arrives, not only the buffered text at
286
+ # THINKING_END. The ``thinking`` field carries the delta, not the
206
287
  # accumulator — clients append to their own buffer.
207
- if room_id:
208
- await self._publish_thinking_event(
209
- EphemeralEventType.THINKING_DELTA, room_id, ev.thinking, 0
210
- )
288
+ await coalescer.add(ev.thinking)
211
289
  yield ThinkingDeltaMarker(thinking=ev.thinking)
212
290
  elif isinstance(ev, StreamTextDelta):
213
291
  if thinking_started and thinking_parts and room_id:
214
292
  thinking_started = False
293
+ await coalescer.flush()
215
294
  await self._publish_thinking_event(
216
295
  EphemeralEventType.THINKING_END,
217
296
  room_id,
@@ -224,6 +303,7 @@ class AIStreamingMixin:
224
303
  # Thinking with no following text — close the boundary anyway so
225
304
  # subscribers see the reasoning even if the model emitted nothing else.
226
305
  if thinking_started and thinking_parts and room_id:
306
+ await coalescer.flush()
227
307
  await self._publish_thinking_event(
228
308
  EphemeralEventType.THINKING_END,
229
309
  room_id,
@@ -235,26 +315,42 @@ class AIStreamingMixin:
235
315
  self, event: RoomEvent, binding: ChannelBinding, context: RoomContext
236
316
  ) -> ChannelOutput:
237
317
  """Return a streaming response that handles tool calls between rounds."""
318
+ from roomkit.channels.ai import _current_loop_ctx
319
+
238
320
  ai_context = await self._build_context(event, binding, context) # ty: ignore[unresolved-attribute]
239
321
  ai_context, blocked = await self._fire_before_generation_hook(ai_context, event) # ty: ignore[unresolved-attribute]
240
322
  if blocked:
241
323
  return ChannelOutput.empty()
324
+ # The generator below executes when the CONSUMER iterates the
325
+ # stream — by then handle_event has reset the loop contextvar, so
326
+ # the parent ctx (participant role, room, the toolset stamped by
327
+ # _build_context) must be captured NOW and passed explicitly.
242
328
  return ChannelOutput(
243
329
  responded=True,
244
- response_stream=self._run_streaming_tool_loop(ai_context),
330
+ response_stream=self._run_streaming_tool_loop(
331
+ ai_context, parent_loop_ctx=_current_loop_ctx.get()
332
+ ),
245
333
  response_metadata=ai_context.response_metadata,
246
334
  )
247
335
 
248
- async def _run_streaming_tool_loop(self, context: AIContext) -> AsyncIterator[StreamDelta]:
336
+ async def _run_streaming_tool_loop(
337
+ self, context: AIContext, *, parent_loop_ctx: Any | None = None
338
+ ) -> AsyncIterator[StreamDelta]:
249
339
  """Stream text deltas, executing tool calls between generation rounds."""
250
- from roomkit.channels.ai import _current_loop_ctx, _ToolLoopContext
340
+ from roomkit.channels.ai import (
341
+ _EMPTY_RETRY_NUDGE,
342
+ _current_loop_ctx,
343
+ _ToolLoopContext,
344
+ )
251
345
  from roomkit.telemetry.context import get_current_span
252
346
 
253
- loop_ctx = _ToolLoopContext()
254
- loop_ctx.loop_id = str(id(loop_ctx))
255
- parent_ctx = _current_loop_ctx.get()
256
- if parent_ctx is not None:
257
- loop_ctx.current_participant_role = parent_ctx.current_participant_role
347
+ # The handle_event ctx is gone from the contextvar by the time this
348
+ # generator runs (reset in handle_event's finally); the caller
349
+ # captured it at stream creation.
350
+ parent_ctx = parent_loop_ctx if parent_loop_ctx is not None else _current_loop_ctx.get()
351
+ loop_ctx = _ToolLoopContext.for_loop(
352
+ parent_ctx, context.room.room.id if context.room else None
353
+ )
258
354
  _current_loop_ctx.set(loop_ctx)
259
355
  self._active_loops[loop_ctx.loop_id] = loop_ctx
260
356
  telemetry = self._telemetry_provider
@@ -287,6 +383,8 @@ class AIStreamingMixin:
287
383
  )
288
384
 
289
385
  _dedup_prefix = ""
386
+ _saw_tool_call_any = False
387
+ _empty_retries = 0
290
388
 
291
389
  for _round_idx in range(self._max_tool_rounds + 1):
292
390
  if loop_ctx.cancel_event.is_set():
@@ -302,6 +400,7 @@ class AIStreamingMixin:
302
400
  text_parts: list[str] = []
303
401
  tool_calls: list[StreamToolCall] = []
304
402
  thinking_started = False
403
+ coalescer = self._new_thinking_coalescer(room_id, round_idx=_round_idx)
305
404
  _dedup_active = bool(_dedup_prefix)
306
405
  _dedup_offset = 0
307
406
  _dedup_buffer: list[str] = []
@@ -323,23 +422,18 @@ class AIStreamingMixin:
323
422
  _round_idx,
324
423
  )
325
424
  thinking_parts.append(event.thinking)
326
- # Publish the per-chunk delta on the realtime bus so
327
- # remote WS subscribers stream the reasoning live; the
328
- # buffered THINKING_END below still fires so observers
329
- # joining mid-stream can recover the complete trace.
330
- if room_id:
331
- await self._publish_thinking_event(
332
- EphemeralEventType.THINKING_DELTA,
333
- room_id,
334
- event.thinking,
335
- _round_idx,
336
- )
425
+ # Buffer the per-chunk delta and publish in windows on the
426
+ # realtime bus so remote WS subscribers stream the reasoning
427
+ # live; the buffered THINKING_END below still fires so
428
+ # observers joining mid-stream recover the complete trace.
429
+ await coalescer.add(event.thinking)
337
430
  # Inline marker so channels can render reasoning in
338
431
  # arrival order with text deltas.
339
432
  yield ThinkingDeltaMarker(thinking=event.thinking)
340
433
  elif isinstance(event, StreamTextDelta):
341
434
  if thinking_started and thinking_parts and room_id:
342
435
  thinking_started = False
436
+ await coalescer.flush()
343
437
  await self._publish_thinking_event(
344
438
  EphemeralEventType.THINKING_END,
345
439
  room_id,
@@ -457,6 +551,7 @@ class AIStreamingMixin:
457
551
  _dedup_buffer.clear()
458
552
 
459
553
  if thinking_started and thinking_parts and room_id:
554
+ await coalescer.flush()
460
555
  await self._publish_thinking_event(
461
556
  EphemeralEventType.THINKING_END,
462
557
  room_id,
@@ -465,8 +560,28 @@ class AIStreamingMixin:
465
560
  )
466
561
 
467
562
  if not tool_calls:
563
+ # Final answer round. If it produced no text *after* a tool
564
+ # round, the model skipped verbalizing the result — re-prompt
565
+ # once (bounded) for the final answer instead of ending empty.
566
+ if (
567
+ _saw_tool_call_any
568
+ and not "".join(text_parts).strip()
569
+ and _empty_retries < self._max_empty_retries
570
+ and not (deadline and asyncio.get_running_loop().time() >= deadline)
571
+ ):
572
+ _empty_retries += 1
573
+ logger.warning(
574
+ "Streaming empty response after tools; re-prompting for "
575
+ "final answer (retry %d/%d)",
576
+ _empty_retries,
577
+ self._max_empty_retries,
578
+ )
579
+ context.messages.append(AIMessage(role="user", content=_EMPTY_RETRY_NUDGE))
580
+ continue
468
581
  return
469
582
 
583
+ _saw_tool_call_any = True
584
+
470
585
  # External tools: provider executed them internally.
471
586
  # If ExternalToolHandler is set, hooks were already fired
472
587
  # inline during streaming (see StreamToolCall handling above).