@@ -556,12 +556,13 @@ async def configure_provider(self, provider_id: str, api_key: str = "") -> dict[
556556 return {"status" : "ok" , "provider" : provider_id , "models" : models }
557557
558558 elif info ["auth_type" ] == "bridge" :
559+ # Auto-install bridge dependencies if missing
560+ await self ._ensure_bridge_deps ()
559561 auth = await self ._check_claude_auth ()
560562 if not auth ["installed" ]:
561563 raise ValueError (
562- "Claude Code SDK not found. Install Claude Code "
563- "(https://claude.ai/download) and run 'bun install' "
564- "in the bridge/ directory."
564+ "Bridge setup failed. Ensure 'bun' is installed "
565+ "(npm i -g bun) and try again."
565566 )
566567 if not auth ["logged_in" ]:
567568 log .info ("Claude Code not authenticated — launching browser login" )
@@ -853,6 +854,63 @@ async def _validate_api_key(self, provider_id: str, api_key: str) -> None:
853854 except httpx .TimeoutException :
854855 raise ValueError (f"Timeout connecting to { provider_id } API" )
855856
857+ async def _ensure_bridge_deps (self ) -> None :
858+ """Auto-install bridge dependencies (bun install) if missing."""
859+ bridge_dir = Path (__file__ ).resolve ().parent .parent .parent / "bridge"
860+ pkg_json = bridge_dir / "package.json"
861+ node_modules = bridge_dir / "node_modules"
862+ cli_js = node_modules / "@anthropic-ai" / "claude-agent-sdk" / "cli.js"
863+
864+ if cli_js .exists ():
865+ return # Already installed
866+
867+ if not pkg_json .exists ():
868+ log .warning ("Bridge package.json not found at %s" , bridge_dir )
869+ return
870+
871+ # Check bun is available
872+ import shutil
873+ bun = shutil .which ("bun" )
874+ if not bun :
875+ # Try installing bun via npm
876+ npm = shutil .which ("npm" )
877+ if npm :
878+ log .info ("Installing bun via npm..." )
879+ try :
880+ proc = await asyncio .create_subprocess_exec (
881+ npm , "install" , "-g" , "bun" ,
882+ stdout = asyncio .subprocess .PIPE ,
883+ stderr = asyncio .subprocess .PIPE ,
884+ )
885+ await asyncio .wait_for (proc .communicate (), timeout = 120 )
886+ bun = shutil .which ("bun" )
887+ except Exception as e :
888+ log .warning ("Failed to install bun: %s" , e )
889+
890+ if not bun :
891+ log .warning ("bun not found — cannot auto-install bridge dependencies" )
892+ return
893+
894+ # Run bun install in the bridge directory
895+ log .info ("Installing bridge dependencies in %s ..." , bridge_dir )
896+ try :
897+ proc = await asyncio .create_subprocess_exec (
898+ bun , "install" ,
899+ cwd = str (bridge_dir ),
900+ stdout = asyncio .subprocess .PIPE ,
901+ stderr = asyncio .subprocess .PIPE ,
902+ )
903+ stdout , stderr = await asyncio .wait_for (proc .communicate (), timeout = 120 )
904+ if proc .returncode == 0 :
905+ log .info ("Bridge dependencies installed successfully" )
906+ else :
907+ log .warning ("bun install failed (exit %s): %s" ,
908+ proc .returncode , stderr .decode (errors = "replace" )[:500 ])
909+ except asyncio .TimeoutError :
910+ log .warning ("bun install timed out" )
911+ except Exception as e :
912+ log .warning ("Failed to install bridge dependencies: %s" , e )
913+
856914 def _resolve_sdk_cli (self ) -> Path | None :
857915 bridge_dir = Path (__file__ ).resolve ().parent .parent .parent / "bridge"
858916 cli_js = bridge_dir / "node_modules" / "@anthropic-ai" / "claude-agent-sdk" / "cli.js"
0 commit comments