Make ApiClient a process-wide singleton via OnceLock so the
connection pool is reused across agent calls. Fix the sync wrapper
to properly pass the caller's log closure through thread::scope
instead of dropping it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Run the async API call on a dedicated thread with its own tokio
runtime so it works whether called from a sync context or from
within an existing tokio runtime (daemon).
Also drops the log closure capture issue — uses a simple eprintln
fallback since the closure can't cross thread boundaries.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When api_base_url is configured, agents call the LLM directly via
OpenAI-compatible API (vllm, llama.cpp, etc.) instead of shelling
out to claude CLI. Implements the full tool loop: send prompt, if
tool_calls execute them and send results back, repeat until text.
This enables running agents against local/remote models like
Qwen-27B on a RunPod B200, with no dependency on claude CLI.
Config fields: api_base_url, api_key, api_model.
Falls back to claude CLI when api_base_url is not set.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>