Files
codecraft/server/src/main.rs
T
Richard ZinkandClaude Opus 5.5 3b0764450a Long chats stay fast; search in a chat; media overview
Performance (measured with 5,900 messages: open 9 s -> 0.7 s, typing 440 ms -> 25 ms)
- GET /sessions/{id}?limit=N loads the end of a chat (from the last summary
  on, at most N); /sessions/{id}/messages?before|after|around loads more
  (scrolling up stops at a summary unless asked). Without parameters the
  full history as before (terminal client).
- Chat view: memoised message list (typing, streaming and status changes no
  longer re-render the history), finished turns fold into "N steps · M files"
  with the answer visible, tool card bodies and summaries are built only when
  opened, scroll-to-bottom only when content changes.

Search: /sessions/{id}/search over the whole chat; a hit loads its part
(around) and marks the message, "back to the latest messages" returns.

Media: /sessions/{id}/media lists images, videos and audio of a chat and its
subagents (generated images, tool output, files written, media in answers,
attachments); ⋯ -> Media shows them with filters, a large view and a jump to
the message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 07:32:18 +01:00

92 lines
2.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! CodeCraft – web-based coding harness for AI models.
mod api;
mod app;
mod auth;
mod backup;
mod blobs;
mod cli_api;
mod budget;
mod config;
mod digest;
mod docs;
mod export;
mod files;
mod git;
mod health;
mod gitcreds;
mod hooks;
mod images;
mod jobs;
mod lsp;
mod mentions;
mod metrics;
mod mcp;
mod media;
mod permission;
mod prompts;
mod push;
mod provider;
mod reverse;
mod runner;
mod sandbox;
mod shells;
mod store;
mod telegram;
mod terminal;
mod tools;
mod types;
mod update;
use anyhow::Result;
use tracing_subscriber::EnvFilter;
#[tokio::main]
async fn main() -> Result<()> {
// CODECRAFT_LOG_FORMAT=json: one JSON object per line (Loki, Elastic, …).
let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info,codecraft=info"));
if std::env::var("CODECRAFT_LOG_FORMAT").is_ok_and(|f| f.eq_ignore_ascii_case("json")) {
tracing_subscriber::fmt().json().flatten_event(true).with_current_span(false).with_env_filter(filter).init();
} else {
tracing_subscriber::fmt().with_env_filter(filter).init();
}
// In Docker, HOME lives on the data volume; make sure it exists for git/npm.
if let Ok(home) = std::env::var("HOME") {
let _ = std::fs::create_dir_all(home);
}
let path = config::config_path();
let (mut cfg, _) = config::load_or_init(&path)?;
// A backup restored from the settings is applied here, before the database is opened.
if backup::apply_pending_restore(&cfg.data_dir(), &path)? {
tracing::warn!("restored database and config from a backup");
cfg = config::load_or_init(&path)?.0;
}
tracing::info!("config: {}", path.display());
tracing::info!("workspace: {}", cfg.workspace().display());
let _ = sandbox::probe().await;
let bind = cfg.server.bind.clone();
let app = app::App::new(path, cfg).await?;
lsp::spawn_reaper(app.clone());
push::spawn_listener(app.clone());
terminal::spawn_reaper(app.clone());
jobs::spawn_scheduler(app.clone());
update::spawn_checker(app.clone());
health::spawn_checker(app.clone());
digest::spawn(app.clone());
budget::spawn_alerts(app.clone());
telegram::spawn(app.clone());
backup::spawn(app.clone());
let router = api::router(app);
let listener = tokio::net::TcpListener::bind(&bind).await?;
tracing::info!("listening on http://{bind}");
axum::serve(listener, router).with_graceful_shutdown(shutdown()).await?;
Ok(())
}
async fn shutdown() {
let _ = tokio::signal::ctrl_c().await;
tracing::info!("shutting down");
}