Skip to main content

qualia_client_core/api/
chat.rs

1//! Chat sessions
2
3#![allow(non_snake_case)]
4
5use super::*;
6
7use std::path::Path;
8
9pub fn create_chat_session(title: Option<String>) -> Result<String, String> {
10    let state = crate::state::APP_STATE.get().unwrap();
11    let storage = state.config.lock().unwrap().storage_path.clone();
12    crate::chat_session::create_session(Path::new(&storage), title, None).map_err(|e| e.to_string())
13}
14
15pub fn list_chat_sessions() -> Result<serde_json::Value, String> {
16    let state = crate::state::APP_STATE.get().unwrap();
17    let storage = state.config.lock().unwrap().storage_path.clone();
18    let sessions =
19        crate::chat_session::list_sessions(Path::new(&storage)).map_err(|e| e.to_string())?;
20    serde_json::to_value(sessions).map_err(|e| e.to_string())
21}
22
23pub fn load_chat_session(id: String) -> Result<serde_json::Value, String> {
24    let state = crate::state::APP_STATE.get().unwrap();
25    let storage = state.config.lock().unwrap().storage_path.clone();
26    let session =
27        crate::chat_session::load_session(Path::new(&storage), &id).map_err(|e| e.to_string())?;
28    serde_json::to_value(session).map_err(|e| e.to_string())
29}
30
31pub fn append_chat_message(
32    session_id: String,
33    role: String,
34    content: String,
35) -> Result<u64, String> {
36    append_chat_message_reply(session_id, role, content, None, None)
37}
38
39pub fn append_chat_message_reply(
40    session_id: String,
41    role: String,
42    content: String,
43    reply_to_fragment: Option<String>,
44    branch_type_id: Option<String>,
45) -> Result<u64, String> {
46    let state = crate::state::APP_STATE.get().unwrap();
47    let storage = state.config.lock().unwrap().storage_path.clone();
48    let role = crate::chat_session::Role::from_str(&role).map_err(|e| e.to_string())?;
49    crate::chat_session::append_message_with_author(
50        Path::new(&storage),
51        &session_id,
52        role,
53        &content,
54        reply_to_fragment,
55        None,
56        None,
57        None,
58        branch_type_id,
59    )
60    .map_err(|e| e.to_string())
61}
62
63pub fn compact_chat_session(session_id: String) -> Result<String, String> {
64    let state = crate::state::APP_STATE.get().unwrap();
65    let storage = state.config.lock().unwrap().storage_path.clone();
66    let path = crate::chat_session::compact_session_to_q42(Path::new(&storage), &session_id)
67        .map_err(|e| e.to_string())?;
68    Ok(path.to_string_lossy().into_owned())
69}
70
71pub fn delete_chat_session(session_id: String) -> Result<(), String> {
72    let state = crate::state::APP_STATE.get().unwrap();
73    let storage = state.config.lock().unwrap().storage_path.clone();
74    crate::chat_session::delete_session(Path::new(&storage), &session_id).map_err(|e| e.to_string())
75}
76
77pub fn rename_chat_session(session_id: String, title: String) -> Result<(), String> {
78    let state = crate::state::APP_STATE.get().unwrap();
79    let storage = state.config.lock().unwrap().storage_path.clone();
80    crate::chat_session::rename_session(Path::new(&storage), &session_id, &title)
81        .map_err(|e| e.to_string())
82}
83
84pub fn get_last_chat_session_id() -> Option<String> {
85    crate::chat_session::get_last_session_id()
86}
87
88pub fn set_last_chat_session_id(session_id: String) -> Result<(), String> {
89    crate::chat_session::set_last_session_id(&session_id).map_err(|e| e.to_string())
90}
91
92pub fn compile_session_environment(session_id: String) -> Result<serde_json::Value, String> {
93    let state = crate::state::APP_STATE.get().unwrap();
94    let storage = state.config.lock().unwrap().storage_path.clone();
95    let catalog = load_workspace_catalog();
96    let env = crate::context_binding::refresh_session_environment(
97        Path::new(&storage),
98        &catalog,
99        &session_id,
100    )
101    .map_err(|e| e.to_string())?;
102    serde_json::to_value(env).map_err(|e| e.to_string())
103}
104
105pub fn update_session_environment(
106    session_id: String,
107    ontology_ids: Vec<String>,
108    prior_session_ids: Vec<String>,
109    graph_mutation: bool,
110    axiom_start_year: u32,
111    axiom_end_year: u32,
112    spatial_context: String,
113) -> Result<serde_json::Value, String> {
114    let state = crate::state::APP_STATE.get().unwrap();
115    let storage = state.config.lock().unwrap().storage_path.clone();
116    let catalog = load_workspace_catalog();
117    let session = crate::chat_session::load_session(Path::new(&storage), &session_id)
118        .map_err(|e| e.to_string())?;
119    let axiom_bounds = crate::context_binding::AxiomBounds {
120        start_year: axiom_start_year.min(u16::MAX as u32) as u16,
121        end_year: axiom_end_year.min(u16::MAX as u32) as u16,
122        spatial_context_hash: 0,
123        spatial_context_label: spatial_context.clone(),
124    }
125    .with_spatial_label(&spatial_context);
126
127    let config = crate::context_binding::ChatEnvironmentConfig {
128        session_id: session_id.clone(),
129        ontology_ids,
130        prior_session_ids,
131        session_kind: session.meta.session_kind,
132        participants: session.meta.participants.clone(),
133        graph_mutation,
134        axiom_bounds,
135    };
136    let env =
137        crate::context_binding::compile_chat_environment(Path::new(&storage), &catalog, &config)
138            .map_err(|e| e.to_string())?;
139    env.save_to_session_dir(Path::new(&storage))
140        .map_err(|e| e.to_string())?;
141    serde_json::to_value(env).map_err(|e| e.to_string())
142}
143
144pub fn get_session_environment(session_id: String) -> Result<serde_json::Value, String> {
145    let state = crate::state::APP_STATE.get().unwrap();
146    let storage = state.config.lock().unwrap().storage_path.clone();
147    let session = crate::chat_session::load_session(Path::new(&storage), &session_id)
148        .map_err(|e| e.to_string())?;
149    serde_json::to_value(session.environment).map_err(|e| e.to_string())
150}
151
152pub fn list_installed_ontology_ids_for_chat() -> Vec<String> {
153    let state = crate::state::APP_STATE.get().unwrap();
154    let storage = state.config.lock().unwrap().storage_path.clone();
155    crate::context_binding::list_installed_ontology_ids(Path::new(&storage))
156}
157
158pub fn run_chat_inference(session_id: String, prompt: String) -> Result<String, String> {
159    let result = crate::chat_inference::run_chat_inference_with_options(&session_id, &prompt, None);
160    if result.committed {
161        Ok(result.text)
162    } else {
163        Err(result
164            .block_reason
165            .unwrap_or_else(|| "Inference blocked".to_string()))
166    }
167}
168
169pub fn run_chat_inference_detailed(
170    session_id: String,
171    prompt: String,
172) -> Result<serde_json::Value, String> {
173    let result = crate::chat_inference::run_chat_inference_with_options(&session_id, &prompt, None);
174    serde_json::to_value(result).map_err(|e| e.to_string())
175}
176
177pub fn cancel_chat_inference() {
178    crate::chat_inference::request_cancel_inference();
179}