use actix_web::{web, HttpResponse, Responder};
use super::prompt::{build_enhanced_system_prompt_with_profile, upsert_system_prompt_message};
use super::{ChatRequest, ChatResponse};
use crate::server::app_state::AppState;
mod images;
mod request;
mod session;
#[cfg(test)]
mod tests;
pub async fn handler(state: web::Data<AppState>, req: web::Json<ChatRequest>) -> impl Responder {
let session_id = request::resolve_session_id(req.session_id.as_deref());
let model = match request::validate_and_normalize_model(req.model.as_str()) {
Ok(model) => model,
Err(response) => return response,
};
let mut session = match session::load_or_create_session(&state, &session_id, &model).await {
Ok(session) => session,
Err(response) => return response,
};
let global_default_prompt =
crate::server::prompt_defaults::read_global_default_system_prompt_template();
let base_prompt = session::resolve_base_prompt(
&mut session,
request::optional_non_empty(req.system_prompt.as_deref()),
global_default_prompt.as_str(),
);
let enhance_prompt = session::resolve_enhance_prompt(
&mut session,
request::optional_non_empty(req.enhance_prompt.as_deref()),
);
session::resolve_copilot_conclusion_with_options_enhancement_enabled(
&mut session,
req.copilot_conclusion_with_options_enhancement_enabled,
);
let workspace_path = session::resolve_workspace_path(
&mut session,
request::optional_non_empty(req.workspace_path.as_deref()),
);
session::resolve_selected_skill_ids(
&mut session,
req.selected_skill_ids.as_deref(),
req.message.as_str(),
);
session::clear_skill_runtime_state(&mut session);
let (system_prompt, prompt_profile) = build_enhanced_system_prompt_with_profile(
base_prompt.as_str(),
enhance_prompt.as_deref(),
workspace_path.as_deref(),
);
session.metadata.insert(
"prompt_composer_version".to_string(),
prompt_profile.version.to_string(),
);
session.metadata.insert(
"prompt_fingerprint".to_string(),
prompt_profile.fingerprint.clone(),
);
session.metadata.insert(
"prompt_component_flags".to_string(),
prompt_profile.component_flags_value(),
);
session.metadata.insert(
"prompt_component_lengths".to_string(),
prompt_profile.component_lengths_value(),
);
upsert_system_prompt_message(&mut session, system_prompt);
if let Err(response) =
images::append_user_message(&state, &mut session, &req.message, req.images.as_deref()).await
{
return response;
}
session.model = model;
if let Err(response) = session::cache_and_save_session(&state, &session_id, session).await {
return response;
}
HttpResponse::Created().json(ChatResponse {
session_id: session_id.clone(),
stream_url: format!("/api/v1/events/{}", session_id),
status: "streaming".to_string(),
})
}