use crate::web::http_types::chat::ClientLlmBody;
use crate::user_data::{LlmEndpointOverride, LlmOverridesFile, load_llm_overrides};
fn fill_optional(dst: &mut Option<String>, src: Option<&String>) {
if dst.as_ref().is_some_and(|s| !s.trim().is_empty()) {
return;
}
if let Some(s) = src.filter(|x| !x.trim().is_empty()) {
*dst = Some(s.clone());
}
}
fn merge_endpoint(body: &mut ClientLlmBody, disk: &LlmEndpointOverride) {
fill_optional(&mut body.api_base, disk.api_base.as_ref());
fill_optional(&mut body.model, disk.model.as_ref());
if body.llm_context_tokens.is_none()
&& let Some(ref t) = disk.llm_context_tokens
&& let Ok(n) = t.trim().parse::<u64>()
{
body.llm_context_tokens = Some(n);
}
if body
.llm_thinking_mode
.as_ref()
.is_none_or(|s| s.trim().is_empty())
{
fill_optional(&mut body.llm_thinking_mode, disk.llm_thinking_mode.as_ref());
}
}
#[must_use]
pub fn merge_client_llm_body(raw: Option<ClientLlmBody>) -> Option<ClientLlmBody> {
let disk = load_llm_overrides();
let mut body = raw.unwrap_or_default();
merge_endpoint(&mut body, &disk.client_llm);
if body.api_base.is_none()
&& body.model.is_none()
&& body.api_key.is_none()
&& body.llm_context_tokens.is_none()
&& body.llm_thinking_mode.is_none()
{
return None;
}
Some(body)
}
#[must_use]
pub fn merge_executor_llm_body(
raw: Option<crate::web::http_types::chat::ExecutorLlmBody>,
) -> Option<crate::web::http_types::chat::ExecutorLlmBody> {
let disk: LlmOverridesFile = load_llm_overrides();
let mut body = raw.unwrap_or_default();
fill_optional(&mut body.api_base, disk.executor_llm.api_base.as_ref());
fill_optional(&mut body.model, disk.executor_llm.model.as_ref());
if body.api_base.is_none() && body.model.is_none() && body.api_key.is_none() {
return None;
}
Some(body)
}