From b815706480d8f44d18e12aef1fac90f4e2c7acbc Mon Sep 17 00:00:00 2001 From: Rachit Mehta Date: Mon, 10 Nov 2025 12:35:08 -0500 Subject: [PATCH] Rename bidirectional components --- .../bidirectional_streaming/__init__.py | 20 +++++------ .../bidirectional_streaming/agent/__init__.py | 4 +-- .../bidirectional_streaming/agent/agent.py | 34 +++++++++---------- .../event_loop/bidirectional_event_loop.py | 14 ++++---- .../bidirectional_streaming/io/audio.py | 2 +- .../models/__init__.py | 16 ++++----- .../models/bidirectional_model.py | 8 ++--- .../models/gemini_live.py | 14 ++++---- .../models/novasonic.py | 14 ++++---- .../bidirectional_streaming/models/openai.py | 10 +++--- .../scripts/test_bidi.py | 4 +-- .../scripts/test_bidi_novasonic.py | 8 ++--- .../scripts/test_bidi_openai.py | 6 ++-- .../scripts/test_gemini_live.py | 6 ++-- .../bidirectional_streaming/types/io.py | 2 +- 15 files changed, 81 insertions(+), 81 deletions(-) diff --git a/src/strands/experimental/bidirectional_streaming/__init__.py b/src/strands/experimental/bidirectional_streaming/__init__.py index 0955a8939..645869c55 100644 --- a/src/strands/experimental/bidirectional_streaming/__init__.py +++ b/src/strands/experimental/bidirectional_streaming/__init__.py @@ -1,18 +1,18 @@ """Bidirectional streaming package.""" # Main components - Primary user interface -from .agent.agent import BidirectionalAgent +from .agent.agent import BidiAgent # IO channels - Hardware abstraction from .io.audio import AudioIO # Model interface (for custom implementations) -from .models.bidirectional_model import BidirectionalModel +from .models.bidirectional_model import BidiModel # Model providers - What users need to create models -from .models.gemini_live import GeminiLiveModel -from .models.novasonic import NovaSonicModel -from .models.openai import OpenAIRealtimeModel +from .models.gemini_live import BidiGeminiLiveModel +from .models.novasonic import BidiNovaSonicModel +from .models.openai import BidiOpenAIRealtimeModel # Event types - For type hints and event handling from .types.bidirectional_streaming import ( @@ -29,13 +29,13 @@ __all__ = [ # Main interface - "BidirectionalAgent", + "BidiAgent", # IO channels "AudioIO", # Model providers - "GeminiLiveModel", - "NovaSonicModel", - "OpenAIRealtimeModel", + "BidiGeminiLiveModel", + "BidiNovaSonicModel", + "BidiOpenAIRealtimeModel", # Event types "AudioInputEvent", @@ -48,5 +48,5 @@ "VoiceActivityEvent", "UsageMetricsEvent", # Model interface - "BidirectionalModel", + "BidiModel", ] diff --git a/src/strands/experimental/bidirectional_streaming/agent/__init__.py b/src/strands/experimental/bidirectional_streaming/agent/__init__.py index c490e001d..564973099 100644 --- a/src/strands/experimental/bidirectional_streaming/agent/__init__.py +++ b/src/strands/experimental/bidirectional_streaming/agent/__init__.py @@ -1,5 +1,5 @@ """Bidirectional agent for real-time streaming conversations.""" -from .agent import BidirectionalAgent +from .agent import BidiAgent -__all__ = ["BidirectionalAgent"] +__all__ = ["BidiAgent"] diff --git a/src/strands/experimental/bidirectional_streaming/agent/agent.py b/src/strands/experimental/bidirectional_streaming/agent/agent.py index aae029ab1..b5dcd428b 100644 --- a/src/strands/experimental/bidirectional_streaming/agent/agent.py +++ b/src/strands/experimental/bidirectional_streaming/agent/agent.py @@ -27,9 +27,9 @@ from ....types.content import Message, Messages from ....types.tools import ToolResult, ToolUse, AgentTool -from ..event_loop.bidirectional_event_loop import BidirectionalAgentLoop -from ..models.bidirectional_model import BidirectionalModel -from ..models.novasonic import NovaSonicModel +from ..event_loop.bidirectional_event_loop import BidiAgentLoop +from ..models.bidirectional_model import BidiModel +from ..models.novasonic import BidiNovaSonicModel from ..types.bidirectional_streaming import AudioInputEvent, BidirectionalStreamEvent, ImageInputEvent from ..types import BidiIO from ....experimental.tools import ToolProvider @@ -42,7 +42,7 @@ BidirectionalInput = str | AudioInputEvent | ImageInputEvent -class BidirectionalAgent: +class BidiAgent: """Agent for bidirectional streaming conversations. Enables real-time audio and text interaction with AI models through persistent @@ -51,7 +51,7 @@ class BidirectionalAgent: def __init__( self, - model: BidirectionalModel| str | None = None, + model: BidiModel| str | None = None, tools: list[str| AgentTool| ToolProvider]| None = None, system_prompt: str | None = None, messages: Messages | None = None, @@ -66,7 +66,7 @@ def __init__( """Initialize bidirectional agent. Args: - model: BidirectionalModel instance, string model_id, or None for default detection. + model: BidiModel instance, string model_id, or None for default detection. tools: Optional list of tools with flexible format support. system_prompt: Optional system prompt for conversations. messages: Optional conversation history to initialize with. @@ -83,9 +83,9 @@ def __init__( TypeError: If model type is unsupported. """ self.model = ( - NovaSonicModel() + BidiNovaSonicModel() if not model - else NovaSonicModel(model_id=model) + else BidiNovaSonicModel(model_id=model) if isinstance(model, str) else model ) @@ -121,7 +121,7 @@ def __init__( self._tool_caller = _ToolCaller(self) # connection management - self._agent_loop: "BidirectionalAgentLoop" | None = None + self._agent_loop: "BidiAgentLoop" | None = None self._output_queue = asyncio.Queue() self._current_adapters = [] # Track adapters for cleanup @@ -134,7 +134,7 @@ def tool(self) -> _ToolCaller: Example: ``` - agent = BidirectionalAgent(model=model, tools=[calculator]) + agent = BidiAgent(model=model, tools=[calculator]) agent.tool.calculator(expression="2+2") ``` """ @@ -252,11 +252,11 @@ async def start(self) -> None: logger.debug("Conversation start - initializing connection") # Create model session and event loop directly - await self.model.connect( + await self.model.start( system_prompt=self.system_prompt, tools=self.tool_registry.get_all_tool_specs(), messages=self.messages ) - self._agent_loop = BidirectionalAgentLoop(model=self.model, agent=self) + self._agent_loop = BidiAgentLoop(model=self.model, agent=self) await self._agent_loop.start() logger.debug("Conversation ready") @@ -306,7 +306,7 @@ async def receive(self) -> AsyncIterable[BidirectionalStreamEvent]: except asyncio.TimeoutError: continue - async def end(self) -> None: + async def stop(self) -> None: """End the conversation connection and cleanup all resources. Terminates the streaming connection, cancels background tasks, and @@ -316,7 +316,7 @@ async def end(self) -> None: await self._agent_loop.stop() self._agent_loop = None - async def __aenter__(self) -> "BidirectionalAgent": + async def __aenter__(self) -> "BidiAgent": """Async context manager entry point. Automatically starts the bidirectional connection when entering the context. @@ -350,7 +350,7 @@ async def __aexit__(self, exc_type, exc_val, exc_tb) -> None: for adapter in self._current_adapters: if hasattr(adapter, "cleanup"): try: - adapter.end() + adapter.stop() logger.debug(f"Cleaned up adapter: {type(adapter).__name__}") except Exception as adapter_error: logger.warning(f"Error cleaning up adapter: {adapter_error}") @@ -359,7 +359,7 @@ async def __aexit__(self, exc_type, exc_val, exc_tb) -> None: self._current_adapters = [] # Cleanup agent connection - await self.end() + await self.stop() except Exception as cleanup_error: if exc_type is None: @@ -393,7 +393,7 @@ async def run(self, io_channels: list[BidiIO | tuple[Callable, Callable]]) -> No ```python # With IO channel audio_io = AudioIO(audio_config={"input_sample_rate": 16000}) - agent = BidirectionalAgent(model=model, tools=[calculator]) + agent = BidiAgent(model=model, tools=[calculator]) await agent.run(io_channels=[audio_io]) # With tuple (backward compatibility) diff --git a/src/strands/experimental/bidirectional_streaming/event_loop/bidirectional_event_loop.py b/src/strands/experimental/bidirectional_streaming/event_loop/bidirectional_event_loop.py index 38d92aea8..d7f87f69e 100644 --- a/src/strands/experimental/bidirectional_streaming/event_loop/bidirectional_event_loop.py +++ b/src/strands/experimental/bidirectional_streaming/event_loop/bidirectional_event_loop.py @@ -21,7 +21,7 @@ from ....types._events import ToolResultEvent, ToolStreamEvent from ....types.content import Message from ....types.tools import ToolResult, ToolUse -from ..models.bidirectional_model import BidirectionalModel +from ..models.bidirectional_model import BidiModel logger = logging.getLogger(__name__) @@ -37,12 +37,12 @@ class BidirectionalConnection: handling while providing a simple interface for agent interactions. """ - def __init__(self, model: BidirectionalModel, agent: "BidirectionalAgent") -> None: + def __init__(self, model: BidiModel, agent: "BidiAgent") -> None: """Initialize connection with model and agent reference. Args: model: Bidirectional model instance. - agent: BidirectionalAgent instance for tool registry access. + agent: BidiAgent instance for tool registry access. """ self.model = model self.agent = agent @@ -64,14 +64,14 @@ def __init__(self, model: BidirectionalModel, agent: "BidirectionalAgent") -> No self.tool_count = 0 -async def start_bidirectional_connection(agent: "BidirectionalAgent") -> BidirectionalConnection: +async def start_bidirectional_connection(agent: "BidiAgent") -> BidirectionalConnection: """Initialize bidirectional session with conycurrent background tasks. Creates a model-specific session and starts background tasks for processing model events, executing tools, and managing the session lifecycle. Args: - agent: BidirectionalAgent instance. + agent: BidiAgent instance. Returns: BidirectionalConnection: Active session with background tasks running. @@ -79,7 +79,7 @@ async def start_bidirectional_connection(agent: "BidirectionalAgent") -> Bidirec logger.debug("Starting bidirectional session - initializing model connection") # Connect to model - await agent.model.connect( + await agent.model.start( system_prompt=agent.system_prompt, tools=agent.tool_registry.get_all_tool_specs(), messages=agent.messages ) @@ -136,7 +136,7 @@ async def stop_bidirectional_connection(session: BidirectionalConnection) -> Non await asyncio.gather(*all_tasks, return_exceptions=True) # Close model connection - await session.model.close() + await session.model.stop() logger.debug("Connection closed") diff --git a/src/strands/experimental/bidirectional_streaming/io/audio.py b/src/strands/experimental/bidirectional_streaming/io/audio.py index 4fb60a2b5..a16dce884 100644 --- a/src/strands/experimental/bidirectional_streaming/io/audio.py +++ b/src/strands/experimental/bidirectional_streaming/io/audio.py @@ -176,7 +176,7 @@ async def receive(self, event: dict) -> None: elif role.upper() == "USER": print(f"User: {text}") - def end(self) -> None: + def stop(self) -> None: """Clean up IO channel resources.""" try: if self.input_stream: diff --git a/src/strands/experimental/bidirectional_streaming/models/__init__.py b/src/strands/experimental/bidirectional_streaming/models/__init__.py index 5b0d50687..6d6d6590b 100644 --- a/src/strands/experimental/bidirectional_streaming/models/__init__.py +++ b/src/strands/experimental/bidirectional_streaming/models/__init__.py @@ -1,13 +1,13 @@ """Bidirectional model interfaces and implementations.""" -from .bidirectional_model import BidirectionalModel -from .gemini_live import GeminiLiveModel -from .novasonic import NovaSonicModel -from .openai import OpenAIRealtimeModel +from .bidirectional_model import BidiModel +from .gemini_live import BidiGeminiLiveModel +from .novasonic import BidiNovaSonicModel +from .openai import BidiOpenAIRealtimeModel __all__ = [ - "BidirectionalModel", - "GeminiLiveModel", - "NovaSonicModel", - "OpenAIRealtimeModel", + "BidiModel", + "BidiGeminiLiveModel", + "BidiNovaSonicModel", + "BidiOpenAIRealtimeModel", ] diff --git a/src/strands/experimental/bidirectional_streaming/models/bidirectional_model.py b/src/strands/experimental/bidirectional_streaming/models/bidirectional_model.py index 05fb19e0f..8a4235d15 100644 --- a/src/strands/experimental/bidirectional_streaming/models/bidirectional_model.py +++ b/src/strands/experimental/bidirectional_streaming/models/bidirectional_model.py @@ -27,7 +27,7 @@ logger = logging.getLogger(__name__) -class BidirectionalModel(Protocol): +class BidiModel(Protocol): """Protocol for bidirectional streaming models. This interface defines the contract for models that support persistent streaming @@ -35,7 +35,7 @@ class BidirectionalModel(Protocol): provider-specific protocols while exposing a standardized event-based API. """ - async def connect( + async def start( self, system_prompt: str | None = None, tools: list[ToolSpec] | None = None, @@ -56,12 +56,12 @@ async def connect( """ ... - async def close(self) -> None: + async def stop(self) -> None: """Close the streaming connection and release resources. Terminates the active bidirectional connection and cleans up any associated resources such as network connections, buffers, or background tasks. After - calling close(), the model instance cannot be used until connect() is called again. + calling close(), the model instance cannot be used until start() is called again. """ ... diff --git a/src/strands/experimental/bidirectional_streaming/models/gemini_live.py b/src/strands/experimental/bidirectional_streaming/models/gemini_live.py index ffff98cf1..f719fdac6 100644 --- a/src/strands/experimental/bidirectional_streaming/models/gemini_live.py +++ b/src/strands/experimental/bidirectional_streaming/models/gemini_live.py @@ -1,6 +1,6 @@ """Gemini Live API bidirectional model provider using official Google GenAI SDK. -Implements the BidirectionalModel interface for Google's Gemini Live API using the +Implements the BidiModel interface for Google's Gemini Live API using the official Google GenAI SDK for simplified and robust WebSocket communication. Key improvements over custom WebSocket implementation: @@ -34,7 +34,7 @@ TextOutputEvent, TranscriptEvent, ) -from .bidirectional_model import BidirectionalModel +from .bidirectional_model import BidiModel logger = logging.getLogger(__name__) @@ -44,7 +44,7 @@ GEMINI_CHANNELS = 1 -class GeminiLiveModel(BidirectionalModel): +class BidiGeminiLiveModel(BidiModel): """Gemini Live API implementation using official Google GenAI SDK. Combines model configuration and connection state in a single class. @@ -82,13 +82,13 @@ def __init__( self.client = genai.Client(**client_kwargs) - # Connection state (initialized in connect()) + # Connection state (initialized in start()) self.live_session = None self.live_session_context_manager = None self.session_id = None self._active = False - async def connect( + async def start( self, system_prompt: Optional[str] = None, tools: Optional[List[ToolSpec]] = None, @@ -404,7 +404,7 @@ async def _send_tool_result(self, tool_result: ToolResult) -> None: except Exception as e: logger.error("Error sending tool result: %s", e) - async def close(self) -> None: + async def stop(self) -> None: """Close Gemini Live API connection.""" if not self._active: return @@ -435,7 +435,7 @@ def _build_live_config( if self.live_config: config_dict.update(self.live_config) - # Override with any kwargs from connect() + # Override with any kwargs from start() config_dict.update(kwargs) # Add system instruction if provided diff --git a/src/strands/experimental/bidirectional_streaming/models/novasonic.py b/src/strands/experimental/bidirectional_streaming/models/novasonic.py index e4c0d1565..e8e048064 100644 --- a/src/strands/experimental/bidirectional_streaming/models/novasonic.py +++ b/src/strands/experimental/bidirectional_streaming/models/novasonic.py @@ -1,6 +1,6 @@ """Nova Sonic bidirectional model provider for real-time streaming conversations. -Implements the BidirectionalModel interface for Amazon's Nova Sonic, handling the +Implements the BidiModel interface for Amazon's Nova Sonic, handling the complex event sequencing and audio processing required by Nova Sonic's InvokeModelWithBidirectionalStream protocol. @@ -43,7 +43,7 @@ TextOutputEvent, UsageMetricsEvent, ) -from .bidirectional_model import BidirectionalModel +from .bidirectional_model import BidiModel logger = logging.getLogger(__name__) @@ -78,12 +78,12 @@ RESPONSE_TIMEOUT = 1.0 -class NovaSonicModel(BidirectionalModel): +class BidiNovaSonicModel(BidiModel): """Nova Sonic implementation for bidirectional streaming. Combines model configuration and connection state in a single class. Manages Nova Sonic's complex event sequencing, audio format conversion, and - tool execution patterns while providing the standard BidirectionalModel interface. + tool execution patterns while providing the standard BidiModel interface. """ def __init__( @@ -104,7 +104,7 @@ def __init__( self.region = region self.client = None - # Connection state (initialized in connect()) + # Connection state (initialized in start()) self.stream = None self.session_id = None self._active = False @@ -124,7 +124,7 @@ def __init__( logger.debug("Nova Sonic bidirectional model initialized: %s", model_id) - async def connect( + async def start( self, system_prompt: str | None = None, tools: list[ToolSpec] | None = None, @@ -469,7 +469,7 @@ async def _send_tool_result(self, tool_result: ToolResult) -> None: for event in events: await self._send_nova_event(event) - async def close(self) -> None: + async def stop(self) -> None: """Close Nova Sonic connection with proper cleanup sequence.""" if not self._active: return diff --git a/src/strands/experimental/bidirectional_streaming/models/openai.py b/src/strands/experimental/bidirectional_streaming/models/openai.py index 4bf43b563..312077621 100644 --- a/src/strands/experimental/bidirectional_streaming/models/openai.py +++ b/src/strands/experimental/bidirectional_streaming/models/openai.py @@ -29,7 +29,7 @@ TextOutputEvent, VoiceActivityEvent, ) -from .bidirectional_model import BidirectionalModel +from .bidirectional_model import BidiModel logger = logging.getLogger(__name__) @@ -58,7 +58,7 @@ } -class OpenAIRealtimeModel(BidirectionalModel): +class BidiOpenAIRealtimeModel(BidiModel): """OpenAI Realtime API implementation for bidirectional streaming. Combines model configuration and connection state in a single class. @@ -97,7 +97,7 @@ def __init__( if not self.api_key: raise ValueError("OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass api_key parameter.") - # Connection state (initialized in connect()) + # Connection state (initialized in start()) self.websocket = None self.session_id = None self._active = False @@ -108,7 +108,7 @@ def __init__( logger.debug("OpenAI Realtime bidirectional model initialized: %s", model) - async def connect( + async def start( self, system_prompt: str | None = None, tools: list[ToolSpec] | None = None, @@ -508,7 +508,7 @@ async def _send_tool_result(self, tool_result: ToolResult) -> None: await self._send_event({"type": "conversation.item.create", "item": item_data}) await self._send_event({"type": "response.create"}) - async def close(self) -> None: + async def stop(self) -> None: """Close session and cleanup resources.""" if not self._active: return diff --git a/src/strands/experimental/bidirectional_streaming/scripts/test_bidi.py b/src/strands/experimental/bidirectional_streaming/scripts/test_bidi.py index 57ce8b986..6df0063be 100644 --- a/src/strands/experimental/bidirectional_streaming/scripts/test_bidi.py +++ b/src/strands/experimental/bidirectional_streaming/scripts/test_bidi.py @@ -7,7 +7,7 @@ sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent.parent)) from strands.experimental.bidirectional_streaming.agent.agent import BidirectionalAgent -from strands.experimental.bidirectional_streaming.models.novasonic import NovaSonicModel +from strands.experimental.bidirectional_streaming.models.novasonic import BidiNovaSonicModel from strands.experimental.bidirectional_streaming.io.audio import AudioIO from strands_tools import calculator @@ -18,7 +18,7 @@ async def main(): # Nova Sonic model adapter = AudioIO() - model = NovaSonicModel(region="us-east-1") + model = BidiNovaSonicModel(region="us-east-1") async with BidirectionalAgent(model=model, tools=[calculator]) as agent: print("New BidirectionalAgent Experience") diff --git a/src/strands/experimental/bidirectional_streaming/scripts/test_bidi_novasonic.py b/src/strands/experimental/bidirectional_streaming/scripts/test_bidi_novasonic.py index b0a41f20d..173c091ac 100644 --- a/src/strands/experimental/bidirectional_streaming/scripts/test_bidi_novasonic.py +++ b/src/strands/experimental/bidirectional_streaming/scripts/test_bidi_novasonic.py @@ -17,7 +17,7 @@ from strands_tools import calculator from strands.experimental.bidirectional_streaming.agent.agent import BidirectionalAgent -from strands.experimental.bidirectional_streaming.models.novasonic import NovaSonicModel +from strands.experimental.bidirectional_streaming.models.novasonic import BidiNovaSonicModel def test_direct_tools(): @@ -30,7 +30,7 @@ def test_direct_tools(): return try: - model = NovaSonicModel() + model = BidiNovaSonicModel() agent = BidirectionalAgent(model=model, tools=[calculator]) # Test calculator @@ -185,7 +185,7 @@ async def main(duration=180): print("Audio optimizations: 1024-byte buffers, balanced smooth playback + responsive interruption") # Initialize model and agent - model = NovaSonicModel(region="us-east-1") + model = BidiNovaSonicModel(region="us-east-1") agent = BidirectionalAgent(model=model, tools=[calculator], system_prompt="You are a helpful assistant.") await agent.start() @@ -215,7 +215,7 @@ async def main(duration=180): finally: print("Cleaning up...") context["active"] = False - await agent.end() + await agent.stop() if __name__ == "__main__": diff --git a/src/strands/experimental/bidirectional_streaming/scripts/test_bidi_openai.py b/src/strands/experimental/bidirectional_streaming/scripts/test_bidi_openai.py index 90e82c2bc..a2a8efc90 100644 --- a/src/strands/experimental/bidirectional_streaming/scripts/test_bidi_openai.py +++ b/src/strands/experimental/bidirectional_streaming/scripts/test_bidi_openai.py @@ -14,7 +14,7 @@ from strands_tools import calculator from strands.experimental.bidirectional_streaming.agent.agent import BidirectionalAgent -from strands.experimental.bidirectional_streaming.models.openai import OpenAIRealtimeModel +from strands.experimental.bidirectional_streaming.models.openai import BidiOpenAIRealtimeModel async def play(context): @@ -205,7 +205,7 @@ async def main(): return False # Create OpenAI model - model = OpenAIRealtimeModel( + model = BidiOpenAIRealtimeModel( model="gpt-4o-realtime-preview", api_key=api_key, session={ @@ -269,7 +269,7 @@ async def main(): context["active"] = False try: - await agent.end() + await agent.stop() except Exception as e: print(f"Cleanup error: {e}") diff --git a/src/strands/experimental/bidirectional_streaming/scripts/test_gemini_live.py b/src/strands/experimental/bidirectional_streaming/scripts/test_gemini_live.py index 23e97bd5d..ca0e5f8ef 100644 --- a/src/strands/experimental/bidirectional_streaming/scripts/test_gemini_live.py +++ b/src/strands/experimental/bidirectional_streaming/scripts/test_gemini_live.py @@ -38,7 +38,7 @@ from strands_tools import calculator from strands.experimental.bidirectional_streaming.agent.agent import BidirectionalAgent -from strands.experimental.bidirectional_streaming.models.gemini_live import GeminiLiveModel +from strands.experimental.bidirectional_streaming.models.gemini_live import BidiGeminiLiveModel # Configure logging - debug only for Gemini Live, info for everything else logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') @@ -301,7 +301,7 @@ async def main(duration=180): # Initialize Gemini Live model with proper configuration logger.info("Initializing Gemini Live model with API key") - model = GeminiLiveModel( + model = BidiGeminiLiveModel( model_id="gemini-2.5-flash-native-audio-preview-09-2025", api_key=api_key, params={ @@ -352,7 +352,7 @@ async def main(duration=180): finally: print("Cleaning up...") context["active"] = False - await agent.end() + await agent.stop() if __name__ == "__main__": diff --git a/src/strands/experimental/bidirectional_streaming/types/io.py b/src/strands/experimental/bidirectional_streaming/types/io.py index 98b9b28bd..2e113c74b 100644 --- a/src/strands/experimental/bidirectional_streaming/types/io.py +++ b/src/strands/experimental/bidirectional_streaming/types/io.py @@ -37,7 +37,7 @@ async def receive(self, event: dict) -> None: """ ... - def end(self) -> None: + def stop(self) -> None: """Clean up IO channel resources. Called by the agent during shutdown to ensure proper