fix: add LLM_SSL_VERIFY support to translate plugin HTTP clients

preview_llm_client.py and _llm_http.py both use requests.post()
without verify=, causing SSLError when corporate CA not in trust store.
Added _get_verify() helper that reads LLM_SSL_VERIFY env var.
This commit is contained in:
2026-05-28 11:53:17 +03:00
parent 477e30a9f2
commit 60333bdb95
2 changed files with 18 additions and 4 deletions

View File

@@ -11,12 +11,19 @@
# @RATIONALE Extracted from LLMTranslationService (793 lines) to keep module under INV_7 limit.
# @REJECTED Single HTTP client class — kept as module-level functions for stateless reusability.
import os
import time
from typing import Any
from ...core.logger import logger
def _get_verify() -> bool:
"""Resolve SSL verify flag from LLM_SSL_VERIFY env var."""
raw = os.getenv("LLM_SSL_VERIFY", "true").strip().lower()
return raw not in ("false", "0", "no", "off")
# #region call_openai_compatible [C:3] [TYPE Function] [SEMANTICS translate, llm, http, openai]
# @BRIEF Call OpenAI-compatible API with rate-limit handling and structured output fallback.
# @PRE Valid API endpoint, key, model, and prompt.
@@ -141,7 +148,7 @@ def _do_http_request(url: str, headers: dict, payload: dict) -> tuple[Any, str]:
_max_retry_429 = 3
_retry_count_429 = 0
while _retry_count_429 < _max_retry_429:
response = http_requests.post(url, headers=headers, json=payload, timeout=180)
response = http_requests.post(url, headers=headers, json=payload, timeout=180, verify=_get_verify())
response_text = response.text
if response.status_code == 429:
_retry_count_429 += 1
@@ -179,7 +186,7 @@ def _handle_response_format_fallback(
logger.explore("Structured outputs not supported, retrying without response_format",
extra={"src": "executor"})
payload.pop("response_format", None)
new_response = http_requests.post(url, headers=headers, json=payload, timeout=180)
new_response = http_requests.post(url, headers=headers, json=payload, timeout=180, verify=_get_verify())
response.status_code = new_response.status_code
response._content = new_response.content
response.encoding = new_response.encoding

View File

@@ -3,12 +3,19 @@
# @SIDE_EFFECT Makes HTTP POST calls to external LLM API.
# @RELATION DEPENDS_ON -> [EXT:requests]
import os
import time as _time
from typing import Any
from ...core.logger import logger
def _get_verify() -> bool:
"""Resolve SSL verify flag from LLM_SSL_VERIFY env var."""
raw = os.getenv("LLM_SSL_VERIFY", "true").strip().lower()
return raw not in ("false", "0", "no", "off")
class LLMClient:
"""Call OpenAI-compatible LLM APIs with retry and structured output handling."""
@@ -63,7 +70,7 @@ class LLMClient:
_max_retry_429 = 3
_retry_count_429 = 0
while _retry_count_429 < _max_retry_429:
response = http_requests.post(url, headers=headers, json=payload, timeout=600)
response = http_requests.post(url, headers=headers, json=payload, timeout=600, verify=_get_verify())
if response.status_code == 429:
_retry_count_429 += 1
retry_after = response.headers.get("Retry-After")
@@ -80,7 +87,7 @@ class LLMClient:
and any(p in (response.text or "").lower() for p in _response_format_error_patterns)):
logger.explore("Structured outputs not supported, retrying without response_format")
payload.pop("response_format", None)
response = http_requests.post(url, headers=headers, json=payload, timeout=600)
response = http_requests.post(url, headers=headers, json=payload, timeout=600, verify=_get_verify())
if not response.ok:
logger.explore(f"LLM API error status={response.status_code} model={payload.get('model')} body={response.text[:2000]}")