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:
1 parent
aa1f8cf016
commit
6dffcb501a
52 files changed
+6477
-765
No files matched your search
@@ -0,0 +1,36 @@
|
||||
//! Local usage log (~/.local/share/codecraft/usage.jsonl) for /costs.
|
||||
|
||||
use crate::session::LocalSession;
|
||||
use codecraft_core::types::{Usage, now_ms};
|
||||
use serde_json::{Value, json};
|
||||
use std::io::Write;
|
||||
|
||||
fn path() -> std::path::PathBuf {
|
||||
crate::conf::data_dir().join("usage.jsonl")
|
||||
}
|
||||
|
||||
pub fn record(session: &LocalSession, model: &str, u: &Usage, cost: f64) {
|
||||
let line = json!({"ts": now_ms(), "session": session.id, "model": model, "in": u.input_tokens, "out": u.output_tokens, "cache_read": u.cache_read_tokens, "cache_write": u.cache_write_tokens, "cost": cost});
|
||||
let _ = std::fs::create_dir_all(crate::conf::data_dir());
|
||||
if let Ok(mut f) = std::fs::OpenOptions::new().create(true).append(true).open(path()) {
|
||||
let _ = writeln!(f, "{line}");
|
||||
}
|
||||
}
|
||||
|
||||
/// (requests, input, output, cost) per model since `since` (ms).
|
||||
pub fn summary(since: i64) -> Vec<(String, u64, u64, u64, f64)> {
|
||||
let text = std::fs::read_to_string(path()).unwrap_or_default();
|
||||
let mut map: std::collections::BTreeMap<String, (u64, u64, u64, f64)> = Default::default();
|
||||
for line in text.lines() {
|
||||
let Ok(v) = serde_json::from_str::<Value>(line) else { continue };
|
||||
if v["ts"].as_i64().unwrap_or(0) < since {
|
||||
continue;
|
||||
}
|
||||
let e = map.entry(v["model"].as_str().unwrap_or("?").to_string()).or_default();
|
||||
e.0 += 1;
|
||||
e.1 += v["in"].as_u64().unwrap_or(0) + v["cache_read"].as_u64().unwrap_or(0) + v["cache_write"].as_u64().unwrap_or(0);
|
||||
e.2 += v["out"].as_u64().unwrap_or(0);
|
||||
e.3 += v["cost"].as_f64().unwrap_or(0.0);
|
||||
}
|
||||
map.into_iter().map(|(k, (n, i, o, c))| (k, n, i, o, c)).collect()
|
||||
}
|
||||
Reference in new issue
Block a user