Files
codecraft/server/src/main.rs
T
Richard ZinkandClaude Opus 5.5 d152ad836d Split view, personal modes, budget warnings, server move script
- Up to three chats side by side (#/s/a+b+c), "Open beside" in the sidebar menu
- File manager tabs of a chat stored per user on the server (/sessions/{id}/tabs)
- Personal modes for every user (Settings → My modes, /account/modes)
- Budget meters (total, provider, images, opencode Go windows) with push warnings
  for admins at the warning share and 100 %, shown in the status overlay
- scripts/move-server.sh: move to another Docker host with bind mounts (Unraid);
  scripts/smoke-test.sh

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 12:06:20 +01:00

88 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 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 permission;
mod prompts;
mod push;
mod provider;
mod reverse;
mod runner;
mod sandbox;
mod shells;
mod store;
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());
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");
}