roomkit 0.1.1__tar.gz → 0.2.1__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.
- {roomkit-0.1.1 → roomkit-0.2.1}/AGENTS.md +17 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/PKG-INFO +26 -6
- {roomkit-0.1.1 → roomkit-0.2.1}/README.md +16 -5
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/channels.md +4 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/index.md +7 -5
- roomkit-0.2.1/docs/api/providers-rcs.md +25 -0
- roomkit-0.2.1/docs/api/providers-voice.md +56 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/sources.md +124 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/architecture.md +106 -0
- roomkit-0.2.1/docs/faq.md +399 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/features.md +199 -20
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/llms.txt +4 -2
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/roomkit-rfc.md +748 -5
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/technical.md +149 -5
- {roomkit-0.1.1 → roomkit-0.2.1}/llms.txt +4 -2
- {roomkit-0.1.1 → roomkit-0.2.1}/pyproject.toml +3 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/__init__.py +45 -0
- roomkit-0.2.1/src/roomkit/_version.py +1 -0
- roomkit-0.2.1/src/roomkit/channels/voice.py +728 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/_channel_ops.py +7 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/_inbound.py +4 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/framework.py +177 -1
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/hooks.py +32 -6
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/models/enums.py +12 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/sources/__init__.py +4 -4
- roomkit-0.2.1/src/roomkit/sources/sse.py +226 -0
- roomkit-0.2.1/src/roomkit/voice/__init__.py +99 -0
- roomkit-0.2.1/src/roomkit/voice/backends/__init__.py +1 -0
- roomkit-0.2.1/src/roomkit/voice/backends/base.py +264 -0
- roomkit-0.2.1/src/roomkit/voice/backends/fastrtc.py +467 -0
- roomkit-0.2.1/src/roomkit/voice/backends/mock.py +302 -0
- roomkit-0.2.1/src/roomkit/voice/base.py +115 -0
- roomkit-0.2.1/src/roomkit/voice/events.py +140 -0
- roomkit-0.2.1/src/roomkit/voice/stt/__init__.py +1 -0
- roomkit-0.2.1/src/roomkit/voice/stt/base.py +58 -0
- roomkit-0.2.1/src/roomkit/voice/stt/deepgram.py +214 -0
- roomkit-0.2.1/src/roomkit/voice/stt/mock.py +40 -0
- roomkit-0.2.1/src/roomkit/voice/tts/__init__.py +1 -0
- roomkit-0.2.1/src/roomkit/voice/tts/base.py +58 -0
- roomkit-0.2.1/src/roomkit/voice/tts/elevenlabs.py +329 -0
- roomkit-0.2.1/src/roomkit/voice/tts/mock.py +51 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_enums.py +1 -1
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_framework.py +23 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_public_api.py +1 -1
- roomkit-0.2.1/tests/test_sources_sse.py +588 -0
- roomkit-0.2.1/tests/test_voice.py +812 -0
- roomkit-0.2.1/tests/test_voice_fastrtc.py +458 -0
- roomkit-0.2.1/tests/test_voice_integration.py +979 -0
- roomkit-0.1.1/src/roomkit/_version.py +0 -1
- {roomkit-0.1.1 → roomkit-0.2.1}/.gitignore +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/LICENSE +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/ai-integration.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/channel-models.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/channel.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/delivery.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/enums.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/events.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/hook-models.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/hooks.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/identity.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/providers-ai.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/providers-email.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/providers-http.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/providers-messenger.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/providers-sms.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/providers-whatsapp.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/realtime.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/room.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/roomkit.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/routing.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/api/store.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/cpaas-comparison.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/index.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/docs/mcp.md +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/ai_docs.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/channels/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/channels/ai.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/channels/base.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/channels/transport.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/channels/websocket.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/_helpers.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/_room_lifecycle.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/circuit_breaker.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/event_router.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/inbound_router.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/locks.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/rate_limiter.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/retry.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/router.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/core/transcoder.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/identity/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/identity/base.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/identity/mock.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/models/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/models/channel.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/models/context.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/models/delivery.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/models/event.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/models/framework_event.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/models/hook.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/models/identity.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/models/participant.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/models/room.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/models/task.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/ai/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/ai/base.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/ai/mock.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/anthropic/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/anthropic/ai.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/anthropic/config.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/elasticemail/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/elasticemail/config.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/elasticemail/email.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/email/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/email/base.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/email/mock.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/gemini/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/gemini/ai.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/gemini/config.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/http/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/http/base.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/http/config.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/http/mock.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/http/provider.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/http/webhook.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/messenger/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/messenger/base.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/messenger/config.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/messenger/facebook.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/messenger/mock.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/messenger/webhook.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/openai/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/openai/ai.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/openai/config.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/pydantic_ai/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/pydantic_ai/config.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/rcs/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/rcs/base.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/rcs/mock.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/sendgrid/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/sendgrid/config.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/sinch/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/sinch/config.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/sinch/sms.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/sms/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/sms/base.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/sms/meta.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/sms/mock.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/sms/phone.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/telnyx/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/telnyx/config.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/telnyx/rcs.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/telnyx/sms.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/twilio/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/twilio/config.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/twilio/rcs.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/twilio/sms.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/voicemeup/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/voicemeup/config.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/voicemeup/sms.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/whatsapp/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/whatsapp/base.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/providers/whatsapp/mock.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/py.typed +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/realtime/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/realtime/base.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/realtime/memory.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/sources/base.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/sources/websocket.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/store/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/store/base.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/src/roomkit/store/memory.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/conftest.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_ai_docs.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_channel_abc.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_channels/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_channels/test_ai.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_channels/test_email.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_channels/test_http.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_channels/test_messenger.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_channels/test_sms.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_channels/test_websocket.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_channels/test_whatsapp.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_circuit_breaker.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_configs.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_framework_events.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_framework_queries.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_hook_side_effects.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_hooks.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_identity_hooks.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_identity_pipeline.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_inbound_routing.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_integration/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_integration/test_ai_assistant.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_integration/test_ai_chain_depth.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_integration/test_cross_channel.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_integration/test_dynamic_channels.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_integration/test_human_ai.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_integration/test_identity_resolution.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_integration/test_observer.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_integration/test_sin_scanning.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_lifecycle_hooks.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_locks.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_mock_providers.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_models.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_observability.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/__init__.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_anthropic.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_elasticemail.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_gemini.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_http.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_messenger.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_openai.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_phone.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_rcs.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_sinch.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_sms_utils.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_telnyx.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_telnyx_rcs.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_twilio.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_providers/test_voicemeup.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_realtime.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_resilience.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_router.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_sources.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_sources_websocket.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_store_memory.py +0 -0
- {roomkit-0.1.1 → roomkit-0.2.1}/tests/test_websocket_lifecycle.py +0 -0
|
@@ -44,6 +44,7 @@ src/roomkit/
|
|
|
44
44
|
│ ├── base.py # Channel ABC
|
|
45
45
|
│ ├── transport.py # TransportChannel (SMS, Email, etc.)
|
|
46
46
|
│ ├── ai.py # AIChannel (intelligence layer)
|
|
47
|
+
│ ├── voice.py # VoiceChannel (real-time audio)
|
|
47
48
|
│ └── websocket.py # WebSocketChannel
|
|
48
49
|
├── providers/
|
|
49
50
|
│ ├── ai/base.py # AIProvider ABC, AIContext, AIResponse
|
|
@@ -66,6 +67,22 @@ src/roomkit/
|
|
|
66
67
|
├── realtime/
|
|
67
68
|
│ ├── base.py # RealtimeBackend ABC, EphemeralEvent
|
|
68
69
|
│ └── memory.py # InMemoryRealtime
|
|
70
|
+
├── voice/
|
|
71
|
+
│ ├── __init__.py # Voice subsystem exports
|
|
72
|
+
│ ├── base.py # Shared types (AudioChunk, VoiceSession, callbacks)
|
|
73
|
+
│ ├── events.py # Voice-specific events
|
|
74
|
+
│ ├── stt/ # Speech-to-text providers
|
|
75
|
+
│ │ ├── base.py # STTProvider ABC
|
|
76
|
+
│ │ ├── mock.py # MockSTTProvider
|
|
77
|
+
│ │ └── deepgram.py # DeepgramSTTProvider
|
|
78
|
+
│ ├── tts/ # Text-to-speech providers
|
|
79
|
+
│ │ ├── base.py # TTSProvider ABC
|
|
80
|
+
│ │ ├── mock.py # MockTTSProvider
|
|
81
|
+
│ │ └── elevenlabs.py # ElevenLabsTTSProvider
|
|
82
|
+
│ └── backends/ # Voice transport backends
|
|
83
|
+
│ ├── base.py # VoiceBackend ABC
|
|
84
|
+
│ ├── mock.py # MockVoiceBackend, MockVoiceCall
|
|
85
|
+
│ └── fastrtc.py # FastRTCVoiceBackend (WebRTC)
|
|
69
86
|
└── identity/
|
|
70
87
|
├── base.py # IdentityResolver ABC
|
|
71
88
|
└── mock.py # MockIdentityResolver
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: roomkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Pure async Python library for multi-channel conversations
|
|
5
5
|
Project-URL: Homepage, https://roomkit.live
|
|
6
6
|
Project-URL: Repository, https://github.com/sboily/roomkit
|
|
@@ -30,6 +30,7 @@ Requires-Dist: anthropic>=0.30; extra == 'anthropic'
|
|
|
30
30
|
Provides-Extra: dev
|
|
31
31
|
Requires-Dist: anthropic>=0.30; extra == 'dev'
|
|
32
32
|
Requires-Dist: google-genai>=1.0.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: httpx-sse>=0.4; extra == 'dev'
|
|
33
34
|
Requires-Dist: httpx>=0.27; extra == 'dev'
|
|
34
35
|
Requires-Dist: mkdocs-material>=9.5; extra == 'dev'
|
|
35
36
|
Requires-Dist: mkdocs>=1.6; extra == 'dev'
|
|
@@ -49,6 +50,9 @@ Provides-Extra: docs
|
|
|
49
50
|
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
|
|
50
51
|
Requires-Dist: mkdocs>=1.6; extra == 'docs'
|
|
51
52
|
Requires-Dist: mkdocstrings[python]>=0.27; extra == 'docs'
|
|
53
|
+
Provides-Extra: fastrtc
|
|
54
|
+
Requires-Dist: fastrtc; extra == 'fastrtc'
|
|
55
|
+
Requires-Dist: numpy; extra == 'fastrtc'
|
|
52
56
|
Provides-Extra: gemini
|
|
53
57
|
Requires-Dist: google-genai>=1.0.0; extra == 'gemini'
|
|
54
58
|
Provides-Extra: httpx
|
|
@@ -68,7 +72,12 @@ Requires-Dist: pydantic-ai>=0.1; extra == 'pydantic-ai'
|
|
|
68
72
|
Provides-Extra: pynacl
|
|
69
73
|
Requires-Dist: pynacl>=1.5; extra == 'pynacl'
|
|
70
74
|
Provides-Extra: sources
|
|
75
|
+
Requires-Dist: httpx-sse>=0.4; extra == 'sources'
|
|
76
|
+
Requires-Dist: httpx>=0.27; extra == 'sources'
|
|
71
77
|
Requires-Dist: websockets>=13.0; extra == 'sources'
|
|
78
|
+
Provides-Extra: sse
|
|
79
|
+
Requires-Dist: httpx-sse>=0.4; extra == 'sse'
|
|
80
|
+
Requires-Dist: httpx>=0.27; extra == 'sse'
|
|
72
81
|
Provides-Extra: twilio
|
|
73
82
|
Requires-Dist: twilio>=9.0; extra == 'twilio'
|
|
74
83
|
Provides-Extra: websocket
|
|
@@ -83,14 +92,14 @@ Description-Content-Type: text/markdown
|
|
|
83
92
|
|
|
84
93
|
Pure async Python 3.12+ library for multi-channel conversations.
|
|
85
94
|
|
|
86
|
-
RoomKit gives you a single abstraction — the **room** — to orchestrate messages across SMS, RCS, Email, WhatsApp, Messenger, WebSocket, HTTP webhooks, and AI channels. Events flow in through any channel, get validated by hooks, and broadcast to every other channel in the room with automatic content transcoding.
|
|
95
|
+
RoomKit gives you a single abstraction — the **room** — to orchestrate messages across SMS, RCS, Email, WhatsApp, Messenger, Voice, WebSocket, HTTP webhooks, and AI channels. Events flow in through any channel, get validated by hooks, and broadcast to every other channel in the room with automatic content transcoding.
|
|
87
96
|
|
|
88
97
|
```
|
|
89
98
|
Inbound ──► Hook pipeline ──► Store ──► Broadcast to all channels
|
|
90
99
|
│
|
|
91
|
-
|
|
92
|
-
▼ ▼ ▼ ▼ ▼ ▼
|
|
93
|
-
SMS/RCS WebSocket Email Messenger
|
|
100
|
+
┌──────────┬──────────┬────────┼────────┬────────┬────────┐
|
|
101
|
+
▼ ▼ ▼ ▼ ▼ ▼ ▼
|
|
102
|
+
SMS/RCS WebSocket Email Messenger Voice AI Webhook
|
|
94
103
|
```
|
|
95
104
|
|
|
96
105
|
**Website:** [www.roomkit.live](https://www.roomkit.live) | **Docs:** [www.roomkit.live/docs](https://www.roomkit.live/docs/)
|
|
@@ -157,6 +166,7 @@ pip install roomkit[websocket] # WebSocket event source
|
|
|
157
166
|
pip install roomkit[anthropic] # Anthropic Claude AI
|
|
158
167
|
pip install roomkit[openai] # OpenAI GPT
|
|
159
168
|
pip install roomkit[gemini] # Google Gemini AI
|
|
169
|
+
pip install roomkit[fastrtc] # FastRTC voice backend
|
|
160
170
|
pip install roomkit[providers] # all transport providers
|
|
161
171
|
pip install roomkit[all] # everything
|
|
162
172
|
```
|
|
@@ -184,10 +194,11 @@ Each channel is a thin adapter between the room and an external transport. All c
|
|
|
184
194
|
| **WebSocket** | `websocket` | text, rich, media | Real-time with typing, reactions |
|
|
185
195
|
| **Messenger** | `messenger` | text, rich, media, template | Buttons, quick replies |
|
|
186
196
|
| **WhatsApp** | `whatsapp` | text, rich, media, location, template | Buttons, templates |
|
|
197
|
+
| **Voice** | `voice` | audio, text | STT/TTS, barge-in, FastRTC streaming |
|
|
187
198
|
| **HTTP** | `webhook` | text, rich | Generic webhook for any system |
|
|
188
199
|
| **AI** | `ai` | text, rich | Intelligence layer (not transport) |
|
|
189
200
|
|
|
190
|
-
Channels have two categories: **transport** (delivers to external systems) and **intelligence** (generates content, like AI).
|
|
201
|
+
Channels have two categories: **transport** (delivers to external systems) and **intelligence** (generates content, like AI). The Voice channel bridges real-time audio with the room-based conversation model.
|
|
191
202
|
|
|
192
203
|
## Providers
|
|
193
204
|
|
|
@@ -217,6 +228,14 @@ Providers handle the actual API calls. Every provider has a mock counterpart for
|
|
|
217
228
|
| `OpenAIAIProvider` | GPT-4, vision, tools | `roomkit[openai]` |
|
|
218
229
|
| `GeminiAIProvider` | Gemini, vision, tools | `roomkit[gemini]` |
|
|
219
230
|
|
|
231
|
+
### Voice Providers
|
|
232
|
+
|
|
233
|
+
| Provider | Role | Dependency |
|
|
234
|
+
|----------|------|------------|
|
|
235
|
+
| `DeepgramSTTProvider` | Speech-to-text | `roomkit[httpx]` |
|
|
236
|
+
| `ElevenLabsTTSProvider` | Text-to-speech | `roomkit[httpx]` |
|
|
237
|
+
| `FastRTCVoiceBackend` | WebRTC audio transport | `roomkit[fastrtc]` |
|
|
238
|
+
|
|
220
239
|
### Other Providers
|
|
221
240
|
|
|
222
241
|
| Provider | Channel | Dependency |
|
|
@@ -542,6 +561,7 @@ src/roomkit/
|
|
|
542
561
|
realtime/ Ephemeral events (typing, presence, read receipts)
|
|
543
562
|
sources/ Event-driven sources (WebSocket, custom)
|
|
544
563
|
store/ Storage abstraction and in-memory implementation
|
|
564
|
+
voice/ Voice subsystem (stt/, tts/, backends/)
|
|
545
565
|
```
|
|
546
566
|
|
|
547
567
|
## Documentation
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
Pure async Python 3.12+ library for multi-channel conversations.
|
|
8
8
|
|
|
9
|
-
RoomKit gives you a single abstraction — the **room** — to orchestrate messages across SMS, RCS, Email, WhatsApp, Messenger, WebSocket, HTTP webhooks, and AI channels. Events flow in through any channel, get validated by hooks, and broadcast to every other channel in the room with automatic content transcoding.
|
|
9
|
+
RoomKit gives you a single abstraction — the **room** — to orchestrate messages across SMS, RCS, Email, WhatsApp, Messenger, Voice, WebSocket, HTTP webhooks, and AI channels. Events flow in through any channel, get validated by hooks, and broadcast to every other channel in the room with automatic content transcoding.
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
Inbound ──► Hook pipeline ──► Store ──► Broadcast to all channels
|
|
13
13
|
│
|
|
14
|
-
|
|
15
|
-
▼ ▼ ▼ ▼ ▼ ▼
|
|
16
|
-
SMS/RCS WebSocket Email Messenger
|
|
14
|
+
┌──────────┬──────────┬────────┼────────┬────────┬────────┐
|
|
15
|
+
▼ ▼ ▼ ▼ ▼ ▼ ▼
|
|
16
|
+
SMS/RCS WebSocket Email Messenger Voice AI Webhook
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
**Website:** [www.roomkit.live](https://www.roomkit.live) | **Docs:** [www.roomkit.live/docs](https://www.roomkit.live/docs/)
|
|
@@ -80,6 +80,7 @@ pip install roomkit[websocket] # WebSocket event source
|
|
|
80
80
|
pip install roomkit[anthropic] # Anthropic Claude AI
|
|
81
81
|
pip install roomkit[openai] # OpenAI GPT
|
|
82
82
|
pip install roomkit[gemini] # Google Gemini AI
|
|
83
|
+
pip install roomkit[fastrtc] # FastRTC voice backend
|
|
83
84
|
pip install roomkit[providers] # all transport providers
|
|
84
85
|
pip install roomkit[all] # everything
|
|
85
86
|
```
|
|
@@ -107,10 +108,11 @@ Each channel is a thin adapter between the room and an external transport. All c
|
|
|
107
108
|
| **WebSocket** | `websocket` | text, rich, media | Real-time with typing, reactions |
|
|
108
109
|
| **Messenger** | `messenger` | text, rich, media, template | Buttons, quick replies |
|
|
109
110
|
| **WhatsApp** | `whatsapp` | text, rich, media, location, template | Buttons, templates |
|
|
111
|
+
| **Voice** | `voice` | audio, text | STT/TTS, barge-in, FastRTC streaming |
|
|
110
112
|
| **HTTP** | `webhook` | text, rich | Generic webhook for any system |
|
|
111
113
|
| **AI** | `ai` | text, rich | Intelligence layer (not transport) |
|
|
112
114
|
|
|
113
|
-
Channels have two categories: **transport** (delivers to external systems) and **intelligence** (generates content, like AI).
|
|
115
|
+
Channels have two categories: **transport** (delivers to external systems) and **intelligence** (generates content, like AI). The Voice channel bridges real-time audio with the room-based conversation model.
|
|
114
116
|
|
|
115
117
|
## Providers
|
|
116
118
|
|
|
@@ -140,6 +142,14 @@ Providers handle the actual API calls. Every provider has a mock counterpart for
|
|
|
140
142
|
| `OpenAIAIProvider` | GPT-4, vision, tools | `roomkit[openai]` |
|
|
141
143
|
| `GeminiAIProvider` | Gemini, vision, tools | `roomkit[gemini]` |
|
|
142
144
|
|
|
145
|
+
### Voice Providers
|
|
146
|
+
|
|
147
|
+
| Provider | Role | Dependency |
|
|
148
|
+
|----------|------|------------|
|
|
149
|
+
| `DeepgramSTTProvider` | Speech-to-text | `roomkit[httpx]` |
|
|
150
|
+
| `ElevenLabsTTSProvider` | Text-to-speech | `roomkit[httpx]` |
|
|
151
|
+
| `FastRTCVoiceBackend` | WebRTC audio transport | `roomkit[fastrtc]` |
|
|
152
|
+
|
|
143
153
|
### Other Providers
|
|
144
154
|
|
|
145
155
|
| Provider | Channel | Dependency |
|
|
@@ -465,6 +475,7 @@ src/roomkit/
|
|
|
465
475
|
realtime/ Ephemeral events (typing, presence, read receipts)
|
|
466
476
|
sources/ Event-driven sources (WebSocket, custom)
|
|
467
477
|
store/ Storage abstraction and in-memory implementation
|
|
478
|
+
voice/ Voice subsystem (stt/, tts/, backends/)
|
|
468
479
|
```
|
|
469
480
|
|
|
470
481
|
## Documentation
|
|
@@ -14,7 +14,8 @@ Full auto-generated reference for the `roomkit` public API.
|
|
|
14
14
|
## Channels
|
|
15
15
|
|
|
16
16
|
- **[Channel ABC](channel.md)** — Base class for all channels
|
|
17
|
-
- **[Built-in Channels](channels.md)** — SMS, Email, AI, WebSocket, WhatsApp, Messenger, HTTP
|
|
17
|
+
- **[Built-in Channels](channels.md)** — SMS, RCS, Email, AI, WebSocket, Voice, WhatsApp, Messenger, HTTP
|
|
18
|
+
- **[Voice Channel](providers-voice.md)** — VoiceBackend, STTProvider, TTSProvider, voice events
|
|
18
19
|
|
|
19
20
|
## Models
|
|
20
21
|
|
|
@@ -29,8 +30,9 @@ Full auto-generated reference for the `roomkit` public API.
|
|
|
29
30
|
## Providers
|
|
30
31
|
|
|
31
32
|
- **[AI](providers-ai.md)** — AIProvider, AIContext, AIResponse
|
|
32
|
-
- **[SMS](providers-sms.md)** — SMSProvider
|
|
33
|
-
- **[
|
|
33
|
+
- **[SMS](providers-sms.md)** — SMSProvider, Sinch, Telnyx, Twilio, VoiceMeUp
|
|
34
|
+
- **[RCS](providers-rcs.md)** — RCSProvider, Telnyx RCS, Twilio RCS
|
|
35
|
+
- **[Email](providers-email.md)** — EmailProvider, ElasticEmail
|
|
34
36
|
- **[WhatsApp](providers-whatsapp.md)** — WhatsAppProvider
|
|
35
|
-
- **[Messenger](providers-messenger.md)** — MessengerProvider
|
|
36
|
-
- **[HTTP](providers-http.md)** — HTTPProvider
|
|
37
|
+
- **[Messenger](providers-messenger.md)** — MessengerProvider, Facebook
|
|
38
|
+
- **[HTTP](providers-http.md)** — HTTPProvider, Webhook
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# RCS Providers
|
|
2
|
+
|
|
3
|
+
## Base Classes
|
|
4
|
+
|
|
5
|
+
::: roomkit.RCSProvider
|
|
6
|
+
|
|
7
|
+
::: roomkit.RCSDeliveryResult
|
|
8
|
+
|
|
9
|
+
::: roomkit.MockRCSProvider
|
|
10
|
+
|
|
11
|
+
## Telnyx
|
|
12
|
+
|
|
13
|
+
::: roomkit.TelnyxRCSProvider
|
|
14
|
+
|
|
15
|
+
::: roomkit.TelnyxRCSConfig
|
|
16
|
+
|
|
17
|
+
::: roomkit.parse_telnyx_rcs_webhook
|
|
18
|
+
|
|
19
|
+
## Twilio
|
|
20
|
+
|
|
21
|
+
::: roomkit.TwilioRCSProvider
|
|
22
|
+
|
|
23
|
+
::: roomkit.TwilioRCSConfig
|
|
24
|
+
|
|
25
|
+
::: roomkit.parse_twilio_rcs_webhook
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Voice Providers
|
|
2
|
+
|
|
3
|
+
## Voice Backend
|
|
4
|
+
|
|
5
|
+
::: roomkit.voice.backends.base.VoiceBackend
|
|
6
|
+
|
|
7
|
+
::: roomkit.VoiceCapability
|
|
8
|
+
|
|
9
|
+
::: roomkit.VoiceSession
|
|
10
|
+
|
|
11
|
+
::: roomkit.VoiceSessionState
|
|
12
|
+
|
|
13
|
+
::: roomkit.AudioChunk
|
|
14
|
+
|
|
15
|
+
::: roomkit.TranscriptionResult
|
|
16
|
+
|
|
17
|
+
## STT (Speech-to-Text)
|
|
18
|
+
|
|
19
|
+
::: roomkit.voice.stt.base.STTProvider
|
|
20
|
+
|
|
21
|
+
::: roomkit.voice.stt.mock.MockSTTProvider
|
|
22
|
+
|
|
23
|
+
## TTS (Text-to-Speech)
|
|
24
|
+
|
|
25
|
+
::: roomkit.voice.tts.base.TTSProvider
|
|
26
|
+
|
|
27
|
+
::: roomkit.voice.tts.mock.MockTTSProvider
|
|
28
|
+
|
|
29
|
+
## Mock Voice Backend
|
|
30
|
+
|
|
31
|
+
::: roomkit.voice.backends.mock.MockVoiceBackend
|
|
32
|
+
|
|
33
|
+
::: roomkit.voice.backends.mock.MockVoiceCall
|
|
34
|
+
|
|
35
|
+
## Voice Events
|
|
36
|
+
|
|
37
|
+
::: roomkit.BargeInEvent
|
|
38
|
+
|
|
39
|
+
::: roomkit.TTSCancelledEvent
|
|
40
|
+
|
|
41
|
+
::: roomkit.PartialTranscriptionEvent
|
|
42
|
+
|
|
43
|
+
::: roomkit.VADSilenceEvent
|
|
44
|
+
|
|
45
|
+
::: roomkit.VADAudioLevelEvent
|
|
46
|
+
|
|
47
|
+
## Callback Types
|
|
48
|
+
|
|
49
|
+
| Callback | Signature |
|
|
50
|
+
|----------|-----------|
|
|
51
|
+
| `SpeechStartCallback` | `(VoiceSession) -> Any` |
|
|
52
|
+
| `SpeechEndCallback` | `(VoiceSession, bytes) -> Any` |
|
|
53
|
+
| `PartialTranscriptionCallback` | `(VoiceSession, str, float, bool) -> Any` |
|
|
54
|
+
| `VADSilenceCallback` | `(VoiceSession, int) -> Any` |
|
|
55
|
+
| `VADAudioLevelCallback` | `(VoiceSession, float, bool) -> Any` |
|
|
56
|
+
| `BargeInCallback` | `(VoiceSession) -> Any` |
|
|
@@ -266,6 +266,130 @@ WebSocketSource requires the `websockets` package:
|
|
|
266
266
|
pip install roomkit[websocket]
|
|
267
267
|
```
|
|
268
268
|
|
|
269
|
+
### SSESource
|
|
270
|
+
|
|
271
|
+
Connect to a Server-Sent Events (SSE) endpoint and receive real-time updates:
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
from roomkit import RoomKit
|
|
275
|
+
from roomkit.sources import SSESource
|
|
276
|
+
|
|
277
|
+
# Basic usage with default JSON parser
|
|
278
|
+
source = SSESource(
|
|
279
|
+
url="https://api.example.com/events",
|
|
280
|
+
channel_id="sse-events",
|
|
281
|
+
)
|
|
282
|
+
await kit.attach_source("sse-events", source)
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
The default parser expects SSE `data` fields to contain JSON:
|
|
286
|
+
|
|
287
|
+
```json
|
|
288
|
+
{
|
|
289
|
+
"sender_id": "user123",
|
|
290
|
+
"text": "Hello world",
|
|
291
|
+
"external_id": "msg-456",
|
|
292
|
+
"metadata": {"key": "value"}
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Supported event types: `message`, `msg`, `chat`, or empty (default). Other event types (e.g., `ping`, `heartbeat`) are skipped.
|
|
297
|
+
|
|
298
|
+
#### Custom SSE Parser
|
|
299
|
+
|
|
300
|
+
For custom SSE formats, provide a parser function that receives the event type, data, and optional event ID:
|
|
301
|
+
|
|
302
|
+
```python
|
|
303
|
+
from roomkit import InboundMessage, TextContent
|
|
304
|
+
|
|
305
|
+
def my_parser(event: str, data: str, event_id: str | None) -> InboundMessage | None:
|
|
306
|
+
"""Parse custom SSE events."""
|
|
307
|
+
if event != "chat":
|
|
308
|
+
return None # Only process 'chat' events
|
|
309
|
+
|
|
310
|
+
# Parse custom format: "user:message"
|
|
311
|
+
parts = data.split(":", 1)
|
|
312
|
+
if len(parts) < 2:
|
|
313
|
+
return None
|
|
314
|
+
|
|
315
|
+
return InboundMessage(
|
|
316
|
+
channel_id="sse-chat",
|
|
317
|
+
sender_id=parts[0],
|
|
318
|
+
content=TextContent(body=parts[1]),
|
|
319
|
+
external_id=event_id,
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
source = SSESource(
|
|
323
|
+
url="https://stream.example.com/chat",
|
|
324
|
+
channel_id="sse-chat",
|
|
325
|
+
parser=my_parser,
|
|
326
|
+
)
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
#### SSESource Options
|
|
330
|
+
|
|
331
|
+
| Parameter | Type | Default | Description |
|
|
332
|
+
|-----------|------|---------|-------------|
|
|
333
|
+
| `url` | `str` | required | SSE endpoint URL |
|
|
334
|
+
| `channel_id` | `str` | required | Channel ID for emitted messages |
|
|
335
|
+
| `parser` | `Callable` | JSON parser | Function to parse SSE events: `(event, data, id) -> InboundMessage` |
|
|
336
|
+
| `headers` | `dict[str, str]` | `None` | HTTP headers (e.g., Authorization) |
|
|
337
|
+
| `params` | `dict[str, str]` | `None` | Query parameters for the URL |
|
|
338
|
+
| `timeout` | `float` | `30.0` | Connection timeout in seconds |
|
|
339
|
+
| `last_event_id` | `str` | `None` | Resume from this event ID (sent as `Last-Event-ID` header) |
|
|
340
|
+
|
|
341
|
+
#### Resuming from Last Event ID
|
|
342
|
+
|
|
343
|
+
SSE supports resumption via the `Last-Event-ID` header. SSESource tracks the last received event ID automatically:
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
# Initial connection
|
|
347
|
+
source = SSESource(
|
|
348
|
+
url="https://api.example.com/events",
|
|
349
|
+
channel_id="sse-events",
|
|
350
|
+
)
|
|
351
|
+
await kit.attach_source("sse-events", source)
|
|
352
|
+
|
|
353
|
+
# ... connection drops ...
|
|
354
|
+
|
|
355
|
+
# Get the last event ID for resumption
|
|
356
|
+
last_id = source.last_event_id
|
|
357
|
+
print(f"Last received event: {last_id}")
|
|
358
|
+
|
|
359
|
+
# Create new source that resumes from last position
|
|
360
|
+
resumed_source = SSESource(
|
|
361
|
+
url="https://api.example.com/events",
|
|
362
|
+
channel_id="sse-events",
|
|
363
|
+
last_event_id=last_id,
|
|
364
|
+
)
|
|
365
|
+
await kit.attach_source("sse-events", resumed_source)
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
When `auto_restart=True` (default), RoomKit automatically handles reconnection and uses the tracked `last_event_id` for seamless resumption.
|
|
369
|
+
|
|
370
|
+
#### Authentication
|
|
371
|
+
|
|
372
|
+
Pass authentication via headers:
|
|
373
|
+
|
|
374
|
+
```python
|
|
375
|
+
source = SSESource(
|
|
376
|
+
url="https://api.example.com/events",
|
|
377
|
+
channel_id="sse-events",
|
|
378
|
+
headers={
|
|
379
|
+
"Authorization": "Bearer your-token-here",
|
|
380
|
+
"X-API-Key": "your-api-key",
|
|
381
|
+
},
|
|
382
|
+
)
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
#### Installation
|
|
386
|
+
|
|
387
|
+
SSESource requires `httpx` and `httpx-sse`:
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
pip install roomkit[sse]
|
|
391
|
+
```
|
|
392
|
+
|
|
269
393
|
## Implementing a Custom Source
|
|
270
394
|
|
|
271
395
|
Extend `SourceProvider` or `BaseSourceProvider` to create custom sources:
|
|
@@ -17,6 +17,9 @@ graph TB
|
|
|
17
17
|
WA_EXT["WhatsApp"]
|
|
18
18
|
HTTP_EXT["HTTP Webhooks"]
|
|
19
19
|
AI_EXT["AI APIs (Anthropic, OpenAI, Gemini)"]
|
|
20
|
+
VOICE_EXT["Voice Clients (FastRTC / WebRTC)"]
|
|
21
|
+
STT_EXT["STT (Deepgram)"]
|
|
22
|
+
TTS_EXT["TTS (ElevenLabs)"]
|
|
20
23
|
end
|
|
21
24
|
|
|
22
25
|
subgraph RoomKit["RoomKit Orchestrator"]
|
|
@@ -40,6 +43,13 @@ graph TB
|
|
|
40
43
|
WA_CH["WhatsAppChannel"]
|
|
41
44
|
HTTP_CH["HTTPChannel"]
|
|
42
45
|
AI_CH["AIChannel"]
|
|
46
|
+
VOICE_CH["VoiceChannel"]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
subgraph VoiceStack["Voice Stack"]
|
|
50
|
+
VB["VoiceBackend (FastRTC)"]
|
|
51
|
+
STT["STTProvider (Deepgram)"]
|
|
52
|
+
TTS["TTSProvider (ElevenLabs)"]
|
|
43
53
|
end
|
|
44
54
|
|
|
45
55
|
subgraph Storage["Storage Layer"]
|
|
@@ -55,6 +65,7 @@ graph TB
|
|
|
55
65
|
WA_EXT --> WA_CH
|
|
56
66
|
HTTP_EXT --> HTTP_CH
|
|
57
67
|
AI_EXT --> AI_CH
|
|
68
|
+
VOICE_EXT --> VB
|
|
58
69
|
|
|
59
70
|
WS_CH --> IR
|
|
60
71
|
SMS_CH --> IR
|
|
@@ -62,6 +73,7 @@ graph TB
|
|
|
62
73
|
EMAIL_CH --> IR
|
|
63
74
|
MSG_CH --> IR
|
|
64
75
|
HTTP_CH --> IR
|
|
76
|
+
VOICE_CH --> IR
|
|
65
77
|
|
|
66
78
|
IR --> IP
|
|
67
79
|
IP --> HE
|
|
@@ -78,6 +90,7 @@ graph TB
|
|
|
78
90
|
ER --> WA_CH
|
|
79
91
|
ER --> HTTP_CH
|
|
80
92
|
ER --> AI_CH
|
|
93
|
+
ER --> VOICE_CH
|
|
81
94
|
|
|
82
95
|
HE --> STORE
|
|
83
96
|
ER --> STORE
|
|
@@ -85,6 +98,13 @@ graph TB
|
|
|
85
98
|
|
|
86
99
|
WS_CH -.-> RT
|
|
87
100
|
RT -.-> WS_CH
|
|
101
|
+
|
|
102
|
+
VOICE_CH --> VB
|
|
103
|
+
VOICE_CH --> STT
|
|
104
|
+
VOICE_CH --> TTS
|
|
105
|
+
VB --> VOICE_EXT
|
|
106
|
+
STT --> STT_EXT
|
|
107
|
+
TTS --> TTS_EXT
|
|
88
108
|
```
|
|
89
109
|
|
|
90
110
|
---
|
|
@@ -135,9 +155,42 @@ All transport channels (SMS, RCS, Email, WhatsApp, Messenger, HTTP) use the unif
|
|
|
135
155
|
| `WhatsAppChannel` | Transport | `WhatsAppChannel()` factory | WhatsApp Business (mock only) |
|
|
136
156
|
| `HTTPChannel` | Transport | `HTTPChannel()` factory | Generic webhook |
|
|
137
157
|
| `AIChannel` | Intelligence | Direct class | Anthropic Claude, OpenAI GPT, Google Gemini |
|
|
158
|
+
| `VoiceChannel` | Transport | Direct class | FastRTC backend + Deepgram STT + ElevenLabs TTS |
|
|
138
159
|
|
|
139
160
|
The `TransportChannel` class is data-driven: it reads a `recipient_key` from binding metadata for the delivery address, and passes configurable `defaults` to the provider's `send()` method. This eliminates the need for per-channel subclasses.
|
|
140
161
|
|
|
162
|
+
### Voice Stack
|
|
163
|
+
|
|
164
|
+
The voice subsystem provides real-time audio support via three pluggable abstractions:
|
|
165
|
+
|
|
166
|
+
| Component | ABC | Implementations | Responsibility |
|
|
167
|
+
|---|---|---|---|
|
|
168
|
+
| **VoiceBackend** | `voice/base.py` | `FastRTCVoiceBackend` (FastRTC WebSocket), `MockVoiceBackend` | Audio transport: WebSocket/WebRTC connections, VAD callbacks, session management, audio streaming |
|
|
169
|
+
| **STTProvider** | `voice/stt.py` | `DeepgramSTTProvider`, `MockSTTProvider` | Speech-to-text: transcribe audio chunks or streams to text |
|
|
170
|
+
| **TTSProvider** | `voice/tts.py` | `ElevenLabsTTSProvider`, `MockTTSProvider` | Text-to-speech: synthesize text to audio chunks for streaming |
|
|
171
|
+
|
|
172
|
+
The `VoiceChannel` orchestrates the full pipeline:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
Client audio → VoiceBackend (VAD) → STTProvider → Hook pipeline → process_inbound()
|
|
176
|
+
↓
|
|
177
|
+
Client audio ← VoiceBackend ← TTSProvider ← AI response ← Event broadcast
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**VoiceBackend capabilities** are declared via `VoiceCapability` flags:
|
|
181
|
+
- `INTERRUPTION` -- Backend can cancel ongoing audio playback
|
|
182
|
+
- `PARTIAL_STT` -- Backend provides partial/streaming transcription
|
|
183
|
+
- `VAD_SILENCE` -- Backend emits silence detection events
|
|
184
|
+
- `VAD_AUDIO_LEVEL` -- Backend emits periodic audio level events
|
|
185
|
+
- `BARGE_IN` -- Backend detects user interrupting TTS playback
|
|
186
|
+
|
|
187
|
+
**Voice hook triggers** extend the standard hook system:
|
|
188
|
+
- `ON_SPEECH_START`, `ON_SPEECH_END` -- VAD events
|
|
189
|
+
- `ON_TRANSCRIPTION` -- After STT, sync (can modify or block the text)
|
|
190
|
+
- `BEFORE_TTS`, `AFTER_TTS` -- Around TTS synthesis, sync (can modify text)
|
|
191
|
+
- `ON_BARGE_IN`, `ON_TTS_CANCELLED` -- Interruption events
|
|
192
|
+
- `ON_PARTIAL_TRANSCRIPTION`, `ON_VAD_SILENCE`, `ON_VAD_AUDIO_LEVEL` -- Streaming events
|
|
193
|
+
|
|
141
194
|
### Storage Layer
|
|
142
195
|
|
|
143
196
|
The `ConversationStore` ABC defines the complete persistence interface:
|
|
@@ -273,6 +326,49 @@ flowchart TD
|
|
|
273
326
|
|
|
274
327
|
This ensures AI-to-AI conversations complete atomically within a single `process_inbound` call, bounded by the `max_chain_depth` limit.
|
|
275
328
|
|
|
329
|
+
### Voice Pipeline
|
|
330
|
+
|
|
331
|
+
When a `VoiceChannel` is configured with a backend, STT, and TTS, the full real-time voice pipeline runs:
|
|
332
|
+
|
|
333
|
+
```mermaid
|
|
334
|
+
sequenceDiagram
|
|
335
|
+
participant Client as Voice Client (Browser)
|
|
336
|
+
participant VB as VoiceBackend (FastRTC)
|
|
337
|
+
participant VC as VoiceChannel
|
|
338
|
+
participant STT as STTProvider (Deepgram)
|
|
339
|
+
participant HE as Hook Engine
|
|
340
|
+
participant RK as RoomKit (process_inbound)
|
|
341
|
+
participant AI as AIChannel
|
|
342
|
+
participant TTS as TTSProvider (ElevenLabs)
|
|
343
|
+
|
|
344
|
+
Client->>VB: Audio stream (WebSocket)
|
|
345
|
+
VB->>VB: VAD: detect speech start
|
|
346
|
+
VB->>VC: on_speech_start(session)
|
|
347
|
+
VC->>HE: ON_SPEECH_START hooks
|
|
348
|
+
|
|
349
|
+
VB->>VB: VAD: detect pause (speech end)
|
|
350
|
+
VB->>VC: on_speech_end(session, audio_bytes)
|
|
351
|
+
VC->>HE: ON_SPEECH_END hooks
|
|
352
|
+
VC->>STT: transcribe(audio_chunk)
|
|
353
|
+
STT-->>VC: "Hello, I need help"
|
|
354
|
+
|
|
355
|
+
VC->>VB: send_transcription(session, text, "user")
|
|
356
|
+
VC->>HE: ON_TRANSCRIPTION hooks (sync, can block/modify)
|
|
357
|
+
|
|
358
|
+
VC->>RK: process_inbound(InboundMessage)
|
|
359
|
+
RK->>AI: Event broadcast
|
|
360
|
+
AI-->>RK: AI response text
|
|
361
|
+
|
|
362
|
+
RK->>VC: deliver(event) with AI response
|
|
363
|
+
VC->>HE: BEFORE_TTS hooks (sync, can modify)
|
|
364
|
+
VC->>VB: send_transcription(session, text, "assistant")
|
|
365
|
+
VC->>TTS: synthesize_stream(text)
|
|
366
|
+
TTS-->>VC: AudioChunk stream
|
|
367
|
+
VC->>VB: send_audio(session, stream)
|
|
368
|
+
VB->>Client: mu-law audio (WebSocket)
|
|
369
|
+
VC->>HE: AFTER_TTS hooks
|
|
370
|
+
```
|
|
371
|
+
|
|
276
372
|
---
|
|
277
373
|
|
|
278
374
|
## External Integrations
|
|
@@ -291,6 +387,16 @@ All AI providers support:
|
|
|
291
387
|
- **Function calling / tools** via the `AITool` model
|
|
292
388
|
- **Vision** (Gemini built-in, others configurable via `supports_vision`)
|
|
293
389
|
|
|
390
|
+
### Voice Providers
|
|
391
|
+
|
|
392
|
+
| Provider | SDK | Purpose |
|
|
393
|
+
|---|---|---|
|
|
394
|
+
| Deepgram | `httpx>=0.27`, `websockets>=13.0` | Streaming speech-to-text via `DeepgramSTTProvider` |
|
|
395
|
+
| ElevenLabs | `httpx>=0.27`, `websockets>=13.0` | Text-to-speech synthesis via `ElevenLabsTTSProvider` |
|
|
396
|
+
| FastRTC | `fastrtc`, `numpy` | WebSocket audio transport with VAD via `FastRTCVoiceBackend` |
|
|
397
|
+
|
|
398
|
+
Voice providers use the same **lazy dependency loading** pattern as other providers -- the SDK is imported only when the provider is instantiated. The `roomkit[fastrtc]` optional extra installs FastRTC and NumPy.
|
|
399
|
+
|
|
294
400
|
### Communication Providers
|
|
295
401
|
|
|
296
402
|
| Provider | SDK | Channel | Features |
|