- Sidebar: three status LEDs (server, models, MCP) with an overview popover (/api/status) - Images: preview stage, purpose-based model choice and reference images (Nano Banana Pro edit refines the chosen preview) - Settings: restore a stored or uploaded backup (staged, applied on restart) - Provider form: test connection; saving or reloading re-checks the status at once - opencode Zen/Go: send x-opencode-session with a stable id per conversation - Releases are named vYYYYMM-NNNNN; scripts/release.sh numbers, tags, builds and publishes - Fix: backups made in the same second no longer overwrite each other Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
47 lines
1.4 KiB
Rust
47 lines
1.4 KiB
Rust
//! Version information and a daily check for new releases.
|
|
|
|
use crate::app::App;
|
|
use serde_json::{Value, json};
|
|
use std::sync::{Arc, Mutex};
|
|
use std::time::Duration;
|
|
|
|
pub use codecraft_core::version::VERSION;
|
|
|
|
/// Git commit the image was built from (Docker build arg GIT_COMMIT).
|
|
pub fn commit() -> &'static str {
|
|
option_env!("CODECRAFT_COMMIT").unwrap_or("")
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct UpdateState {
|
|
pub latest: Mutex<Option<Value>>,
|
|
}
|
|
|
|
use codecraft_core::version::newer;
|
|
|
|
async fn check(app: &App) -> Option<Value> {
|
|
let url = app.config().server.update_url.clone();
|
|
if url.is_empty() {
|
|
return None;
|
|
}
|
|
let v: Value = crate::provider::http_client().get(&url).timeout(Duration::from_secs(20)).send().await.ok()?.json().await.ok()?;
|
|
let tag = v["tag_name"].as_str()?.to_string();
|
|
if !newer(&tag, VERSION) {
|
|
return None;
|
|
}
|
|
Some(json!({"version": tag.trim_start_matches('v'), "url": v["html_url"], "notes": v["body"].as_str().unwrap_or("").chars().take(4000).collect::<String>(), "published_at": v["published_at"]}))
|
|
}
|
|
|
|
pub fn spawn_checker(app: Arc<App>) {
|
|
tokio::spawn(async move {
|
|
tokio::time::sleep(Duration::from_secs(60)).await;
|
|
loop {
|
|
let found = check(&app).await;
|
|
*app.update.latest.lock().unwrap() = found;
|
|
tokio::time::sleep(Duration::from_secs(24 * 3600)).await;
|
|
}
|
|
});
|
|
}
|
|
|
|
|