roomkit 0.7.2__tar.gz → 0.8.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 (805) hide show
  1. {roomkit-0.7.2 → roomkit-0.8.0}/PKG-INFO +3 -3
  2. {roomkit-0.7.2 → roomkit-0.8.0}/README.md +2 -2
  3. roomkit-0.8.0/src/roomkit/_version.py +1 -0
  4. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_ai_context.py +13 -7
  5. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_ai_generation.py +33 -6
  6. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_ai_streaming.py +48 -8
  7. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_tool_eviction.py +22 -7
  8. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/ai.py +47 -1
  9. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/event_router.py +7 -14
  10. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/framework.py +17 -10
  11. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/__init__.py +2 -0
  12. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/inbound.py +16 -0
  13. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/inbound_locked.py +158 -64
  14. roomkit-0.8.0/src/roomkit/core/mixins/regenerate.py +143 -0
  15. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/channel.py +10 -0
  16. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/delivery.py +5 -0
  17. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/telegram/bot.py +36 -0
  18. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tools/__init__.py +3 -0
  19. roomkit-0.8.0/src/roomkit/tools/context.py +48 -0
  20. roomkit-0.8.0/tests/test_channels/test_ai_empty_retry.py +137 -0
  21. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_ai_skill_gating.py +52 -0
  22. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_ai_tool_loop.py +3 -2
  23. roomkit-0.8.0/tests/test_inbound_visibility.py +58 -0
  24. roomkit-0.8.0/tests/test_integration/test_regenerate.py +132 -0
  25. roomkit-0.8.0/tests/test_rfc_conformance.py +230 -0
  26. roomkit-0.8.0/tests/test_tool_context.py +159 -0
  27. roomkit-0.8.0/tests/test_tool_eviction_room_scope.py +71 -0
  28. roomkit-0.7.2/src/roomkit/_version.py +0 -1
  29. {roomkit-0.7.2 → roomkit-0.8.0}/.gitignore +0 -0
  30. {roomkit-0.7.2 → roomkit-0.8.0}/AGENTS.md +0 -0
  31. {roomkit-0.7.2 → roomkit-0.8.0}/LICENSE +0 -0
  32. {roomkit-0.7.2 → roomkit-0.8.0}/docs/README.md +0 -0
  33. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/ai-channels.md +0 -0
  34. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/api-reference.md +0 -0
  35. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/architecture.md +0 -0
  36. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/hooks.md +0 -0
  37. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/identity-and-realtime.md +0 -0
  38. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/installation.md +0 -0
  39. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/ollama-provider.md +0 -0
  40. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/orchestration.md +0 -0
  41. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/overview.md +0 -0
  42. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/quickstart.md +0 -0
  43. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/realtime-voice.md +0 -0
  44. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/resilience.md +0 -0
  45. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/rooms-and-channels.md +0 -0
  46. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/storage.md +0 -0
  47. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/testing.md +0 -0
  48. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/transport-providers.md +0 -0
  49. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/voice-channels.md +0 -0
  50. {roomkit-0.7.2 → roomkit-0.8.0}/docs/c7/voice-pipeline.md +0 -0
  51. {roomkit-0.7.2 → roomkit-0.8.0}/docs/diagrams/architecture.svg +0 -0
  52. {roomkit-0.7.2 → roomkit-0.8.0}/docs/diagrams/avatar-pipeline.svg +0 -0
  53. {roomkit-0.7.2 → roomkit-0.8.0}/docs/diagrams/message-flow.svg +0 -0
  54. {roomkit-0.7.2 → roomkit-0.8.0}/docs/diagrams/orchestration.svg +0 -0
  55. {roomkit-0.7.2 → roomkit-0.8.0}/docs/diagrams/room-lifecycle.svg +0 -0
  56. {roomkit-0.7.2 → roomkit-0.8.0}/docs/diagrams/video-pipeline.svg +0 -0
  57. {roomkit-0.7.2 → roomkit-0.8.0}/docs/diagrams/voice-orchestration.svg +0 -0
  58. {roomkit-0.7.2 → roomkit-0.8.0}/docs/diagrams/voice-pipeline.svg +0 -0
  59. {roomkit-0.7.2 → roomkit-0.8.0}/llms-full.txt +0 -0
  60. {roomkit-0.7.2 → roomkit-0.8.0}/llms.txt +0 -0
  61. {roomkit-0.7.2 → roomkit-0.8.0}/pyproject.toml +0 -0
  62. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/__init__.py +0 -0
  63. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/ai_docs.py +0 -0
  64. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/__init__.py +0 -0
  65. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_ai_events.py +0 -0
  66. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_ai_policy.py +0 -0
  67. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_ai_resilience.py +0 -0
  68. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_ai_steering.py +0 -0
  69. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_ai_tools.py +0 -0
  70. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_dangling_recovery.py +0 -0
  71. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_realtime_audio.py +0 -0
  72. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_realtime_context.py +0 -0
  73. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_realtime_response.py +0 -0
  74. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_realtime_skills.py +0 -0
  75. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_realtime_speech.py +0 -0
  76. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_realtime_tool_recovery.py +0 -0
  77. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_realtime_tool_search.py +0 -0
  78. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_realtime_tools.py +0 -0
  79. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_realtime_transcription.py +0 -0
  80. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_sandbox_handlers.py +0 -0
  81. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_skill_constants.py +0 -0
  82. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_skill_handlers.py +0 -0
  83. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_task_planner.py +0 -0
  84. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_tool_search_constants.py +0 -0
  85. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_turn_config.py +0 -0
  86. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_video_hooks.py +0 -0
  87. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_voice_hooks.py +0 -0
  88. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_voice_pipeline.py +0 -0
  89. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_voice_stt.py +0 -0
  90. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_voice_tts.py +0 -0
  91. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/_voice_turn.py +0 -0
  92. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/agent.py +0 -0
  93. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/av.py +0 -0
  94. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/base.py +0 -0
  95. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/cli.py +0 -0
  96. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/realtime_av.py +0 -0
  97. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/realtime_voice.py +0 -0
  98. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/transport.py +0 -0
  99. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/video.py +0 -0
  100. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/voice.py +0 -0
  101. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/channels/websocket.py +0 -0
  102. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/console/__init__.py +0 -0
  103. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/console/_display.py +0 -0
  104. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/console/_hooks.py +0 -0
  105. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/console/_state.py +0 -0
  106. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/__init__.py +0 -0
  107. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/circuit_breaker.py +0 -0
  108. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/delivery.py +0 -0
  109. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/exceptions.py +0 -0
  110. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/hooks.py +0 -0
  111. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/inbound_router.py +0 -0
  112. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/locks.py +0 -0
  113. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/channel_ops.py +0 -0
  114. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/delegation.py +0 -0
  115. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/deliver.py +0 -0
  116. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/greeting.py +0 -0
  117. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/helpers.py +0 -0
  118. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/hooks_api.py +0 -0
  119. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/inbound_identity.py +0 -0
  120. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/inbound_streaming.py +0 -0
  121. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/realtime_ops.py +0 -0
  122. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/recording.py +0 -0
  123. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/room_lifecycle.py +0 -0
  124. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/source_ops.py +0 -0
  125. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/mixins/voice_ops.py +0 -0
  126. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/rate_limiter.py +0 -0
  127. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/retry.py +0 -0
  128. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/router.py +0 -0
  129. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/task_utils.py +0 -0
  130. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/core/transcoder.py +0 -0
  131. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/delivery/__init__.py +0 -0
  132. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/delivery/base.py +0 -0
  133. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/delivery/memory.py +0 -0
  134. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/delivery/redis.py +0 -0
  135. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/delivery/serialization.py +0 -0
  136. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/delivery/worker.py +0 -0
  137. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/identity/__init__.py +0 -0
  138. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/identity/base.py +0 -0
  139. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/identity/mock.py +0 -0
  140. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/knowledge/__init__.py +0 -0
  141. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/knowledge/base.py +0 -0
  142. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/knowledge/mock.py +0 -0
  143. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/knowledge/postgres.py +0 -0
  144. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/memory/__init__.py +0 -0
  145. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/memory/base.py +0 -0
  146. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/memory/budget_aware.py +0 -0
  147. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/memory/compacting.py +0 -0
  148. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/memory/mock.py +0 -0
  149. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/memory/retrieval.py +0 -0
  150. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/memory/sliding_window.py +0 -0
  151. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/memory/summarizing.py +0 -0
  152. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/memory/token_estimator.py +0 -0
  153. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/__init__.py +0 -0
  154. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/context.py +0 -0
  155. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/enums.py +0 -0
  156. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/event.py +0 -0
  157. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/framework_event.py +0 -0
  158. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/hook.py +0 -0
  159. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/identity.py +0 -0
  160. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/participant.py +0 -0
  161. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/pending_input.py +0 -0
  162. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/room.py +0 -0
  163. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/session_event.py +0 -0
  164. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/steering.py +0 -0
  165. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/store_filter.py +0 -0
  166. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/streaming.py +0 -0
  167. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/task.py +0 -0
  168. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/tool_call.py +0 -0
  169. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/trace.py +0 -0
  170. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/models/vision_event.py +0 -0
  171. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/__init__.py +0 -0
  172. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/base.py +0 -0
  173. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/handoff.py +0 -0
  174. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/pipeline.py +0 -0
  175. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/router.py +0 -0
  176. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/session_audit.py +0 -0
  177. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/state.py +0 -0
  178. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/status_bus.py +0 -0
  179. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/strategies/__init__.py +0 -0
  180. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/strategies/loop.py +0 -0
  181. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/strategies/pipeline.py +0 -0
  182. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/strategies/supervisor.py +0 -0
  183. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/strategies/swarm.py +0 -0
  184. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/orchestration/tool_audit.py +0 -0
  185. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/__init__.py +0 -0
  186. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/ai/__init__.py +0 -0
  187. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/ai/base.py +0 -0
  188. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/ai/mock.py +0 -0
  189. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/anam/__init__.py +0 -0
  190. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/anam/_convert.py +0 -0
  191. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/anam/avatar.py +0 -0
  192. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/anam/config.py +0 -0
  193. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/anam/realtime.py +0 -0
  194. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/anthropic/__init__.py +0 -0
  195. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/anthropic/ai.py +0 -0
  196. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/anthropic/config.py +0 -0
  197. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/azure/__init__.py +0 -0
  198. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/azure/ai.py +0 -0
  199. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/azure/config.py +0 -0
  200. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/elasticemail/__init__.py +0 -0
  201. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/elasticemail/config.py +0 -0
  202. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/elasticemail/email.py +0 -0
  203. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/elevenlabs/__init__.py +0 -0
  204. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/elevenlabs/config.py +0 -0
  205. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/elevenlabs/realtime.py +0 -0
  206. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/email/__init__.py +0 -0
  207. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/email/base.py +0 -0
  208. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/email/mock.py +0 -0
  209. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/gemini/__init__.py +0 -0
  210. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/gemini/ai.py +0 -0
  211. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/gemini/config.py +0 -0
  212. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/gemini/realtime.py +0 -0
  213. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/gemini/schema.py +0 -0
  214. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/http/__init__.py +0 -0
  215. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/http/base.py +0 -0
  216. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/http/config.py +0 -0
  217. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/http/mock.py +0 -0
  218. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/http/provider.py +0 -0
  219. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/http/webhook.py +0 -0
  220. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/http_errors.py +0 -0
  221. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/messenger/__init__.py +0 -0
  222. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/messenger/base.py +0 -0
  223. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/messenger/config.py +0 -0
  224. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/messenger/facebook.py +0 -0
  225. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/messenger/mock.py +0 -0
  226. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/messenger/webhook.py +0 -0
  227. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/mistral/__init__.py +0 -0
  228. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/mistral/ai.py +0 -0
  229. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/mistral/config.py +0 -0
  230. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/ollama/__init__.py +0 -0
  231. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/ollama/ai.py +0 -0
  232. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/ollama/config.py +0 -0
  233. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/openai/__init__.py +0 -0
  234. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/openai/ai.py +0 -0
  235. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/openai/config.py +0 -0
  236. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/openai/realtime.py +0 -0
  237. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/personaplex/__init__.py +0 -0
  238. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/personaplex/config.py +0 -0
  239. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/personaplex/realtime.py +0 -0
  240. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/rcs/__init__.py +0 -0
  241. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/rcs/base.py +0 -0
  242. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/rcs/mock.py +0 -0
  243. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/sendgrid/__init__.py +0 -0
  244. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/sendgrid/config.py +0 -0
  245. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/sendgrid/email.py +0 -0
  246. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/sinch/__init__.py +0 -0
  247. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/sinch/config.py +0 -0
  248. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/sinch/sms.py +0 -0
  249. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/sms/__init__.py +0 -0
  250. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/sms/base.py +0 -0
  251. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/sms/meta.py +0 -0
  252. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/sms/mock.py +0 -0
  253. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/sms/phone.py +0 -0
  254. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/teams/__init__.py +0 -0
  255. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/teams/base.py +0 -0
  256. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/teams/bot_framework.py +0 -0
  257. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/teams/config.py +0 -0
  258. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/teams/conversation_store.py +0 -0
  259. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/teams/mock.py +0 -0
  260. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/teams/models.py +0 -0
  261. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/teams/webhook.py +0 -0
  262. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/telegram/__init__.py +0 -0
  263. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/telegram/base.py +0 -0
  264. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/telegram/config.py +0 -0
  265. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/telegram/mock.py +0 -0
  266. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/telegram/webhook.py +0 -0
  267. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/telnyx/__init__.py +0 -0
  268. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/telnyx/_signature.py +0 -0
  269. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/telnyx/config.py +0 -0
  270. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/telnyx/rcs.py +0 -0
  271. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/telnyx/sms.py +0 -0
  272. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/twilio/__init__.py +0 -0
  273. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/twilio/config.py +0 -0
  274. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/twilio/rcs.py +0 -0
  275. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/twilio/sms.py +0 -0
  276. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/twilio/webhook.py +0 -0
  277. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/url_safety.py +0 -0
  278. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/utils.py +0 -0
  279. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/vllm/__init__.py +0 -0
  280. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/vllm/config.py +0 -0
  281. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/voicemeup/__init__.py +0 -0
  282. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/voicemeup/config.py +0 -0
  283. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/voicemeup/sms.py +0 -0
  284. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/whatsapp/__init__.py +0 -0
  285. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/whatsapp/base.py +0 -0
  286. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/whatsapp/mock.py +0 -0
  287. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/whatsapp/personal.py +0 -0
  288. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/xai/__init__.py +0 -0
  289. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/xai/config.py +0 -0
  290. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/providers/xai/realtime.py +0 -0
  291. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/py.typed +0 -0
  292. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/realtime/__init__.py +0 -0
  293. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/realtime/base.py +0 -0
  294. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/realtime/memory.py +0 -0
  295. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/recorder/__init__.py +0 -0
  296. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/recorder/_pyav_mux.py +0 -0
  297. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/recorder/_room_recorder_manager.py +0 -0
  298. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/recorder/base.py +0 -0
  299. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/recorder/mock.py +0 -0
  300. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/recorder/pyav.py +0 -0
  301. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/sandbox/__init__.py +0 -0
  302. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/sandbox/executor.py +0 -0
  303. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/sandbox/models.py +0 -0
  304. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/sandbox/tools.py +0 -0
  305. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/scoring/__init__.py +0 -0
  306. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/scoring/base.py +0 -0
  307. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/scoring/hook.py +0 -0
  308. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/scoring/mock.py +0 -0
  309. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/scoring/tracker.py +0 -0
  310. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/skills/__init__.py +0 -0
  311. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/skills/executor.py +0 -0
  312. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/skills/models.py +0 -0
  313. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/skills/parser.py +0 -0
  314. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/skills/registry.py +0 -0
  315. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/sources/__init__.py +0 -0
  316. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/sources/base.py +0 -0
  317. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/sources/neonize.py +0 -0
  318. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/sources/sse.py +0 -0
  319. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/sources/websocket.py +0 -0
  320. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/store/__init__.py +0 -0
  321. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/store/base.py +0 -0
  322. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/store/memory.py +0 -0
  323. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/store/postgres.py +0 -0
  324. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tasks/__init__.py +0 -0
  325. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tasks/base.py +0 -0
  326. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tasks/cache.py +0 -0
  327. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tasks/delegate.py +0 -0
  328. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tasks/memory.py +0 -0
  329. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tasks/models.py +0 -0
  330. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/telemetry/__init__.py +0 -0
  331. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/telemetry/base.py +0 -0
  332. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/telemetry/config.py +0 -0
  333. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/telemetry/console.py +0 -0
  334. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/telemetry/context.py +0 -0
  335. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/telemetry/mock.py +0 -0
  336. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/telemetry/noop.py +0 -0
  337. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/telemetry/opentelemetry.py +0 -0
  338. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/telemetry/pyroscope.py +0 -0
  339. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tools/base.py +0 -0
  340. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tools/compose.py +0 -0
  341. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tools/external.py +0 -0
  342. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tools/human_input.py +0 -0
  343. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tools/mcp.py +0 -0
  344. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/tools/policy.py +0 -0
  345. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/__init__.py +0 -0
  346. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/ai_integration.py +0 -0
  347. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/avatar/__init__.py +0 -0
  348. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/avatar/base.py +0 -0
  349. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/avatar/mock.py +0 -0
  350. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/avatar/musetalk.py +0 -0
  351. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/avatar/websocket.py +0 -0
  352. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/backends/__init__.py +0 -0
  353. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/backends/base.py +0 -0
  354. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/backends/fastrtc.py +0 -0
  355. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/backends/local.py +0 -0
  356. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/backends/mock.py +0 -0
  357. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/backends/rtp.py +0 -0
  358. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/backends/screen.py +0 -0
  359. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/backends/sip.py +0 -0
  360. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/backends/websocket.py +0 -0
  361. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/base.py +0 -0
  362. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/bridge.py +0 -0
  363. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/events.py +0 -0
  364. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/__init__.py +0 -0
  365. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/config.py +0 -0
  366. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/decoder/__init__.py +0 -0
  367. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/decoder/base.py +0 -0
  368. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/decoder/mock.py +0 -0
  369. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/decoder/pyav.py +0 -0
  370. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/encoder/__init__.py +0 -0
  371. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/encoder/base.py +0 -0
  372. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/encoder/pyav.py +0 -0
  373. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/engine.py +0 -0
  374. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/filter/__init__.py +0 -0
  375. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/filter/base.py +0 -0
  376. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/filter/censor.py +0 -0
  377. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/filter/mediapipe_face_touch.py +0 -0
  378. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/filter/mock.py +0 -0
  379. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/filter/mock_face_touch.py +0 -0
  380. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/filter/watermark.py +0 -0
  381. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/filter/yolo.py +0 -0
  382. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/overlay/__init__.py +0 -0
  383. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/overlay/base.py +0 -0
  384. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/overlay/filter.py +0 -0
  385. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/overlay/image.py +0 -0
  386. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/overlay/mock.py +0 -0
  387. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/overlay/rich.py +0 -0
  388. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/overlay/subtitle.py +0 -0
  389. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/overlay/text.py +0 -0
  390. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/resizer/__init__.py +0 -0
  391. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/resizer/base.py +0 -0
  392. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/resizer/mock.py +0 -0
  393. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/resizer/pyav.py +0 -0
  394. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/transform/__init__.py +0 -0
  395. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/transform/base.py +0 -0
  396. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/transform/effects.py +0 -0
  397. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/pipeline/transform/mock.py +0 -0
  398. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/recorder/__init__.py +0 -0
  399. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/recorder/base.py +0 -0
  400. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/recorder/mock.py +0 -0
  401. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/recorder/opencv.py +0 -0
  402. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/recorder/pyav.py +0 -0
  403. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/utils.py +0 -0
  404. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/video_frame.py +0 -0
  405. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/vision/__init__.py +0 -0
  406. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/vision/base.py +0 -0
  407. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/vision/encode.py +0 -0
  408. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/vision/gemini.py +0 -0
  409. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/vision/mock.py +0 -0
  410. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/vision/openai.py +0 -0
  411. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/vision/screen_input.py +0 -0
  412. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/vision/screen_tool.py +0 -0
  413. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/video/vision/webcam_tool.py +0 -0
  414. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/__init__.py +0 -0
  415. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/audio_frame.py +0 -0
  416. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/auth.py +0 -0
  417. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/__init__.py +0 -0
  418. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/_mulaw.py +0 -0
  419. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/_sip_types.py +0 -0
  420. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/base.py +0 -0
  421. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/fastrtc.py +0 -0
  422. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/local.py +0 -0
  423. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/mock.py +0 -0
  424. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/rtp.py +0 -0
  425. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/sip.py +0 -0
  426. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/sip_audio.py +0 -0
  427. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/sip_auth.py +0 -0
  428. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/sip_calling.py +0 -0
  429. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/twilio_ws.py +0 -0
  430. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/backends/webtransport.py +0 -0
  431. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/base.py +0 -0
  432. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/bridge.py +0 -0
  433. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/events.py +0 -0
  434. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/inbound.py +0 -0
  435. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/interruption.py +0 -0
  436. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/__init__.py +0 -0
  437. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/aec/__init__.py +0 -0
  438. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/aec/base.py +0 -0
  439. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/aec/mock.py +0 -0
  440. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/aec/speex.py +0 -0
  441. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/aec/webrtc.py +0 -0
  442. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/agc/__init__.py +0 -0
  443. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/agc/base.py +0 -0
  444. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/agc/mock.py +0 -0
  445. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/backchannel/__init__.py +0 -0
  446. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/backchannel/base.py +0 -0
  447. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/backchannel/mock.py +0 -0
  448. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/config.py +0 -0
  449. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/debug_taps.py +0 -0
  450. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/denoiser/__init__.py +0 -0
  451. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/denoiser/aicoustics.py +0 -0
  452. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/denoiser/base.py +0 -0
  453. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/denoiser/mock.py +0 -0
  454. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/denoiser/rnnoise.py +0 -0
  455. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/denoiser/sherpa_onnx.py +0 -0
  456. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/diarization/__init__.py +0 -0
  457. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/diarization/base.py +0 -0
  458. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/diarization/mock.py +0 -0
  459. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/diarization/sherpa_onnx.py +0 -0
  460. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/dtmf/__init__.py +0 -0
  461. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/dtmf/base.py +0 -0
  462. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/dtmf/mock.py +0 -0
  463. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/engine.py +0 -0
  464. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/mixer/__init__.py +0 -0
  465. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/mixer/base.py +0 -0
  466. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/mixer/numpy.py +0 -0
  467. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/mixer/python.py +0 -0
  468. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/postprocessor/__init__.py +0 -0
  469. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/postprocessor/base.py +0 -0
  470. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/recorder/__init__.py +0 -0
  471. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/recorder/base.py +0 -0
  472. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/recorder/mock.py +0 -0
  473. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/recorder/wav.py +0 -0
  474. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/resampler/__init__.py +0 -0
  475. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/resampler/base.py +0 -0
  476. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/resampler/linear.py +0 -0
  477. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/resampler/mock.py +0 -0
  478. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/resampler/numpy.py +0 -0
  479. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/resampler/sinc.py +0 -0
  480. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/turn/__init__.py +0 -0
  481. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/turn/base.py +0 -0
  482. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/turn/mock.py +0 -0
  483. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/turn/smart_turn.py +0 -0
  484. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/vad/__init__.py +0 -0
  485. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/vad/base.py +0 -0
  486. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/vad/energy.py +0 -0
  487. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/vad/mock.py +0 -0
  488. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/pipeline/vad/sherpa_onnx.py +0 -0
  489. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/realtime/__init__.py +0 -0
  490. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/realtime/bridge.py +0 -0
  491. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/realtime/events.py +0 -0
  492. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/realtime/fastrtc_transport.py +0 -0
  493. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/realtime/mock.py +0 -0
  494. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/realtime/pacer.py +0 -0
  495. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/realtime/provider.py +0 -0
  496. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/realtime/sip_transport.py +0 -0
  497. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/realtime/ws_transport.py +0 -0
  498. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/stt/__init__.py +0 -0
  499. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/stt/base.py +0 -0
  500. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/stt/deepgram.py +0 -0
  501. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/stt/gradium.py +0 -0
  502. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/stt/mock.py +0 -0
  503. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/stt/qwen3.py +0 -0
  504. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/stt/sherpa_onnx.py +0 -0
  505. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/tts/__init__.py +0 -0
  506. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/tts/audio_utils.py +0 -0
  507. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/tts/base.py +0 -0
  508. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/tts/elevenlabs.py +0 -0
  509. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/tts/filters.py +0 -0
  510. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/tts/gradium.py +0 -0
  511. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/tts/grok.py +0 -0
  512. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/tts/mock.py +0 -0
  513. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/tts/neutts.py +0 -0
  514. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/tts/qwen3.py +0 -0
  515. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/tts/sentence_splitter.py +0 -0
  516. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/tts/sherpa_onnx.py +0 -0
  517. {roomkit-0.7.2 → roomkit-0.8.0}/src/roomkit/voice/utils.py +0 -0
  518. {roomkit-0.7.2 → roomkit-0.8.0}/tests/__init__.py +0 -0
  519. {roomkit-0.7.2 → roomkit-0.8.0}/tests/conftest.py +0 -0
  520. {roomkit-0.7.2 → roomkit-0.8.0}/tests/delivery/__init__.py +0 -0
  521. {roomkit-0.7.2 → roomkit-0.8.0}/tests/delivery/test_base.py +0 -0
  522. {roomkit-0.7.2 → roomkit-0.8.0}/tests/delivery/test_integration.py +0 -0
  523. {roomkit-0.7.2 → roomkit-0.8.0}/tests/delivery/test_memory.py +0 -0
  524. {roomkit-0.7.2 → roomkit-0.8.0}/tests/delivery/test_redis.py +0 -0
  525. {roomkit-0.7.2 → roomkit-0.8.0}/tests/delivery/test_serialization.py +0 -0
  526. {roomkit-0.7.2 → roomkit-0.8.0}/tests/delivery/test_worker.py +0 -0
  527. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/__init__.py +0 -0
  528. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_framework_orchestration.py +0 -0
  529. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_handoff.py +0 -0
  530. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_loop_strategy.py +0 -0
  531. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_orchestration_base.py +0 -0
  532. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_pipeline.py +0 -0
  533. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_router.py +0 -0
  534. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_session_audit.py +0 -0
  535. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_state.py +0 -0
  536. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_status_bus.py +0 -0
  537. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_strategy_behavioral.py +0 -0
  538. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_strategy_loop.py +0 -0
  539. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_strategy_pipeline.py +0 -0
  540. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_strategy_supervisor.py +0 -0
  541. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_strategy_swarm.py +0 -0
  542. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_supervisor_inline.py +0 -0
  543. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_supervisor_strategy.py +0 -0
  544. {roomkit-0.7.2 → roomkit-0.8.0}/tests/orchestration/test_tool_audit.py +0 -0
  545. {roomkit-0.7.2 → roomkit-0.8.0}/tests/providers/__init__.py +0 -0
  546. {roomkit-0.7.2 → roomkit-0.8.0}/tests/providers/gemini/__init__.py +0 -0
  547. {roomkit-0.7.2 → roomkit-0.8.0}/tests/providers/gemini/test_reconfigure_preservation.py +0 -0
  548. {roomkit-0.7.2 → roomkit-0.8.0}/tests/providers/gemini/test_schema.py +0 -0
  549. {roomkit-0.7.2 → roomkit-0.8.0}/tests/tasks/__init__.py +0 -0
  550. {roomkit-0.7.2 → roomkit-0.8.0}/tests/tasks/test_cache.py +0 -0
  551. {roomkit-0.7.2 → roomkit-0.8.0}/tests/tasks/test_delegate.py +0 -0
  552. {roomkit-0.7.2 → roomkit-0.8.0}/tests/tasks/test_integration.py +0 -0
  553. {roomkit-0.7.2 → roomkit-0.8.0}/tests/tasks/test_models.py +0 -0
  554. {roomkit-0.7.2 → roomkit-0.8.0}/tests/tasks/test_runner.py +0 -0
  555. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_aec_pipeline.py +0 -0
  556. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_ai_docs.py +0 -0
  557. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_ai_streaming_thinking.py +0 -0
  558. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_ai_streaming_tool_loop.py +0 -0
  559. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_aicoustics_denoiser.py +0 -0
  560. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_anam_realtime.py +0 -0
  561. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_audio_pipeline.py +0 -0
  562. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_auto_connect.py +0 -0
  563. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_av_channel.py +0 -0
  564. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_avatar.py +0 -0
  565. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_before_ai_generation.py +0 -0
  566. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channel_abc.py +0 -0
  567. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/__init__.py +0 -0
  568. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_agent.py +0 -0
  569. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_ai.py +0 -0
  570. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_ai_retry.py +0 -0
  571. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_ai_steering.py +0 -0
  572. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_email.py +0 -0
  573. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_http.py +0 -0
  574. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_messenger.py +0 -0
  575. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_sms.py +0 -0
  576. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_telegram.py +0 -0
  577. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_turn_config.py +0 -0
  578. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_websocket.py +0 -0
  579. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_channels/test_whatsapp.py +0 -0
  580. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_circuit_breaker.py +0 -0
  581. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_cli_channel.py +0 -0
  582. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_compose_tool_handlers.py +0 -0
  583. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_configs.py +0 -0
  584. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_console.py +0 -0
  585. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_dangling_recovery.py +0 -0
  586. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_delivery_strategies.py +0 -0
  587. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_describe_screen_tool.py +0 -0
  588. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_describe_webcam_tool.py +0 -0
  589. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_drain_barge_in.py +0 -0
  590. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_energy_vad.py +0 -0
  591. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_enums.py +0 -0
  592. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_external_tool_handler.py +0 -0
  593. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_face_touch_filter.py +0 -0
  594. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_fastrtc_realtime_transport.py +0 -0
  595. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_framework.py +0 -0
  596. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_framework_events.py +0 -0
  597. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_framework_queries.py +0 -0
  598. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_framework_status_bus.py +0 -0
  599. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_hook_side_effects.py +0 -0
  600. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_hooks.py +0 -0
  601. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_human_input.py +0 -0
  602. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_identity_hooks.py +0 -0
  603. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_identity_pipeline.py +0 -0
  604. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_inbound_rate_limit.py +0 -0
  605. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_inbound_routing.py +0 -0
  606. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_integration/__init__.py +0 -0
  607. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_integration/test_ai_assistant.py +0 -0
  608. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_integration/test_ai_chain_depth.py +0 -0
  609. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_integration/test_cross_channel.py +0 -0
  610. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_integration/test_dynamic_channels.py +0 -0
  611. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_integration/test_human_ai.py +0 -0
  612. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_integration/test_identity_resolution.py +0 -0
  613. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_integration/test_observer.py +0 -0
  614. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_integration/test_sin_scanning.py +0 -0
  615. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_interruption.py +0 -0
  616. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_lifecycle_hooks.py +0 -0
  617. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_local_backend_aec.py +0 -0
  618. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_locks.py +0 -0
  619. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_mcp_tool_provider.py +0 -0
  620. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_mcp_tools.py +0 -0
  621. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_media_recorder.py +0 -0
  622. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_memory.py +0 -0
  623. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_memory_new.py +0 -0
  624. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_mock_providers.py +0 -0
  625. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_models.py +0 -0
  626. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_observability.py +0 -0
  627. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_opencv_recorder.py +0 -0
  628. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_opentelemetry.py +0 -0
  629. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_outbound_audio_pacer.py +0 -0
  630. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_personaplex_realtime.py +0 -0
  631. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_pipeline_debug_taps.py +0 -0
  632. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_pipeline_engine.py +0 -0
  633. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_pipeline_providers.py +0 -0
  634. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_pipeline_resampler.py +0 -0
  635. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_pipeline_resampler_numpy.py +0 -0
  636. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_pipeline_resampler_sinc.py +0 -0
  637. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_postgres_store.py +0 -0
  638. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_protocol_trace.py +0 -0
  639. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/__init__.py +0 -0
  640. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_anam_avatar.py +0 -0
  641. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_anam_realtime.py +0 -0
  642. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_anthropic.py +0 -0
  643. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_azure.py +0 -0
  644. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_elasticemail.py +0 -0
  645. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_gemini.py +0 -0
  646. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_gemini_realtime.py +0 -0
  647. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_http.py +0 -0
  648. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_messenger.py +0 -0
  649. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_mistral.py +0 -0
  650. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_ollama.py +0 -0
  651. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_openai.py +0 -0
  652. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_openai_realtime.py +0 -0
  653. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_personaplex_realtime.py +0 -0
  654. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_phone.py +0 -0
  655. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_rcs.py +0 -0
  656. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_sendgrid.py +0 -0
  657. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_sinch.py +0 -0
  658. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_sms_utils.py +0 -0
  659. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_teams.py +0 -0
  660. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_teams_webhook.py +0 -0
  661. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_telegram_bot.py +0 -0
  662. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_telegram_webhook.py +0 -0
  663. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_telnyx.py +0 -0
  664. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_telnyx_rcs.py +0 -0
  665. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_twilio.py +0 -0
  666. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_vllm.py +0 -0
  667. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_voicemeup.py +0 -0
  668. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_whatsapp_personal.py +0 -0
  669. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_providers/test_xai_realtime.py +0 -0
  670. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_public_api.py +0 -0
  671. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_pyav_media_recorder.py +0 -0
  672. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_pyav_recorder.py +0 -0
  673. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_realtime.py +0 -0
  674. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_realtime_av_channel.py +0 -0
  675. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_realtime_elevenlabs.py +0 -0
  676. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_realtime_skills.py +0 -0
  677. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_realtime_tool_search.py +0 -0
  678. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_realtime_voice.py +0 -0
  679. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_realtime_voice_integration.py +0 -0
  680. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_realtime_xai.py +0 -0
  681. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_recording_wiring.py +0 -0
  682. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_reentry_block_side_effects.py +0 -0
  683. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_resilience.py +0 -0
  684. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_response_metadata.py +0 -0
  685. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_response_visibility.py +0 -0
  686. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_retrieval_memory.py +0 -0
  687. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_rnnoise.py +0 -0
  688. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_router.py +0 -0
  689. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_rtp_video_backend.py +0 -0
  690. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_scoring.py +0 -0
  691. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_screen_capture_backend.py +0 -0
  692. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_screen_input.py +0 -0
  693. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_session_started.py +0 -0
  694. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_sherpa_onnx_denoiser.py +0 -0
  695. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_sherpa_onnx_vad.py +0 -0
  696. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_sip_auth.py +0 -0
  697. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_sip_dial.py +0 -0
  698. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_sip_helpers.py +0 -0
  699. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_sip_realtime_transport.py +0 -0
  700. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_sip_video_backend.py +0 -0
  701. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_skills.py +0 -0
  702. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_skills_integration.py +0 -0
  703. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_smart_turn.py +0 -0
  704. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_smoke_quickstart.py +0 -0
  705. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_source_rate_limit.py +0 -0
  706. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_sources.py +0 -0
  707. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_sources_init.py +0 -0
  708. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_sources_neonize.py +0 -0
  709. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_sources_sse.py +0 -0
  710. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_sources_websocket.py +0 -0
  711. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_speex_aec.py +0 -0
  712. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_store_activity.py +0 -0
  713. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_store_memory.py +0 -0
  714. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_store_postgres.py +0 -0
  715. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_stt_qwen3.py +0 -0
  716. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_summarizing_memory.py +0 -0
  717. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_supervisor.py +0 -0
  718. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_task_planner.py +0 -0
  719. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_task_utils.py +0 -0
  720. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_telemetry.py +0 -0
  721. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_telemetry_pyroscope.py +0 -0
  722. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_tool_policy.py +0 -0
  723. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_tool_protocol.py +0 -0
  724. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_transport_auth.py +0 -0
  725. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_tts_elevenlabs.py +0 -0
  726. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_tts_grok.py +0 -0
  727. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_tts_neutts.py +0 -0
  728. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_tts_qwen3.py +0 -0
  729. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_tts_text_split.py +0 -0
  730. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_turn_detection.py +0 -0
  731. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_twilio_ws_backend.py +0 -0
  732. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_unified_tool_call.py +0 -0
  733. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_vad_debug_logging.py +0 -0
  734. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_video.py +0 -0
  735. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_video_ai_integration.py +0 -0
  736. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_video_channel.py +0 -0
  737. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_video_local.py +0 -0
  738. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_video_pipeline.py +0 -0
  739. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_video_pipeline_config.py +0 -0
  740. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_video_recording.py +0 -0
  741. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_video_transform.py +0 -0
  742. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_vision_gemini.py +0 -0
  743. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_vision_openai.py +0 -0
  744. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice.py +0 -0
  745. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_batch_stt.py +0 -0
  746. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_binding_gate.py +0 -0
  747. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_channel_aec.py +0 -0
  748. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_fastrtc.py +0 -0
  749. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_frame_limit.py +0 -0
  750. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_inbound.py +0 -0
  751. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_integration.py +0 -0
  752. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_local.py +0 -0
  753. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_map.py +0 -0
  754. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_rtp.py +0 -0
  755. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_say_play.py +0 -0
  756. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_sherpa_onnx.py +0 -0
  757. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_streaming_ai_tts.py +0 -0
  758. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_streaming_stt.py +0 -0
  759. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_voice_webtransport.py +0 -0
  760. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_wav_recorder.py +0 -0
  761. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_websocket_lifecycle.py +0 -0
  762. {roomkit-0.7.2 → roomkit-0.8.0}/tests/test_yolo_filter.py +0 -0
  763. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/__init__.py +0 -0
  764. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_av_channel_fastrtc.py +0 -0
  765. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_fastrtc_video_backend.py +0 -0
  766. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_overlay_filter.py +0 -0
  767. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_overlay_image.py +0 -0
  768. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_overlay_rich.py +0 -0
  769. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_overlay_subtitle.py +0 -0
  770. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_overlay_text.py +0 -0
  771. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_screen_input.py +0 -0
  772. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_screen_input_tools.py +0 -0
  773. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_video_bridge.py +0 -0
  774. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_video_effects.py +0 -0
  775. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_watermark_filter.py +0 -0
  776. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_websocket_avatar.py +0 -0
  777. {roomkit-0.7.2 → roomkit-0.8.0}/tests/video/test_websocket_video_backend.py +0 -0
  778. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/__init__.py +0 -0
  779. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/backends/__init__.py +0 -0
  780. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/backends/test_rtp.py +0 -0
  781. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/backends/test_sip.py +0 -0
  782. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/backends/test_sip_coverage.py +0 -0
  783. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/backends/test_webtransport.py +0 -0
  784. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/pipeline/__init__.py +0 -0
  785. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/pipeline/test_aicoustics_denoiser.py +0 -0
  786. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/pipeline/test_rnnoise_denoiser.py +0 -0
  787. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/pipeline/test_sherpa_diarization.py +0 -0
  788. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/pipeline/test_smart_turn.py +0 -0
  789. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/pipeline/test_speex_aec.py +0 -0
  790. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/pipeline/test_webrtc_aec.py +0 -0
  791. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/realtime/__init__.py +0 -0
  792. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/realtime/test_fastrtc_transport.py +0 -0
  793. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/realtime/test_realtime_bridge.py +0 -0
  794. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/realtime/test_ws_transport.py +0 -0
  795. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/stt/__init__.py +0 -0
  796. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/stt/test_deepgram.py +0 -0
  797. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/stt/test_gradium_stt.py +0 -0
  798. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/stt/test_qwen3_asr.py +0 -0
  799. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/test_bridge.py +0 -0
  800. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/test_tts_filters.py +0 -0
  801. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/test_voice_tts_filter.py +0 -0
  802. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/tts/__init__.py +0 -0
  803. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/tts/test_elevenlabs.py +0 -0
  804. {roomkit-0.7.2 → roomkit-0.8.0}/tests/voice/tts/test_gradium_tts.py +0 -0
  805. {roomkit-0.7.2 → roomkit-0.8.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.8.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/
@@ -350,7 +350,7 @@ For development:
350
350
  git clone https://github.com/roomkit-live/roomkit.git
351
351
  cd roomkit
352
352
  uv sync --extra dev
353
- make all # ruff check + mypy --strict + pytest
353
+ make all # ruff check + ty + pytest
354
354
  ```
355
355
 
356
356
  Requires **Python 3.12+**.
@@ -729,7 +729,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.
729
729
 
730
730
  ```bash
731
731
  uv sync --extra dev
732
- make all # ruff check + mypy --strict + pytest
732
+ make all # ruff check + ty + pytest
733
733
  ```
734
734
 
735
735
  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.
@@ -0,0 +1 @@
1
+ __version__ = "0.8.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:
@@ -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():
@@ -70,6 +70,7 @@ class AIStreamingHost(Protocol):
70
70
  _max_tool_rounds: int
71
71
  _tool_loop_timeout_seconds: float | None
72
72
  _tool_loop_warn_after: int
73
+ _max_empty_retries: int
73
74
  _tool_handler: Any
74
75
  _active_loops: dict[str, _ToolLoopContext]
75
76
  _after_response_hook: Any
@@ -126,6 +127,7 @@ class AIStreamingMixin:
126
127
  _max_tool_rounds: int
127
128
  _tool_loop_timeout_seconds: float | None
128
129
  _tool_loop_warn_after: int
130
+ _max_empty_retries: int
129
131
  _tool_handler: Any
130
132
  _active_loops: dict[str, Any]
131
133
  _after_response_hook: Any
@@ -235,26 +237,42 @@ class AIStreamingMixin:
235
237
  self, event: RoomEvent, binding: ChannelBinding, context: RoomContext
236
238
  ) -> ChannelOutput:
237
239
  """Return a streaming response that handles tool calls between rounds."""
240
+ from roomkit.channels.ai import _current_loop_ctx
241
+
238
242
  ai_context = await self._build_context(event, binding, context) # ty: ignore[unresolved-attribute]
239
243
  ai_context, blocked = await self._fire_before_generation_hook(ai_context, event) # ty: ignore[unresolved-attribute]
240
244
  if blocked:
241
245
  return ChannelOutput.empty()
246
+ # The generator below executes when the CONSUMER iterates the
247
+ # stream — by then handle_event has reset the loop contextvar, so
248
+ # the parent ctx (participant role, room, the toolset stamped by
249
+ # _build_context) must be captured NOW and passed explicitly.
242
250
  return ChannelOutput(
243
251
  responded=True,
244
- response_stream=self._run_streaming_tool_loop(ai_context),
252
+ response_stream=self._run_streaming_tool_loop(
253
+ ai_context, parent_loop_ctx=_current_loop_ctx.get()
254
+ ),
245
255
  response_metadata=ai_context.response_metadata,
246
256
  )
247
257
 
248
- async def _run_streaming_tool_loop(self, context: AIContext) -> AsyncIterator[StreamDelta]:
258
+ async def _run_streaming_tool_loop(
259
+ self, context: AIContext, *, parent_loop_ctx: Any | None = None
260
+ ) -> AsyncIterator[StreamDelta]:
249
261
  """Stream text deltas, executing tool calls between generation rounds."""
250
- from roomkit.channels.ai import _current_loop_ctx, _ToolLoopContext
262
+ from roomkit.channels.ai import (
263
+ _EMPTY_RETRY_NUDGE,
264
+ _current_loop_ctx,
265
+ _ToolLoopContext,
266
+ )
251
267
  from roomkit.telemetry.context import get_current_span
252
268
 
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
269
+ # The handle_event ctx is gone from the contextvar by the time this
270
+ # generator runs (reset in handle_event's finally); the caller
271
+ # captured it at stream creation.
272
+ parent_ctx = parent_loop_ctx if parent_loop_ctx is not None else _current_loop_ctx.get()
273
+ loop_ctx = _ToolLoopContext.for_loop(
274
+ parent_ctx, context.room.room.id if context.room else None
275
+ )
258
276
  _current_loop_ctx.set(loop_ctx)
259
277
  self._active_loops[loop_ctx.loop_id] = loop_ctx
260
278
  telemetry = self._telemetry_provider
@@ -287,6 +305,8 @@ class AIStreamingMixin:
287
305
  )
288
306
 
289
307
  _dedup_prefix = ""
308
+ _saw_tool_call_any = False
309
+ _empty_retries = 0
290
310
 
291
311
  for _round_idx in range(self._max_tool_rounds + 1):
292
312
  if loop_ctx.cancel_event.is_set():
@@ -465,8 +485,28 @@ class AIStreamingMixin:
465
485
  )
466
486
 
467
487
  if not tool_calls:
488
+ # Final answer round. If it produced no text *after* a tool
489
+ # round, the model skipped verbalizing the result — re-prompt
490
+ # once (bounded) for the final answer instead of ending empty.
491
+ if (
492
+ _saw_tool_call_any
493
+ and not "".join(text_parts).strip()
494
+ and _empty_retries < self._max_empty_retries
495
+ and not (deadline and asyncio.get_running_loop().time() >= deadline)
496
+ ):
497
+ _empty_retries += 1
498
+ logger.warning(
499
+ "Streaming empty response after tools; re-prompting for "
500
+ "final answer (retry %d/%d)",
501
+ _empty_retries,
502
+ self._max_empty_retries,
503
+ )
504
+ context.messages.append(AIMessage(role="user", content=_EMPTY_RETRY_NUDGE))
505
+ continue
468
506
  return
469
507
 
508
+ _saw_tool_call_any = True
509
+
470
510
  # External tools: provider executed them internally.
471
511
  # If ExternalToolHandler is set, hooks were already fired
472
512
  # inline during streaming (see StreamToolCall handling above).
@@ -21,15 +21,30 @@ class ToolEviction:
21
21
  stored in a FIFO-bounded buffer and replaced with a head/tail preview.
22
22
  The ``read_tool_result`` tool definition is injected into the AI
23
23
  context so the agent can paginate back through the full output.
24
+
25
+ The store is scoped per room: the eviction buffer lives on a channel
26
+ object shared by every room the channel serves, so an unscoped buffer
27
+ would leak one conversation's tool output into another (and inject
28
+ the re-read tool into rooms that evicted nothing). The room comes
29
+ from the tool-loop context; paths outside a loop share one fallback
30
+ scope.
24
31
  """
25
32
 
26
33
  def __init__(self, threshold_tokens: int = 5000) -> None:
27
34
  self.threshold_tokens = threshold_tokens
28
- self._store: OrderedDict[str, str] = OrderedDict()
35
+ self._store: OrderedDict[tuple[str, str], str] = OrderedDict()
36
+
37
+ @staticmethod
38
+ def _room_scope() -> str:
39
+ from roomkit.channels.ai import _current_loop_ctx
40
+
41
+ ctx = _current_loop_ctx.get()
42
+ return (ctx.room_id if ctx is not None else None) or ""
29
43
 
30
44
  @property
31
45
  def has_evicted(self) -> bool:
32
- return bool(self._store)
46
+ room = self._room_scope()
47
+ return any(key[0] == room for key in self._store)
33
48
 
34
49
  def maybe_evict(self, result: str, tool_call_id: str = "") -> str:
35
50
  """Evict large results to the store, returning a preview."""
@@ -38,7 +53,7 @@ class ToolEviction:
38
53
  return result
39
54
 
40
55
  result_id = f"evicted_{tool_call_id}" if tool_call_id else f"evicted_{id(result)}"
41
- self._store[result_id] = result
56
+ self._store[(self._room_scope(), result_id)] = result
42
57
  while len(self._store) > _MAX_EVICTED:
43
58
  self._store.popitem(last=False)
44
59
 
@@ -71,11 +86,11 @@ class ToolEviction:
71
86
  offset = arguments.get("offset", 0)
72
87
  limit = arguments.get("limit", 200)
73
88
 
74
- full_result = self._store.get(result_id)
89
+ room = self._room_scope()
90
+ full_result = self._store.get((room, result_id))
75
91
  if full_result is None:
76
- return json.dumps(
77
- {"error": f"Result '{result_id}' not found", "available": list(self._store.keys())}
78
- )
92
+ available = [rid for scope, rid in self._store if scope == room]
93
+ return json.dumps({"error": f"Result '{result_id}' not found", "available": available})
79
94
 
80
95
  # Char budget per page: threshold_tokens chars ≈ threshold/4 tokens of
81
96
  # content, leaving ample headroom for JSON escaping (worst case 2×)
@@ -89,16 +89,44 @@ class _ToolLoopContext:
89
89
  activated_skills: set[str] = field(default_factory=set)
90
90
  all_context_tools: list[Any] = field(default_factory=list)
91
91
  current_participant_role: str | None = None
92
+ room_id: str | None = None
92
93
  steering_queue: asyncio.Queue[SteeringDirective] = field(default_factory=asyncio.Queue)
93
94
  cancel_event: asyncio.Event = field(default_factory=asyncio.Event)
94
95
  loop_id: str = ""
95
96
 
97
+ @classmethod
98
+ def for_loop(cls, parent: _ToolLoopContext | None, room_id: str | None) -> _ToolLoopContext:
99
+ """Create a tool-loop context inheriting per-turn state from *parent*.
100
+
101
+ _build_context ran under the parent (handle_event) ctx and stamped the
102
+ turn's full toolset there — without this inheritance the per-round
103
+ tools re-application never fires (skill-gated tools would stay hidden
104
+ after activation) and per-call allowlist accessors see nothing.
105
+ """
106
+ ctx = cls()
107
+ ctx.loop_id = str(id(ctx))
108
+ if parent is not None:
109
+ ctx.current_participant_role = parent.current_participant_role
110
+ ctx.all_context_tools = parent.all_context_tools
111
+ ctx.room_id = room_id or (parent.room_id if parent else None)
112
+ return ctx
113
+
96
114
 
97
115
  _current_loop_ctx: contextvars.ContextVar[_ToolLoopContext | None] = contextvars.ContextVar(
98
116
  "_current_loop_ctx", default=None
99
117
  )
100
118
 
101
119
 
120
+ # Corrective nudge re-injected when a generation round ends after tool calls
121
+ # without any final text (common with small local models): the tool results
122
+ # are in context, the model just failed to verbalize the answer. Re-prompting
123
+ # for the final answer recovers it. Bounded by ``max_empty_retries``.
124
+ _EMPTY_RETRY_NUDGE = (
125
+ "You called tools and already have their results above. Now write your "
126
+ "final answer to the user in plain text. Do not call any more tools."
127
+ )
128
+
129
+
102
130
  class AIChannel(
103
131
  AIStreamingMixin,
104
132
  AIGenerationMixin,
@@ -129,9 +157,11 @@ class AIChannel(
129
157
  max_tool_rounds: int = 200,
130
158
  tool_loop_timeout_seconds: float | None = 300.0,
131
159
  tool_loop_warn_after: int = 50,
160
+ max_empty_retries: int = 1,
132
161
  retry_policy: RetryPolicy | None = None,
133
162
  fallback_provider: AIProvider | None = None,
134
163
  skills: SkillRegistry | None = None,
164
+ skills_in_prompt: bool = True,
135
165
  script_executor: ScriptExecutor | None = None,
136
166
  sandbox: SandboxExecutor | None = None,
137
167
  external_tool_handler: ExternalToolHandler | None = None,
@@ -157,9 +187,15 @@ class AIChannel(
157
187
  self._max_tool_rounds = max_tool_rounds
158
188
  self._tool_loop_timeout_seconds = tool_loop_timeout_seconds
159
189
  self._tool_loop_warn_after = tool_loop_warn_after
190
+ self._max_empty_retries = max_empty_retries
160
191
  self._retry_policy = retry_policy
161
192
  self._fallback_provider = fallback_provider
162
193
  self._skills = skills
194
+ # Hosts that render their own skills manifest inside ``system_prompt``
195
+ # (e.g. positioned above a prompt-cache boundary) set this to False to
196
+ # skip the automatic preamble+XML injection while keeping the skill
197
+ # activation tools.
198
+ self._skills_in_prompt = skills_in_prompt
163
199
  self._script_executor = script_executor
164
200
  self._sandbox = sandbox
165
201
  self._memory = memory or SlidingWindowMemory(max_events=max_context_events)
@@ -310,14 +346,24 @@ class AIChannel(
310
346
 
311
347
  # Resolve participant role for role-based tool policy.
312
348
  # Set on a per-invocation _ToolLoopContext visible via contextvar so that
313
- # _build_context and the tool loop methods can read it.
349
+ # _build_context and the tool loop methods can read it. ``room_id``
350
+ # rides the same contextvar: the channel object is registered once
351
+ # per channel_id and shared by every room it serves, so per-call
352
+ # room resolution (``current_tool_room_id``) is the only safe way
353
+ # for tool handlers to learn the originating room.
314
354
  event_ctx = _ToolLoopContext()
315
355
  event_ctx.current_participant_role = self._resolve_participant_role(event, context)
356
+ event_ctx.room_id = context.room.id if context.room else event.room_id
316
357
  token = _current_loop_ctx.set(event_ctx)
317
358
  try:
318
359
  raw_tools = binding.metadata.get("tools", [])
360
+ # A config_provider may deliver tools at _build_context time even
361
+ # when the binding carries no snapshot — route to the tool loop
362
+ # so those tools are executable. An empty turn toolset just runs
363
+ # the loop for a single round.
319
364
  has_tools = (
320
365
  bool(raw_tools)
366
+ or self._config_provider is not None
321
367
  or bool(self._user_tools)
322
368
  or bool(self._injected_tools)
323
369
  or (self._skills is not None and self._skills.skill_count > 0)
@@ -148,22 +148,15 @@ class EventRouter:
148
148
 
149
149
  result = BroadcastResult()
150
150
 
151
- # Check source can write
152
- if source_binding.access in (Access.READ_ONLY, Access.NONE):
151
+ # Check source can write (RFC §7.5). Inbound events from non-writable
152
+ # sources are already blocked before broadcast in the inbound pipeline;
153
+ # this guards reentry events and any direct broadcast callers.
154
+ if not source_binding.can_write:
153
155
  logger.debug(
154
- "Source %s has no write access",
155
- source_binding.channel_id,
156
- extra={"room_id": event.room_id, "channel_id": source_binding.channel_id},
157
- )
158
- reset_span(broadcast_token)
159
- telemetry.end_span(span_id, attributes={"target_count": 0})
160
- return result
161
-
162
- # Check source is not muted
163
- if source_binding.muted:
164
- logger.debug(
165
- "Source %s is muted",
156
+ "Source %s cannot write (access=%s, muted=%s) — not broadcasting",
166
157
  source_binding.channel_id,
158
+ source_binding.access,
159
+ source_binding.muted,
167
160
  extra={"room_id": event.room_id, "channel_id": source_binding.channel_id},
168
161
  )
169
162
  reset_span(broadcast_token)
@@ -53,6 +53,7 @@ from roomkit.core.mixins import (
53
53
  InboundStreamingMixin,
54
54
  RealtimeOpsMixin,
55
55
  RecordingMixin,
56
+ RegenerateMixin,
56
57
  RoomLifecycleMixin,
57
58
  SourceOpsMixin,
58
59
  VoiceOpsMixin,
@@ -60,6 +61,7 @@ from roomkit.core.mixins import (
60
61
  from roomkit.core.transcoder import DefaultContentTranscoder
61
62
  from roomkit.identity.base import IdentityResolver
62
63
  from roomkit.models.channel import RateLimit
64
+ from roomkit.models.context import RoomContext
63
65
  from roomkit.models.enums import (
64
66
  ChannelType,
65
67
  EventStatus,
@@ -105,6 +107,7 @@ class RoomKit(
105
107
  InboundIdentityMixin,
106
108
  InboundLockedMixin,
107
109
  InboundStreamingMixin,
110
+ RegenerateMixin,
108
111
  ChannelOpsMixin,
109
112
  RoomLifecycleMixin,
110
113
  VoiceOpsMixin,
@@ -510,19 +513,23 @@ class RoomKit(
510
513
  )
511
514
  token = set_current_span(span_id, telemetry_ctx=telemetry.get_span_context(span_id))
512
515
  try:
516
+ # Direct injection traverses the SAME locked pipeline as inbound
517
+ # (RFC §10.5): index assignment, BEFORE_BROADCAST hooks, edit/delete
518
+ # handling, source write-permission gate, persistence, broadcast,
519
+ # reentry drain and AFTER_BROADCAST hooks. This keeps a single
520
+ # validation/hooks/indexing/persistence model across entry points.
521
+ pending_after_broadcast: list[tuple[RoomEvent, RoomContext]] = []
513
522
  async with self._lock_manager.locked(room_id):
514
- count = await self._store.get_event_count(room_id)
515
- event = event.model_copy(update={"index": count})
516
- await self._persist_event(event)
517
-
518
523
  context = await self._build_context(room_id)
519
- router = self._get_router()
520
- await router.broadcast(event, binding, context)
521
-
522
- # Run AFTER_BROADCAST hooks for observability and fan-out
523
- await self._hook_engine.run_async_hooks(
524
- room_id, HookTrigger.AFTER_BROADCAST, event, context
524
+ result = await self._process_locked(
525
+ event,
526
+ room_id,
527
+ context,
528
+ pending_after_broadcast_out=pending_after_broadcast,
525
529
  )
530
+ event = result.event or event
531
+ # AFTER_BROADCAST runs outside the room lock (RFC §10.1)
532
+ await self._run_deferred_after_broadcast(room_id, pending_after_broadcast)
526
533
 
527
534
  telemetry.end_span(span_id)
528
535
  except Exception as exc:
@@ -14,6 +14,7 @@ from roomkit.core.mixins.inbound_locked import InboundLockedMixin
14
14
  from roomkit.core.mixins.inbound_streaming import InboundStreamingMixin
15
15
  from roomkit.core.mixins.realtime_ops import RealtimeOpsMixin
16
16
  from roomkit.core.mixins.recording import RecordingMixin
17
+ from roomkit.core.mixins.regenerate import RegenerateMixin
17
18
  from roomkit.core.mixins.room_lifecycle import RoomLifecycleMixin
18
19
  from roomkit.core.mixins.source_ops import SourceOpsMixin
19
20
  from roomkit.core.mixins.voice_ops import VoiceOpsMixin
@@ -33,6 +34,7 @@ __all__ = [
33
34
  "InboundStreamingMixin",
34
35
  "RealtimeOpsMixin",
35
36
  "RecordingMixin",
37
+ "RegenerateMixin",
36
38
  "RoomLifecycleMixin",
37
39
  "SourceOpsMixin",
38
40
  "VoiceOpsMixin",
@@ -9,11 +9,13 @@ from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
9
9
  from roomkit.core.exceptions import ChannelNotRegisteredError
10
10
  from roomkit.core.mixins.helpers import HelpersMixin
11
11
  from roomkit.core.mixins.inbound_identity import _IdentityBlockedError
12
+ from roomkit.models.context import RoomContext
12
13
  from roomkit.models.delivery import InboundMessage, InboundResult
13
14
  from roomkit.models.enums import (
14
15
  ChannelType,
15
16
  HookTrigger,
16
17
  )
18
+ from roomkit.models.event import RoomEvent
17
19
 
18
20
  if TYPE_CHECKING:
19
21
  from roomkit.channels.base import Channel
@@ -47,6 +49,7 @@ class InboundHost(Protocol):
47
49
  Cross-mixin methods (provided by other mixins in the MRO):
48
50
  _resolve_identity: From :class:`InboundIdentityMixin`.
49
51
  _process_locked: From :class:`InboundLockedMixin`.
52
+ _run_deferred_after_broadcast: From :class:`InboundLockedMixin`.
50
53
  _process_streaming_responses: From :class:`InboundStreamingMixin`.
51
54
  create_room: From :class:`RoomLifecycleMixin`.
52
55
  attach_channel: From :class:`ChannelOpsMixin`.
@@ -88,6 +91,7 @@ class InboundMixin(HelpersMixin):
88
91
  # Cross-mixin methods — attribute annotations avoid MRO shadowing
89
92
  _resolve_identity: Any # see InboundHost
90
93
  _process_locked: Any # see InboundHost
94
+ _run_deferred_after_broadcast: Any # see InboundHost
91
95
  _process_streaming_responses: Any # see InboundHost
92
96
  create_room: Any # see InboundHost
93
97
  attach_channel: Any # see InboundHost
@@ -181,6 +185,11 @@ class InboundMixin(HelpersMixin):
181
185
  # Let channel process inbound
182
186
  event = await channel.handle_inbound(message, context)
183
187
 
188
+ # Caller-requested visibility (e.g. ``"transport"`` for a proactive
189
+ # notification that must not wake the room's intelligence channel).
190
+ if message.visibility != "all" and event.visibility == "all":
191
+ event = event.model_copy(update={"visibility": message.visibility})
192
+
184
193
  # Identity resolution pipeline (RFC §7)
185
194
  try:
186
195
  event, resolved_identity, pending_id_result = await self._resolve_identity(
@@ -191,6 +200,7 @@ class InboundMixin(HelpersMixin):
191
200
 
192
201
  # Process under room lock
193
202
  pending_streams: list[Any] = []
203
+ pending_after_broadcast: list[tuple[RoomEvent, RoomContext]] = []
194
204
  async with self._lock_manager.locked(room_id):
195
205
  try:
196
206
  result: InboundResult = await asyncio.wait_for(
@@ -201,6 +211,7 @@ class InboundMixin(HelpersMixin):
201
211
  resolved_identity=resolved_identity,
202
212
  pending_id_result=pending_id_result,
203
213
  pending_streams_out=pending_streams,
214
+ pending_after_broadcast_out=pending_after_broadcast,
204
215
  ),
205
216
  timeout=self._process_timeout,
206
217
  )
@@ -218,6 +229,11 @@ class InboundMixin(HelpersMixin):
218
229
  )
219
230
  return InboundResult(blocked=True, reason="process_timeout")
220
231
 
232
+ # Run AFTER_BROADCAST async hooks now that the room lock is released
233
+ # (RFC §10.1) — a slow observer hook no longer blocks concurrent
234
+ # process_inbound calls for the same room.
235
+ await self._run_deferred_after_broadcast(room_id, pending_after_broadcast)
236
+
221
237
  # Handle streaming responses outside lock (TTS delivery can take seconds;
222
238
  # holding the lock would block concurrent process_inbound calls)
223
239
  if pending_streams: