diff --git a/config/settings.py b/config/settings.py index 2a14913..5db7d69 100644 --- a/config/settings.py +++ b/config/settings.py @@ -40,6 +40,7 @@ def load_config(): == "true", "require_confirmation": os.getenv("CLOVER_REQUIRE_CONFIRMATION", "true").lower() == "true", + "ssl_verify": os.getenv("CLOVER_SSL_VERIFY", "true").lower() == "true", "project_root": os.getenv("CLOVER_PROJECT_ROOT", "."), "summary_file": os.getenv("CLOVER_SUMMARY_FILE", "clover.md"), "structure_file": os.getenv("CLOVER_STRUCTURE_FILE", "structure.md"), diff --git a/models/api_client.py b/models/api_client.py index 6e531e2..b3f7d31 100644 --- a/models/api_client.py +++ b/models/api_client.py @@ -20,8 +20,36 @@ class APIClient: def __init__(self): """Initialize the API client with configuration""" self.config = load_config() - self.base_url = self.config.get("base_url", "http://192.168.8.223:11434") + self.base_url = self.config.get( + "base_url", "error-set-CLOVER_BASE_URL-in-.env-file" + ) self.api_key = self.config.get("api_key") + self.ssl_verify = self.config.get("ssl_verify", True) + + # Use requests.Session for connection pooling and consistent SSL settings + self.session = requests.Session() + self.session.headers.update( + { + "Content-Type": "application/json", + "User-Agent": "clover-cli/1.0", + "Accept": "application/json", + } + ) + if self.api_key: + self.session.headers["Authorization"] = f"Bearer {self.api_key}" + + # Warn if using HTTP (non-TLS) connection + if self.base_url.startswith("http://") and not self.base_url.startswith( + "http://localhost" + ): + import warnings + + warnings.warn( + f"Using non-TLS connection to {self.base_url}. " + "Consider using HTTPS for remote endpoints. " + "Set CLOVER_SSL_VERIFY=false to disable SSL verification for self-signed certs.", + UserWarning, + ) def _make_request( self, endpoint: str, method: str = "GET", data: Optional[Dict] = None @@ -29,6 +57,8 @@ class APIClient: """ Make a request to the LLM API server + Uses requests.Session with explicit SSL verification control. + Args: endpoint (str): API endpoint method (str): HTTP method (GET, POST) @@ -43,27 +73,15 @@ class APIClient: endpoint = endpoint if endpoint.startswith("/") else f"/{endpoint}" url = f"{base}{endpoint}" - headers = { - "Content-Type": "application/json", - "User-Agent": "clover-cli/1.0", - "Accept": "application/json", + kwargs = { + "timeout": self.config.get("timeout", 300), + "verify": self.ssl_verify, } - # Add API key if available - if self.api_key: - headers["Authorization"] = f"Bearer {self.api_key}" - if method == "GET": - response = requests.get( - url, headers=headers, timeout=self.config.get("timeout", 300) - ) + response = self.session.get(url, **kwargs) elif method == "POST": - response = requests.post( - url, - headers=headers, - json=data, - timeout=self.config.get("timeout", 300), - ) + response = self.session.post(url, json=data, **kwargs) else: raise ValueError(f"Unsupported HTTP method: {method}")