chore: hapus semua source Rust + Cargo.toml/lock + .cargo (247 file .rs, migrasi ke TS/Bun)

This commit is contained in:
asepharyana
2026-09-02 22:51:10 +07:00
parent 319198d2f0
commit c165dff114
250 changed files with 0 additions and 33715 deletions
-108
View File
@@ -1,108 +0,0 @@
//! Database migration binary.
//!
//! Scans all session directories and initializes or upgrades the SQLite
//! schema for each one. Standalone CLI tool invoked as `cargo run --bin migrate`.
use std::path::Path;
fn main() -> anyhow::Result<()> {
let store = zesdex_domain::core::Store::new();
let sessions_dir = store.base_dir.join("sessions");
if !sessions_dir.exists() {
tracing::info!("No sessions directory found, nothing to migrate");
return Ok(());
}
let mut migrated = 0u32;
let mut failed = 0u32;
for entry in std::fs::read_dir(&sessions_dir)? {
let entry = entry?;
let path = entry.path();
if !path.is_dir() {
continue;
}
match migrate_session_msglog(&path) {
Ok(_) => {
migrated += 1;
tracing::info!("Migrated session: {:?}", path.file_name());
}
Err(e) => {
failed += 1;
tracing::error!("Failed to migrate session {:?}: {e}", path.file_name());
}
}
}
tracing::info!("Migration complete: {migrated} succeeded, {failed} failed");
if failed > 0 {
anyhow::bail!("{failed} session(s) failed to migrate");
}
Ok(())
}
fn migrate_session_msglog(session_dir: &Path) -> anyhow::Result<()> {
let msglog_path = session_dir.join("messages.sqlite");
if let Some(parent) = msglog_path.parent() {
std::fs::create_dir_all(parent)?;
}
let conn = rusqlite::Connection::open(&msglog_path)?;
conn.execute_batch("PRAGMA journal_mode = WAL;")?;
conn.execute_batch("PRAGMA busy_timeout = 5000;")?;
conn.execute_batch("PRAGMA foreign_keys = ON;")?;
conn.execute_batch(
"CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL,
role TEXT NOT NULL,
content TEXT,
tool_call_id TEXT,
tool_name TEXT,
tool_arguments TEXT,
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS archives (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL UNIQUE,
title TEXT,
model TEXT,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
message_count INTEGER DEFAULT 0,
token_count INTEGER DEFAULT 0,
summary TEXT
);
CREATE INDEX IF NOT EXISTS idx_messages_session_id ON messages(session_id);
CREATE INDEX IF NOT EXISTS idx_messages_created_at ON messages(created_at);
CREATE INDEX IF NOT EXISTS idx_archives_created_at ON archives(created_at);
CREATE TABLE IF NOT EXISTS blobs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL,
blob_key TEXT NOT NULL,
data BLOB NOT NULL,
mime_type TEXT,
created_at INTEGER NOT NULL,
UNIQUE(session_id, blob_key)
);",
)?;
let version: i32 = conn
.pragma_query_value(None, "user_version", |row| row.get(0))
.unwrap_or(0);
if version < 1 {
conn.pragma_update(None, "user_version", 1)?;
}
if version < 2 {
conn.execute_batch(
"CREATE INDEX IF NOT EXISTS idx_messages_session_role ON messages(session_id, role);",
)?;
conn.pragma_update(None, "user_version", 2)?;
}
Ok(())
}
-57
View File
@@ -1,57 +0,0 @@
//! Database seeder binary.
//!
//! Initialises the store directory structure and creates default
//! configuration files plus a seed session for development/testing.
//! Invoked as `cargo run --bin seed`.
fn main() -> anyhow::Result<()> {
let store = zesdex_domain::core::Store::new();
store.ensure_dirs()?;
// Create default settings if not present
let settings_path = store.base_dir.join("settings.json");
if !settings_path.exists() {
let settings = zesdex_domain::cms::Settings::default();
let content = serde_json::to_string_pretty(&settings)?;
let tmp = store.base_dir.join("settings.json.tmp");
std::fs::write(&tmp, content)?;
let f = std::fs::File::open(&tmp)?;
f.sync_all()?;
std::fs::rename(&tmp, settings_path)?;
tracing::info!("Default settings created");
} else {
tracing::info!("Settings already exist, skipping");
}
// Create default app config if not present
let config_path = store.base_dir.join("app_config.json");
if !config_path.exists() {
let config = zesdex_domain::cms::AppConfig::default();
let content = serde_json::to_string_pretty(&config)?;
let tmp = store.base_dir.join("app_config.json.tmp");
std::fs::write(&tmp, content)?;
let f = std::fs::File::open(&tmp)?;
f.sync_all()?;
std::fs::rename(&tmp, config_path)?;
tracing::info!("Default app_config created");
} else {
tracing::info!("App config already exists, skipping");
}
// Create data directories
std::fs::create_dir_all(&store.memory_dir)?;
std::fs::create_dir_all(&store.session_images_dir)?;
tracing::info!("All store directories verified");
// Create a seed session
let session_id = uuid::Uuid::new_v4().to_string();
let session = zesdex_domain::auth::Session::new(session_id.clone(), "Seed Session".to_string());
// Persist via the session repository
use zesdex_domain::SessionRepository;
let repo =
zesdex_infrastructure::persistence::iam::session_repo::FileSystemSessionRepository::new();
repo.save_session(&store.base_dir, &session)?;
tracing::info!("Seed session created: id={session_id}");
Ok(())
}
-20
View File
@@ -1,20 +0,0 @@
use zesdex_domain::cms::AppConfigRepository;
use zesdex_infrastructure::persistence::cms::app_config_repo::JsonAppConfigRepository;
fn main() {
let base_dir = dirs::home_dir().unwrap().join(".local/share/zesdex");
let repo = JsonAppConfigRepository::new();
let config = repo.load(&base_dir).unwrap();
println!("Providers:");
for (k, v) in &config.providers {
println!(" - {} (default model: {:?})", k, v.default_model);
}
println!("Default provider: {}", config.default_provider);
println!("Default model: {}", config.default_model);
println!("Model roles:");
for (k, v) in &config.model_roles {
println!(" - {}: provider={}, model={}", k, v.provider, v.model);
}
}
-46
View File
@@ -1,46 +0,0 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
struct ClaudeEnv {
#[serde(alias = "ANTHROPIC_BASE_URL")]
anthropic_base_url: Option<String>,
#[serde(alias = "ANTHROPIC_API_KEY")]
anthropic_api_key: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct ClaudeSettings {
env: Option<ClaudeEnv>,
#[serde(alias = "customModel", alias = "model")]
custom_model: Option<String>,
}
fn main() {
let path = dirs::home_dir()
.unwrap()
.join(".claude")
.join("settings.json");
println!("Path: {:?}", path);
match std::fs::read_to_string(&path) {
Ok(content) => {
println!("File content length: {}", content.len());
match serde_json::from_str::<ClaudeSettings>(&content) {
Ok(settings) => {
println!("Parsed successfully: {:?}", settings);
if let Some(env) = settings.env {
println!("Base URL: {:?}", env.anthropic_base_url);
println!("API Key: {:?}", env.anthropic_api_key);
} else {
println!("No env block");
}
}
Err(e) => {
println!("Parse error: {}", e);
}
}
}
Err(e) => {
println!("Read error: {}", e);
}
}
}
-2
View File
@@ -1,2 +0,0 @@
//! Gateway library — provides shared utilities for the gateway binary.
//! The main entry point is in `main.rs`.
-190
View File
@@ -1,190 +0,0 @@
//! Zesdex Gateway — main entry point.
//!
//! Assembles domain + application + infrastructure layers and dispatches
//! to the requested interface: TUI (default), daemon (background IPC),
//! API server (REST), WebSocket server, gRPC server, or Web frontend.
//!
//! CLI flags are parsed via clap; run with `--help` for details.
use std::sync::Mutex;
use clap::Parser;
/// Zesdex — autonomous AI coding agent.
#[derive(Parser, Debug)]
#[command(
name = "zesdex",
version,
about = "Autonomous AI coding agent with TUI"
)]
struct Cli {
/// Run as background daemon with IPC socket
#[arg(long)]
daemon: bool,
/// Attach TUI client to a running daemon session
#[arg(long)]
attach: Option<String>,
/// Run REST API server
#[arg(long)]
api: bool,
/// REST API port
#[arg(long, default_value_t = 8080)]
api_port: u16,
/// Run WebSocket server
#[arg(long)]
ws: bool,
/// WebSocket port
#[arg(long, default_value_t = 8081)]
ws_port: u16,
/// Run gRPC server
#[arg(long)]
grpc: bool,
/// gRPC port
#[arg(long, default_value_t = 50051)]
grpc_port: u16,
/// Serve web frontend
#[arg(long)]
web: bool,
/// Web frontend port
#[arg(long, default_value_t = 3000)]
web_port: u16,
}
fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
// ── Setup logging ────────────────────────────────────────────────────
let log_dir = dirs::data_dir()
.unwrap_or_else(|| std::path::PathBuf::from("."))
.join("zesdex");
let _ = std::fs::create_dir_all(&log_dir);
let log_path = log_dir.join("zesdex.log");
let log_file = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(&log_path)
.unwrap_or_else(|_| {
std::fs::OpenOptions::new()
.write(true)
.open("/dev/null")
.expect("cannot open /dev/null")
});
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
)
.with_writer(Mutex::new(log_file))
.init();
tracing::info!("zesdex gateway starting");
// ── Dispatch to interface ────────────────────────────────────────────
// Validate mutually exclusive flags
let mode_count = [cli.daemon, cli.api, cli.ws, cli.grpc, cli.web]
.iter()
.filter(|&&b| b)
.count()
+ if cli.attach.is_some() { 1 } else { 0 };
if mode_count > 1 {
anyhow::bail!(
"Cannot specify multiple modes: --daemon, --attach, --api, --ws, --grpc, --web are mutually exclusive"
);
}
if cli.daemon {
tracing::info!("starting in daemon mode");
zesdex_daemon::server::run_daemon()?;
} else if let Some(session_id) = cli.attach {
tracing::info!("starting in attach mode for session {session_id}");
zesdex_daemon::client::run_attach(&session_id)?;
} else if cli.api {
tracing::info!("starting in API server mode");
run_api_server(cli.api_port)?;
} else if cli.ws {
tracing::info!("starting in WebSocket server mode");
run_ws_server(cli.ws_port)?;
} else if cli.grpc {
tracing::info!("starting in gRPC server mode");
run_grpc_server(cli.grpc_port)?;
} else if cli.web {
tracing::info!("starting in web server mode");
run_web_server(cli.web_port)?;
} else {
// Default: run TUI single-process mode
tracing::info!("starting in TUI single-process mode");
run_tui_single_process()?;
}
Ok(())
}
/// Run the TUI in single-process mode (TUI + agent in one process).
fn run_tui_single_process() -> anyhow::Result<()> {
zesdex_tui::run_single_process()
}
/// Run the REST API server.
fn run_api_server(port: u16) -> anyhow::Result<()> {
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(async {
let store = zesdex_domain::core::Store::new();
store.ensure_dirs()?;
// Load JWT secret from environment variable with a secure default warning
let jwt_secret = std::env::var("JWT_SECRET").unwrap_or_else(|_| {
tracing::warn!(
"JWT_SECRET environment variable not set; using insecure default. \
Set JWT_SECRET to a secure random value in production."
);
zesdex_domain::agent::defaults::FALLBACK_JWT_SECRET.to_string()
});
let state = zesdex_api::ApiState::new(
store.base_dir.clone(),
jwt_secret,
"",
zesdex_domain::agent::defaults::DEFAULT_MODEL,
Some(zesdex_domain::agent::defaults::DEFAULT_API_BASE.to_string()),
);
let app = zesdex_api::build_router(state);
let addr = std::net::SocketAddr::from(([0, 0, 0, 0], port));
tracing::info!("REST API server listening on http://{addr}/api/v1/health");
let listener = tokio::net::TcpListener::bind(addr).await?;
axum::serve(listener, app).await?;
Ok::<_, anyhow::Error>(())
})?;
Ok(())
}
/// Run the WebSocket server.
fn run_ws_server(port: u16) -> anyhow::Result<()> {
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(async { zesdex_ws::run_server(port).await })?;
Ok(())
}
/// Run the gRPC server.
fn run_grpc_server(port: u16) -> anyhow::Result<()> {
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(async { zesdex_grpc::run_server(port).await })?;
Ok(())
}
/// Serve the web frontend.
fn run_web_server(port: u16) -> anyhow::Result<()> {
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(async { zesdex_web::run_server(port, None).await })?;
Ok(())
}