From 29016a50bcf6587ed5e22409795cc802dfb01b19 Mon Sep 17 00:00:00 2001 From: Erosika Date: Thu, 2 Jul 2026 18:46:52 -0400 Subject: [PATCH] perf(memory): run provider config I/O off the event loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GET walked honcho.json plus dozens of .env reads and PUT rewrote json/.env/ config.yaml — all synchronously inside async handlers, stalling every other in-flight request behind one settings save on a slow disk. Offload both bodies via asyncio.to_thread (the file's existing pattern) and skip the config.yaml rewrite when memory.provider is already the saved provider. --- hermes_cli/web_server.py | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/hermes_cli/web_server.py b/hermes_cli/web_server.py index 0b4808e86d57..7a37e700bb0a 100644 --- a/hermes_cli/web_server.py +++ b/hermes_cli/web_server.py @@ -4190,36 +4190,38 @@ def _write_provider_honcho(provider: ProviderConfigSchema, values: Dict[str, str @app.get("/api/memory/providers/{name}/config") async def get_memory_provider_config(name: str): - provider = get_provider_config_schema(name) + provider = await asyncio.to_thread(get_provider_config_schema, name) if provider is None: # Undeclared providers (e.g. builtin) have no config surface. Return an # empty schema so the generic panel simply renders nothing. return {"name": name, "label": name, "docs_url": "", "fields": []} - return _memory_provider_payload(provider) + return await asyncio.to_thread(_memory_provider_payload, provider) + + +def _update_memory_provider_config(provider: ProviderConfigSchema, values: Dict[str, str]) -> None: + if provider.storage == STORAGE_HONCHO_HOST_BLOCK: + _write_provider_honcho(provider, values) + else: + _write_provider_flat(provider, values) + + config = load_config() + memory_config = config.get("memory") + if not isinstance(memory_config, dict): + memory_config = {} + config["memory"] = memory_config + if memory_config.get("provider") != provider.name: + memory_config["provider"] = provider.name + save_config(config) @app.put("/api/memory/providers/{name}/config") async def update_memory_provider_config(name: str, body: MemoryProviderConfigUpdate): - provider = get_provider_config_schema(name) + provider = await asyncio.to_thread(get_provider_config_schema, name) if provider is None: raise HTTPException(status_code=404, detail=f"Unknown memory provider: {name}") - values = body.values or {} - try: - if provider.storage == STORAGE_HONCHO_HOST_BLOCK: - _write_provider_honcho(provider, values) - else: - _write_provider_flat(provider, values) - - config = load_config() - memory_config = config.get("memory") - if not isinstance(memory_config, dict): - memory_config = {} - config["memory"] = memory_config - memory_config["provider"] = provider.name - save_config(config) - + await asyncio.to_thread(_update_memory_provider_config, provider, body.values or {}) return {"ok": True} except HTTPException: raise