Status LEDs, image model selection, backup restore, provider test, monthly versions

- 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>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-09 09:31:24 +01:00
1 parent 49d404eec7
commit 1f69d63b09
35 files changed
+1156 -88

No files matched your search

+5 -6
View File
@@ -29,7 +29,7 @@ use tokio::sync::mpsc;
use tokio_util::sync::CancellationToken;
#[derive(Parser)]
#[command(name = "codecraft", version, about = "CodeCraft in the terminal – a local coding agent")]
#[command(name = "codecraft", version = codecraft_core::version::VERSION, about = "CodeCraft in the terminal – a local coding agent")]
struct Cli {
/// Start with this prompt
prompt: Option<String>,
@@ -164,8 +164,7 @@ fn prompt_line(label: &str, secret: bool) -> Result<String> {
}
fn version_newer(server: &str, ours: &str) -> bool {
let parse = |v: &str| v.split('.').map(|p| p.parse::<u64>().unwrap_or(0)).collect::<Vec<_>>();
parse(server) > parse(ours)
codecraft_core::version::newer(server, ours)
}
fn target() -> String {
@@ -178,8 +177,8 @@ async fn self_update() -> Result<()> {
let http = server::http();
let info: Value = http.get(format!("{}/api/info", login.url)).send().await?.json().await?;
let latest = info["version"].as_str().unwrap_or("0");
if !version_newer(latest, env!("CARGO_PKG_VERSION")) {
println!("codecraft {} is up to date.", env!("CARGO_PKG_VERSION"));
if !version_newer(latest, codecraft_core::version::VERSION) {
println!("codecraft {} is up to date.", codecraft_core::version::VERSION);
return Ok(());
}
let url = format!("{}/cli/download/{}", login.url, target());
@@ -365,7 +364,7 @@ async fn main() -> Result<()> {
// Notice when the server has a newer CLI.
let mut status = String::new();
if let Some(v) = env.server_cfg.as_ref().and_then(|s| s["version"].as_str()) {
if version_newer(v, env!("CARGO_PKG_VERSION")) {
if version_newer(v, codecraft_core::version::VERSION) {
status = format!("update available: {v} – run `codecraft update`");
}
}
+1 -1
View File
@@ -105,7 +105,7 @@ pub async fn stream(
mc.effort = Some(e);
}
let max_tokens = mc.max_output.unwrap_or(16_000);
let req = ChatRequest { model: mc, system, messages, tools, max_tokens, reasoning: true };
let req = ChatRequest { model: mc, system, messages, tools, max_tokens, reasoning: true, session_id: Some(session.to_string()) };
provider.stream(req, tx, cancel).await
}
+1 -1
View File
@@ -19,7 +19,7 @@ pub struct Server {
pub fn http() -> reqwest::Client {
reqwest::Client::builder()
.user_agent(concat!("codecraft-cli/", env!("CARGO_PKG_VERSION")))
.user_agent(format!("codecraft-cli/{}", codecraft_core::version::VERSION))
.connect_timeout(std::time::Duration::from_secs(15))
.build()
.expect("http client")