refactor: unify voice transcription config across all channels

- Move transcriptionProvider to global channels config (not per-channel)
- ChannelManager auto-resolves API key from matching provider config
- BaseChannel gets transcription_provider attribute, no more getattr hack
- Remove redundant transcription fields from WhatsAppConfig
- Update README: document transcriptionProvider, update provider table

Made-with: Cursor
This commit is contained in:
Xubin Ren
2026-04-06 06:07:30 +00:00
parent 7b7a3e5748
commit 35dde8a30e
6 changed files with 21 additions and 15 deletions
+2 -2
View File
@@ -22,6 +22,7 @@ class BaseChannel(ABC):
name: str = "base"
display_name: str = "Base"
transcription_provider: str = "groq"
transcription_api_key: str = ""
def __init__(self, config: Any, bus: MessageBus):
@@ -41,8 +42,7 @@ class BaseChannel(ABC):
if not self.transcription_api_key:
return ""
try:
provider_name = getattr(self, "transcription_provider", "groq")
if provider_name == "openai":
if self.transcription_provider == "openai":
from nanobot.providers.transcription import OpenAITranscriptionProvider
provider = OpenAITranscriptionProvider(api_key=self.transcription_api_key)
else:
+10 -2
View File
@@ -39,7 +39,8 @@ class ChannelManager:
"""Initialize channels discovered via pkgutil scan + entry_points plugins."""
from nanobot.channels.registry import discover_all
groq_key = self.config.providers.groq.api_key
transcription_provider = self.config.channels.transcription_provider
transcription_key = self._resolve_transcription_key(transcription_provider)
for name, cls in discover_all().items():
section = getattr(self.config.channels, name, None)
@@ -54,7 +55,8 @@ class ChannelManager:
continue
try:
channel = cls(section, self.bus)
channel.transcription_api_key = groq_key
channel.transcription_provider = transcription_provider
channel.transcription_api_key = transcription_key
self.channels[name] = channel
logger.info("{} channel enabled", cls.display_name)
except Exception as e:
@@ -62,6 +64,12 @@ class ChannelManager:
self._validate_allow_from()
def _resolve_transcription_key(self, provider: str) -> str:
"""Pick the API key for the configured transcription provider."""
if provider == "openai":
return self.config.providers.openai.api_key
return self.config.providers.groq.api_key
def _validate_allow_from(self) -> None:
for name, ch in self.channels.items():
if getattr(ch.config, "allow_from", None) == []:
-4
View File
@@ -27,8 +27,6 @@ class WhatsAppConfig(Base):
bridge_url: str = "ws://localhost:3001"
bridge_token: str = ""
allow_from: list[str] = Field(default_factory=list)
transcription_provider: str = "openai" # openai or groq
transcription_api_key: str = ""
group_policy: Literal["open", "mention"] = "open" # "open" responds to all, "mention" only when @mentioned
@@ -77,8 +75,6 @@ class WhatsAppChannel(BaseChannel):
self._ws = None
self._connected = False
self._processed_message_ids: OrderedDict[str, None] = OrderedDict()
self.transcription_api_key = config.transcription_api_key
self.transcription_provider = config.transcription_provider
self._bridge_token: str | None = None
def _effective_bridge_token(self) -> str:
+1
View File
@@ -28,6 +28,7 @@ class ChannelsConfig(Base):
send_progress: bool = True # stream agent's text progress to the channel
send_tool_hints: bool = False # stream tool-call hints (e.g. read_file("…"))
send_max_retries: int = Field(default=3, ge=0, le=10) # Max delivery attempts (initial send included)
transcription_provider: str = "groq" # Voice transcription backend: "groq" or "openai"
class DreamConfig(Base):