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 -1
View File
@@ -298,6 +298,7 @@ pub async fn run_session(app: Arc<App>, session_id: &str, cancel: CancellationTo
tools: tools.iter().map(|t| t.def()).collect(),
max_tokens: model.max_output.unwrap_or(16_000),
reasoning: true,
session_id: Some(session_id.to_string()),
model: model.clone(),
};
let step = match stream_step(&app, &session, &agent.name, &model_spec, provider, req.clone(), &cancel).await {
@@ -985,6 +986,7 @@ fn maybe_generate_title(app: Arc<App>, session_id: &str, text: &str) {
tools: vec![],
max_tokens: 2000,
reasoning: false,
session_id: Some(session.id.clone()),
model: model.clone(),
};
match complete_text(&app, &spec, provider, req, CancellationToken::new()).await {
@@ -1032,6 +1034,7 @@ pub async fn suggest_title(app: Arc<App>, session_id: &str, model_spec: Option<S
tools: vec![],
max_tokens: 2000,
reasoning: false,
session_id: Some(session.id.clone()),
model: model.clone(),
};
let (text, usage) = complete_text(&app, &spec, provider, req, CancellationToken::new()).await?;
@@ -1159,7 +1162,7 @@ async fn review_turn(app: &Arc<App>, session: &Session, agent: &prompts::Agent,
agent.name,
if changes.is_empty() { "(no files changed in this turn)" } else { changes.as_str() }
);
let req = ChatRequest { system: system.into(), messages: vec![Message::new(Role::User, vec![Part::Text { text: body }])], tools: vec![], max_tokens: 4000, reasoning: false, model: model.clone() };
let req = ChatRequest { system: system.into(), messages: vec![Message::new(Role::User, vec![Part::Text { text: body }])], tools: vec![], max_tokens: 4000, reasoning: false, model: model.clone(), session_id: Some(session.id.clone()) };
let (text, usage) = complete_text(app, &spec, provider, req, cancel.clone()).await?;
record_side_usage(app, session, &spec, &model, &usage, "review");
let text = strip_think(&text);
@@ -1254,6 +1257,7 @@ pub async fn compact(app: Arc<App>, session_id: &str, cancel: CancellationToken)
tools: vec![],
max_tokens: 16_000,
reasoning: false,
session_id: Some(session.id.clone()),
model: model.clone(),
};
let (text, usage) = complete_text(&app, &spec, provider.clone(), req, cancel.clone()).await?;