Conversation
| logger.warning("Translator.start() called more than once; ignoring.") | ||
| return | ||
|
|
||
| self._started = True |
There was a problem hiding this comment.
🔴 start() sets _started = True before fallible operations, permanently bricking the Translator on transient failure
If any awaited operation after line 144 raises (e.g. _create_session() returns an auth error, _connect_with_retry() exhausts retries, or publish_track() fails), the self._started flag is already True. Any subsequent call to start() will be silently ignored due to the guard at lines 140-142, making the Translator instance permanently unusable even though it never actually started.
Root Cause and Impact
self._started = True is set at line 144, before all the async operations that can fail (session creation at line 154, room connection at line 160, track publishing at lines 169/180). If any of these raises an exception, the flag remains True and start() can never be retried:
# Line 140-142: guard prevents retry
if self._started:
logger.warning("Translator.start() called more than once; ignoring.")
returnAdditionally, if the failure occurs after self._pinch_room is connected (line 160) but before start() completes, the Pinch room connection is leaked — it's never disconnected because stop() won't know the partial state.
Impact: A single transient failure (network blip, rate limit, publish error) forces the user to discard the entire Translator and create a new one, with no indication that retrying start() is being silently swallowed.
Prompt for agents
In livekit-plugins/livekit-plugins-pinch/livekit/plugins/pinch/translator.py, the `start()` method (line 121) sets `self._started = True` at line 144 before any of the fallible async operations. This should be moved to the very end of `start()` (after line 189, before line 190) so that if any operation fails, `start()` can be retried. Additionally, wrap the body of `start()` in a try/except that performs cleanup (disconnect the pinch room if connected, unpublish tracks if published) and resets `self._started = False` before re-raising the exception. This ensures the Translator is not permanently bricked by a transient failure.
Was this helpful? React with 👍 or 👎 to provide feedback.
| """livekit-plugins-pinch — real-time speech-to-speech translation via Pinch.""" | ||
|
|
||
| from .models import TranscriptEvent, TranslatorOptions | ||
| from .translator import ( | ||
| PinchAuthError, | ||
| PinchError, | ||
| PinchRateLimitError, | ||
| PinchSessionError, | ||
| Translator, | ||
| ) | ||
| from .version import __version__ | ||
|
|
||
| __all__ = [ | ||
| # Core classes | ||
| "Translator", | ||
| "TranslatorOptions", | ||
| "TranscriptEvent", | ||
| # Exceptions | ||
| "PinchError", | ||
| "PinchAuthError", | ||
| "PinchRateLimitError", | ||
| "PinchSessionError", | ||
| # Version | ||
| "__version__", | ||
| ] |
There was a problem hiding this comment.
🔴 Missing Plugin.register_plugin() call prevents framework integration
The Pinch plugin's __init__.py does not define a Plugin subclass or call Plugin.register_plugin(), unlike every other plugin in the repository (58 out of 59 existing plugins do this).
Impact on framework features
The Plugin.registered_plugins list is used in several critical framework paths:
-
Logger configuration (
livekit-agents/livekit/agents/cli/cli.py:1001-1004): Plugin loggers are auto-configured to match the agent's log level. Without registration, thelivekit.plugins.pinchlogger will remain atNOTSET. -
Forkserver preloading (
livekit-agents/livekit/agents/worker.py:646): Registered plugin packages are preloaded in forkserver mode for faster subprocess startup. Pinch won't be preloaded. -
File downloading (
livekit-agents/livekit/agents/cli/cli.py:1937-1940): Thedownload-filesCLI command iterates registered plugins. Pinch will be skipped. -
Hot reload watching (
livekit-agents/livekit/agents/cli/watcher.py:40): The dev mode file watcher monitors registered plugin packages for changes. Pinch file changes won't trigger reloads.
Every other plugin follows this pattern (e.g. livekit-plugins/livekit-plugins-deepgram/livekit/plugins/deepgram/__init__.py):
from livekit.agents import Plugin
from .log import logger
class DeepgramPlugin(Plugin):
def __init__(self) -> None:
super().__init__(__name__, __version__, __package__, logger)
Plugin.register_plugin(DeepgramPlugin())| """livekit-plugins-pinch — real-time speech-to-speech translation via Pinch.""" | |
| from .models import TranscriptEvent, TranslatorOptions | |
| from .translator import ( | |
| PinchAuthError, | |
| PinchError, | |
| PinchRateLimitError, | |
| PinchSessionError, | |
| Translator, | |
| ) | |
| from .version import __version__ | |
| __all__ = [ | |
| # Core classes | |
| "Translator", | |
| "TranslatorOptions", | |
| "TranscriptEvent", | |
| # Exceptions | |
| "PinchError", | |
| "PinchAuthError", | |
| "PinchRateLimitError", | |
| "PinchSessionError", | |
| # Version | |
| "__version__", | |
| ] | |
| """livekit-plugins-pinch — real-time speech-to-speech translation via Pinch.""" | |
| from .models import TranscriptEvent, TranslatorOptions | |
| from .translator import ( | |
| PinchAuthError, | |
| PinchError, | |
| PinchRateLimitError, | |
| PinchSessionError, | |
| Translator, | |
| ) | |
| from .version import __version__ | |
| __all__ = [ | |
| # Core classes | |
| "Translator", | |
| "TranslatorOptions", | |
| "TranscriptEvent", | |
| # Exceptions | |
| "PinchError", | |
| "PinchAuthError", | |
| "PinchRateLimitError", | |
| "PinchSessionError", | |
| # Version | |
| "__version__", | |
| ] | |
| from livekit.agents import Plugin | |
| from .log import logger | |
| class PinchPlugin(Plugin): | |
| def __init__(self) -> None: | |
| super().__init__(__name__, __version__, __package__, logger) | |
| Plugin.register_plugin(PinchPlugin()) |
Was this helpful? React with 👍 or 👎 to provide feedback.
Adds support for Pinch via a LiveKit Agents plugin.
This plugin enables real-time speech translation using the Pinch API through the LiveKit Agents plugin interface.
Includes:
The plugin registers via
livekit.agents.pluginsentry points and loads correctly within the LiveKit Agents workspace.