@@ -95,6 +95,7 @@ def __init__(
9595 )
9696 self ._store = store_manager
9797 self ._exit_stack : AsyncExitStack | None = None
98+ self ._lock : asyncio .Lock = asyncio .Lock ()
9899
99100 async def _run_in_context (self ) -> AsyncGenerator [Self , None ]:
100101 async with AsyncExitStack () as stack :
@@ -198,45 +199,48 @@ async def reload(
198199 Chats can be resumed after reload by using the same chat_id.
199200 """
200201 # NOTE: Do Not restart MCP Servers when there is on-going query.
201- if self ._exit_stack is None :
202- raise RuntimeError ("Host not initialized" )
203-
204- # Update config
205- old_config = self ._config
206- self ._config = new_config
207-
208- try :
209- # Reload model if needed
210- if old_config .llm != new_config .llm :
211- self ._model = None
212- await self ._init_models ()
213-
214- await self ._tool_manager .reload (
215- new_configs = new_config .mcp_servers , force = force_mcp
216- )
217-
218- # Reload checkpointer if needed
219- if old_config .checkpointer != new_config .checkpointer :
220- if self ._checkpointer is not None :
221- await self ._exit_stack .aclose ()
222- self ._checkpointer = None
223-
224- if new_config .checkpointer :
225- checkpointer = get_checkpointer (str (new_config .checkpointer .uri ))
226- self ._checkpointer = await self ._exit_stack .enter_async_context (
227- checkpointer
228- )
229- await self ._checkpointer .setup ()
230-
231- # Call the reloader function to handle service restart
232- if reloader :
233- await reloader ()
234-
235- except Exception as e :
236- # Restore old config if reload fails
237- self ._config = old_config
238- logging .error ("Failed to reload host: %s" , e )
239- raise
202+ async with self ._lock :
203+ if self ._exit_stack is None :
204+ raise RuntimeError ("Host not initialized" )
205+
206+ # Update config
207+ old_config = self ._config
208+ self ._config = new_config
209+
210+ try :
211+ # Reload model if needed
212+ if old_config .llm != new_config .llm :
213+ self ._model = None
214+ await self ._init_models ()
215+
216+ await self ._tool_manager .reload (
217+ new_configs = new_config .mcp_servers , force = force_mcp
218+ )
219+
220+ # Reload checkpointer if needed
221+ if old_config .checkpointer != new_config .checkpointer :
222+ if self ._checkpointer is not None :
223+ await self ._exit_stack .aclose ()
224+ self ._checkpointer = None
225+
226+ if new_config .checkpointer :
227+ checkpointer = get_checkpointer (
228+ str (new_config .checkpointer .uri )
229+ )
230+ self ._checkpointer = await self ._exit_stack .enter_async_context (
231+ checkpointer
232+ )
233+ await self ._checkpointer .setup ()
234+
235+ # Call the reloader function to handle service restart
236+ if reloader :
237+ await reloader ()
238+
239+ except Exception as e :
240+ # Restore old config if reload fails
241+ self ._config = old_config
242+ logging .error ("Failed to reload host: %s" , e )
243+ raise
240244
241245 @property
242246 def config (self ) -> HostConfig :
0 commit comments