OpenSSL 3.x ignores intermediate CA certs in -CAfile (verify code 20)
but correctly builds chains with -CApath (verify code 0).
All three clients now use capath:
- service.py: ssl.create_default_context(capath=...)
- _llm_http.py: verify='/etc/ssl/certs/'
- preview_llm_client.py: verify='/etc/ssl/certs/'
check_llm_certs.py rewritten for clarity.
Tests all 4 SSL methods with actual project libraries:
- httpx (verify=True/False/SSLContext cafile/cafile+capath)
- requests (verify=True/False/cafile/capath)
- openssl s_client (default/CAfile/CApath/chain bundle)
- certutil (NSS/Chromium)
- certifi vs system CA comparison
Outputs JSON summary with AI diagnosis hint.
Runs from inside Docker container to verify all 4 SSL layers:
1. System CA store (openssl s_client)
2. NSS database (certutil) for Chromium
3. Python httpx (SSLContext with cafile)
4. Python requests (verify with system CA path)
Reads LLM_SSL_VERIFY and CA paths from .env.enterprise-clean
- Enable response_format (json_object) for all providers including Kilo/OpenRouter
- Skip reasoning_effort for Kilo/OpenRouter (returns 400 — mandatory reasoning)
- Add structured_outputs fallback: retry once without response_format if upstream
provider (e.g. StepFun) rejects it with 'structured_outputs is not supported'
- Handle model refusal field (refusal) instead of treating as empty content
- Fix None-handling guards for message/finish_reason/content fields
- Apply same fixes to both preview.py and executor.py _call_openai_compatible
- Connect orphaned TermCorrectionPopup, BulkReplaceModal, BulkCorrectionSidebar
Preview + executor now log the raw LLM response (first 1000 chars)
when JSON parsing fails, enabling debugging of malformed LLM output.
Previously ValueErrors from JSON parse failures were silently returned
as 400 without any diagnostic data in logs.