Small fixes & fmt

This commit is contained in:
Andras Schmelczer 2026-03-19 21:51:07 +00:00
parent 6b12e21d50
commit f32a552f46
23 changed files with 347 additions and 99 deletions

View file

@ -154,6 +154,20 @@ impl Field {
}
}
fn number(name: &str) -> Self {
Self {
name: name.to_string(),
r#type: "number".to_string(),
required: None,
max_select: None,
collection_id: None,
max_size: None,
mime_types: None,
on_create: None,
on_update: None,
}
}
fn autodate(name: &str, on_create: bool, on_update: bool) -> Self {
Self {
name: name.to_string(),
@ -717,6 +731,39 @@ pub async fn ensure_collections(
ensure_autodate_fields(client, base_url, &token, "short_urls").await?;
}
if !existing.iter().any(|n| n == "ai_query_logs") {
let users_id = find_users_collection_id(client, base_url, &token).await?;
create_collection(
client,
base_url,
&token,
CreateCollection {
name: "ai_query_logs".to_string(),
r#type: "base".to_string(),
fields: vec![
Field::relation("user", &users_id),
Field::text("query", true),
Field::text("listing_type", false),
Field::text("response_filters", false),
Field::text("response_notes", false),
Field::number("tokens_used"),
Field::number("rounds"),
Field::text("model", false),
Field::autodate("created", true, false),
Field::autodate("updated", true, true),
],
list_rule: None,
view_rule: None,
create_rule: None,
update_rule: None,
delete_rule: None,
},
)
.await?;
} else {
ensure_autodate_fields(client, base_url, &token, "ai_query_logs").await?;
}
Ok(())
}
@ -869,6 +916,56 @@ async fn poll_pocketbase_counts(state: &AppState) {
}
}
/// Insert a record into the `ai_query_logs` collection.
/// Best-effort — logs warnings on failure but does not propagate errors.
#[allow(clippy::too_many_arguments)]
pub async fn log_ai_query(
state: &AppState,
user_id: &str,
query: &str,
listing_type: &str,
response_filters: &str,
response_notes: &str,
tokens_used: u64,
rounds: u64,
) {
let token = match get_superuser_token(state).await {
Ok(tk) => tk,
Err(err) => {
warn!("Failed to auth superuser for AI query log: {err}");
return;
}
};
let pb_url = state.pocketbase_url.trim_end_matches('/');
let url = format!("{pb_url}/api/collections/ai_query_logs/records");
let res = state
.http_client
.post(&url)
.header("Authorization", format!("Bearer {token}"))
.json(&serde_json::json!({
"user": user_id,
"query": query,
"listing_type": listing_type,
"response_filters": response_filters,
"response_notes": response_notes,
"tokens_used": tokens_used,
"rounds": rounds,
"model": &state.gemini_model,
}))
.send()
.await;
match res {
Ok(resp) if resp.status().is_success() => {}
Ok(resp) => {
let status = resp.status();
warn!("Failed to log AI query ({status})");
}
Err(err) => warn!("Failed to log AI query: {err}"),
}
}
async fn pb_count(
client: &reqwest::Client,
pb_url: &str,