Stats history with year filter, folding and XLSX/CSV export; snippets, read-only links, commit suggestions, weekly review, offline copies, server speech-to-text, planning model, job reports; fal.ai health fix
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c08c6c7436
commit
388ca96419
31 files changed
+1518
-82
No files matched your search
@@ -231,6 +231,29 @@ pub async fn put_prefs(Extension(user): Extension<User>, State(app): State<AppSt
|
||||
Ok(Json(b))
|
||||
}
|
||||
|
||||
/// Personal prompt snippets (`/name` in the composer): [{id, name, text}].
|
||||
pub async fn get_snippets(Extension(user): Extension<User>, State(app): State<AppState>) -> ApiResult {
|
||||
let v: Value = app.store.user_setting(&user.id, "snippets")?;
|
||||
Ok(Json(if v.is_array() { v } else { json!([]) }))
|
||||
}
|
||||
|
||||
pub async fn put_snippets(Extension(user): Extension<User>, State(app): State<AppState>, Json(b): Json<Value>) -> ApiResult {
|
||||
let ok = b.as_array().is_some_and(|a| {
|
||||
a.len() <= 100
|
||||
&& a.iter().all(|x| {
|
||||
let name = x["name"].as_str().unwrap_or("");
|
||||
!name.is_empty() && name.len() <= 40 && !name.contains(char::is_whitespace) && x["text"].as_str().is_some_and(|t| !t.is_empty() && t.len() <= 8000)
|
||||
})
|
||||
});
|
||||
if !ok {
|
||||
return Err(ApiError(StatusCode::BAD_REQUEST, "invalid snippets (name: one word, up to 40 characters; text: up to 8000)".into()));
|
||||
}
|
||||
let clean: Vec<Value> = b.as_array().unwrap().iter().map(|x| json!({"id": x["id"].as_str().filter(|i| i.len() <= 64).map(str::to_string).unwrap_or_else(crate::types::new_id), "name": x["name"], "text": x["text"]})).collect();
|
||||
let v = Value::Array(clean);
|
||||
app.store.set_user_setting(&user.id, "snippets", &v)?;
|
||||
Ok(Json(v))
|
||||
}
|
||||
|
||||
/// Order and pinning of the groups (folders, projects) in the chat list – per user, so
|
||||
/// every device shows the same order: {"order": [group ids], "pinned": [group ids]}.
|
||||
pub async fn get_sidebar(Extension(user): Extension<User>, State(app): State<AppState>) -> ApiResult {
|
||||
|
||||
Reference in new issue
Block a user