diff --git a/client/src/BotConfig.tsx b/client/src/BotConfig.tsx index 2d3c5e8..d6da9bf 100644 --- a/client/src/BotConfig.tsx +++ b/client/src/BotConfig.tsx @@ -34,10 +34,14 @@ const BotConfigComponent: React.FC = ({ botInstanceId, botName, setLoading(true); setError(null); + // Use bot instance ID if available, otherwise fall back to bot name + const identifier = botInstanceId || botName; + const endpointPath = botInstanceId + ? `/api/bots/config/schema/instance/${identifier}` + : `/api/bots/config/schema/${identifier}`; + // Use refresh endpoint if force refresh is requested - const url = forceRefresh - ? `${base}/api/bots/config/schema/${botName}/refresh` - : `${base}/api/bots/config/schema/${botName}`; + const url = forceRefresh ? `${base}${endpointPath}/refresh` : `${base}${endpointPath}`; const method = forceRefresh ? "POST" : "GET"; @@ -58,7 +62,7 @@ const BotConfigComponent: React.FC = ({ botInstanceId, botName, }); setConfigValues(defaultValues); } else if (response.status === 404) { - setError(`Bot "${botName}" does not support configuration`); + setError(`Bot does not support configuration`); } else { setError("Failed to fetch configuration schema"); } @@ -68,12 +72,12 @@ const BotConfigComponent: React.FC = ({ botInstanceId, botName, setLoading(false); } }, - [botName] + [botName, botInstanceId] ); useEffect(() => { fetchSchema(); - }, [botName, fetchSchema]); + }, [botName, botInstanceId, fetchSchema]); // Handle schema refresh const handleRefreshSchema = async () => { diff --git a/server/api/bot_config.py b/server/api/bot_config.py index 437dd0e..6c10c65 100644 --- a/server/api/bot_config.py +++ b/server/api/bot_config.py @@ -78,11 +78,14 @@ def create_bot_config_router( bot_names = [bot.name for bot in provider_bots.bots] if bot_name in bot_names: - schema = await config_manager.discover_bot_config_schema( - bot_name, provider.base_url - ) - if schema: - break + # Get the full provider object to access base_url + full_provider = bot_manager.get_provider(provider.provider_id) + if full_provider: + schema = await config_manager.discover_bot_config_schema( + bot_name, full_provider.base_url + ) + if schema: + break except Exception as e: logger.warning( f"Failed to check provider {provider.provider_id} for bot {bot_name}: {e}" @@ -101,13 +104,16 @@ def create_bot_config_router( if bot_name in bot_names: # This will only refresh if the cached schema is older than 1 hour - fresh_schema = ( - await config_manager.discover_bot_config_schema( - bot_name, provider.base_url, force_refresh=False + # Get the full provider object to access base_url + full_provider = bot_manager.get_provider(provider.provider_id) + if full_provider: + fresh_schema = ( + await config_manager.discover_bot_config_schema( + bot_name, full_provider.base_url, force_refresh=False + ) ) - ) - if fresh_schema: - schema = fresh_schema + if fresh_schema: + schema = fresh_schema break except Exception as e: logger.debug(f"Failed to refresh schema for {bot_name}: {e}") @@ -128,6 +134,93 @@ def create_bot_config_router( logger.error(f"Failed to get bot config schema for {bot_name}: {e}") raise HTTPException(status_code=500, detail="Internal server error") + @router.get("/schema/instance/{bot_instance_id}") + async def get_bot_config_schema_by_instance(bot_instance_id: str) -> BotConfigSchema: # type: ignore + """Get configuration schema for a specific bot instance""" + try: + # Get bot instance to find the bot_name + bot_instance = await bot_manager.get_bot_instance(bot_instance_id) + bot_name = bot_instance.bot_name + + # Check if we have cached schema + schema = config_manager.get_bot_config_schema(bot_name) + + if not schema: + # Try to discover schema from bot provider + provider = bot_manager.get_provider(bot_instance.provider_id) + if provider: + try: + schema = await config_manager.discover_bot_config_schema( + bot_name, provider.base_url + ) + except Exception as e: + logger.warning( + f"Failed to discover schema for bot {bot_name} from provider {bot_instance.provider_id}: {e}" + ) + else: + logger.warning(f"Provider {bot_instance.provider_id} not found") + + if not schema: + raise HTTPException( + status_code=404, + detail=f"No configuration schema found for bot instance '{bot_instance_id}' (bot: '{bot_name}')", + ) + + return schema + + except ValueError: + # Bot instance not found + raise HTTPException( + status_code=404, detail=f"Bot instance '{bot_instance_id}' not found" + ) + except HTTPException: + raise + except Exception as e: + logger.error(f"Failed to get bot config schema for instance {bot_instance_id}: {e}") + raise HTTPException(status_code=500, detail="Internal server error") + + @router.post("/schema/instance/{bot_instance_id}/refresh") + async def refresh_bot_schema_by_instance(bot_instance_id: str) -> Dict[str, Any]: + """Refresh configuration schema for a specific bot instance""" + try: + # Get bot instance to find the bot_name and provider + bot_instance = await bot_manager.get_bot_instance(bot_instance_id) + bot_name = bot_instance.bot_name + provider_id = bot_instance.provider_id + + # Get the provider to access base_url + provider = bot_manager.get_provider(provider_id) + if not provider: + raise HTTPException( + status_code=404, detail=f"Provider '{provider_id}' not found" + ) + + schema = await config_manager.refresh_bot_schema( + bot_name, provider.base_url + ) + if schema: + return { + "success": True, + "message": f"Schema refreshed for bot instance {bot_instance_id} (bot: {bot_name})", + "schema": schema.model_dump(), + } + else: + raise HTTPException( + status_code=404, + detail=f"Bot instance {bot_instance_id} (bot: {bot_name}) does not support configuration", + ) + + except ValueError: + # Bot instance not found + raise HTTPException( + status_code=404, detail=f"Bot instance '{bot_instance_id}' not found" + ) + except HTTPException: + raise + except Exception as e: + logger.error(f"Failed to refresh schema for bot instance {bot_instance_id}: {e}") + raise HTTPException(status_code=500, detail="Internal server error") + @router.get("/lobby/{lobby_id}") async def get_lobby_bot_configs(lobby_id: str) -> BotConfigListResponse: """Get all bot configurations for a lobby""" @@ -305,13 +398,16 @@ def create_bot_config_router( for bot in provider_bots.bots: try: - schema = ( - await config_manager.discover_bot_config_schema( - bot.name, provider.base_url, force_refresh=True + # Get the full provider object to access base_url + full_provider = bot_manager.get_provider(provider.provider_id) + if full_provider: + schema = ( + await config_manager.discover_bot_config_schema( + bot.name, full_provider.base_url, force_refresh=True + ) ) - ) - if schema: - refreshed += 1 + if schema: + refreshed += 1 except Exception as e: logger.warning(f"Failed to refresh schema for {bot.name}: {e}")