use std::path::PathBuf;
use std::sync::atomic::{AtomicU64, Ordering};
use crate::provider::gemini::transport::types::GeminiRequest;
static REQUEST_LOG_SEQUENCE: AtomicU64 = AtomicU64::new(1);
pub(crate) struct GeminiRequestLogContext<'a> {
pub(crate) kind: &'a str,
}
pub(crate) fn write_request_log(context: &GeminiRequestLogContext<'_>, request: &GeminiRequest) {
let Some(path) = build_log_path(context) else {
return;
};
let rendered = match serde_json::to_string_pretty(request) {
Ok(value) => value,
Err(error) => {
if std::env::var_os("SQUIGIT_TUI_ACTIVE").is_none() {
eprintln!("[SquigitBrain] Failed to render Gemini request log: {error}");
}
return;
}
};
if let Err(error) = std::fs::write(&path, format!("{rendered}\n")) {
if std::env::var_os("SQUIGIT_TUI_ACTIVE").is_none() {
eprintln!(
"[SquigitBrain] Failed to write Gemini request log {}: {}",
path.display(),
error
);
}
}
}
fn build_log_path(context: &GeminiRequestLogContext<'_>) -> Option<PathBuf> {
let logs_dir = std::env::var_os("SQUIGIT_LOG_DIR")
.filter(|path| !path.is_empty())
.map(PathBuf::from)?;
if let Err(error) = std::fs::create_dir_all(&logs_dir) {
if std::env::var_os("SQUIGIT_TUI_ACTIVE").is_none() {
eprintln!(
"[SquigitBrain] Failed to create logs directory {}: {}",
logs_dir.display(),
error
);
}
return None;
}
let timestamp = chrono::Local::now().format("%Y%m%d-%H%M%S-%3f");
let sequence = REQUEST_LOG_SEQUENCE.fetch_add(1, Ordering::Relaxed);
let name = format!(
"Squigit-LLM-{}-{}-{:04}.log",
timestamp,
sanitize_filename_component(context.kind),
sequence
);
Some(logs_dir.join(name))
}
fn sanitize_filename_component(value: &str) -> String {
let sanitized: String = value
.chars()
.map(|ch| {
if ch.is_ascii_alphanumeric() || matches!(ch, '-' | '_' | '.') {
ch
} else {
'_'
}
})
.collect();
let trimmed = sanitized.trim_matches('_');
let final_value = if trimmed.is_empty() {
"request"
} else {
trimmed
};
final_value.chars().take(48).collect()
}