Add terminal client, memory, model fallback, version and install improvements

- codecraft: full-screen terminal client (ratatui) – local tools and files,
  models via the CodeCraft server gateway or own providers (standalone with a
  guided setup), slash commands, @files, permission dialogs, resume, update
- Static Linux CLI builds (x86_64/aarch64, cargo-zigbuild) served by the
  server: /cli/install.sh and /cli/download/<target>
- Project memory (remember tool, .codecraft/memory.md) and personal memory
- Model fallback when a host is unreachable or a budget is used up
- Version/commit in UI and health, daily release check, "What's new" dialog
- PWA: install button, maskable icon, manifest id and screenshots
- Case-insensitive detection of connection errors for retries

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-09 00:13:06 +01:00
1 parent aa1f8cf016
commit 6dffcb501a
52 files changed
+6477 -765

No files matched your search

+39
View File
@@ -97,6 +97,45 @@ impl Tool for CraftPhase {
// ---------------------------------------------------------------------------
/// Project memory: lasting facts about the project in .codecraft/memory.md.
pub struct Remember;
#[async_trait]
impl Tool for Remember {
fn name(&self) -> &str {
"remember"
}
fn description(&self) -> String {
"Save a lasting insight about this project (build/test commands, conventions, pitfalls, decisions) to \
.codecraft/memory.md – it is loaded into every future session in this project. Keep entries short; \
never store secrets or temporary state."
.into()
}
fn schema(&self) -> Value {
json!({"type": "object", "properties": {"note": {"type": "string"}}, "required": ["note"]})
}
fn is_edit(&self) -> bool {
true
}
fn title(&self, input: &Value) -> String {
input["note"].as_str().unwrap_or("").chars().take(80).collect()
}
async fn run(&self, input: Value, ctx: &ToolCtx) -> Result<ToolOutput> {
let note = arg_str(&input, "note")?.trim().replace('\n', " ");
let path = ctx.resolve(".codecraft/memory.md")?;
std::fs::create_dir_all(path.parent().unwrap())?;
let mut text = std::fs::read_to_string(&path).unwrap_or_else(|_| "# Project memory\n\nLearned facts about this project (maintained by CodeCraft; edit freely).\n\n".into());
if !text.ends_with('\n') {
text.push('\n');
}
text.push_str(&format!("- {note}\n"));
std::fs::write(&path, &text)?;
Ok(ToolOutput::text(format!("Saved to .codecraft/memory.md: {note}")).with_meta(json!({"memory": note})))
}
}
// ---------------------------------------------------------------------------
/// Switch the session's working directory (only on the user's request).
pub struct ChangeDirectory;
+1
View File
@@ -164,6 +164,7 @@ pub fn builtin_tools() -> Vec<Arc<dyn Tool>> {
Arc::new(web::WebSearch),
Arc::new(agent::CraftPhase),
Arc::new(agent::ChangeDirectory),
Arc::new(agent::Remember),
Arc::new(cad::OpenScad),
Arc::new(crate::jobs::Schedule),
Arc::new(crate::lsp::Diagnostics),