dell_ai/apps.py (85 lines of code) (raw):

"""App-related functionality for the Dell AI SDK.""" from typing import Dict, List, Optional, Any, TYPE_CHECKING from pydantic import BaseModel, Field from dell_ai import constants from dell_ai.exceptions import ResourceNotFoundError, ValidationError, APIError if TYPE_CHECKING: from dell_ai.client import DellAIClient class EnvParam(BaseModel): """Environment parameter for app configuration.""" name: str description: str type: str = Field( description="Parameter type", examples=["string", "number", "boolean", "json"] ) example: Optional[str] = None required: Optional[bool] = None default: Optional[Any] = None helmPath: str value: Optional[Any] = None class Secret(BaseModel): """Secret parameter for app configuration.""" name: str description: str type: str example: Optional[str] = None required: Optional[bool] = None helmPath: str class AppComponent(BaseModel): """Component of an application.""" id: str name: str description: str required: bool config: List[EnvParam] secrets: List[Secret] class App(BaseModel): """Represents an application in the catalog.""" id: str name: str license: str image: str screenshot: str docs: str description: str features: str instructions: str tags: List[str] recommendedModels: List[str] components: List[AppComponent] def list_apps(client: "DellAIClient") -> List[str]: """ Get a list of all available application names. Args: client: The Dell AI client Returns: A list of application names Raises: AuthenticationError: If authentication fails APIError: If the API returns an error """ response = client._make_request("GET", constants.APPS_ENDPOINT) return response.get("apps", []) def get_app(client: "DellAIClient", app_id: str) -> App: """ Get detailed information about a specific application. Args: client: The Dell AI client app_id: The application ID Returns: Detailed application information as an App object Raises: ResourceNotFoundError: If the application is not found AuthenticationError: If authentication fails APIError: If the API returns an error """ try: endpoint = f"{constants.APPS_ENDPOINT}/{app_id}" response = client._make_request("GET", endpoint) return App.model_validate(response) except ResourceNotFoundError: # Reraise with more specific information raise ResourceNotFoundError("app", app_id) def get_app_snippet( client: "DellAIClient", app_id: str, config: List[Dict[str, Any]] ) -> str: """ Get a deployment snippet for the specified app with the provided configuration. Args: client: The Dell AI client app_id: The application ID config: List of configuration parameters with helmPath, type, and value Returns: A string containing the deployment snippet (Helm command) Raises: ValidationError: If any of the input parameters are invalid ResourceNotFoundError: If the application is not found APIError: If the API returns an error """ try: # Use the correct endpoint construction from the implementation plan endpoint = f"{constants.SNIPPETS_ENDPOINT}/apps/{app_id}" data = {"config": config} # Make the API request response = client._make_request("POST", endpoint, data=data) # Extract the snippet from the response if ( isinstance(response, dict) and "snippet" in response and "raw" in response.get("snippet", {}) ): return response["snippet"]["raw"] else: # Handle unexpected response format raise ValidationError("Unexpected response format from API") except ResourceNotFoundError: # Reraise with more specific information raise ResourceNotFoundError("app", app_id) except ValidationError as e: # Pass through validation errors raise e except Exception as e: # Handle other errors with appropriate context if hasattr(e, "response") and getattr(e, "response", None): status_code = getattr(e.response, "status_code", None) if status_code == 400: raise ValidationError("Invalid request: " + str(e)) elif status_code == 404: raise ResourceNotFoundError("app", app_id) elif status_code == 500: raise APIError( "Server error. Please verify your configuration and app ID." ) # If not a recognized error, re-raise raise