Rust (Axum) + Vue 3 + SQLite. Features: - Project CRUD REST API with proper error handling - Per-project agent loop (mpsc + broadcast channels) - LLM-driven plan generation and replan on user feedback - SSH command execution with status streaming - WebSocket real-time updates to frontend - Four-zone UI: requirement, plan (left), execution (right), comment Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
107 lines
2.9 KiB
Rust
107 lines
2.9 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use sqlx::sqlite::{SqlitePool, SqlitePoolOptions};
|
|
|
|
#[derive(Clone)]
|
|
pub struct Database {
|
|
pub pool: SqlitePool,
|
|
}
|
|
|
|
impl Database {
|
|
pub async fn new(path: &str) -> anyhow::Result<Self> {
|
|
let url = format!("sqlite:{}?mode=rwc", path);
|
|
let pool = SqlitePoolOptions::new()
|
|
.max_connections(5)
|
|
.connect(&url)
|
|
.await?;
|
|
Ok(Self { pool })
|
|
}
|
|
|
|
pub async fn migrate(&self) -> anyhow::Result<()> {
|
|
sqlx::query(
|
|
"CREATE TABLE IF NOT EXISTS projects (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
description TEXT NOT NULL DEFAULT '',
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)"
|
|
)
|
|
.execute(&self.pool)
|
|
.await?;
|
|
|
|
sqlx::query(
|
|
"CREATE TABLE IF NOT EXISTS workflows (
|
|
id TEXT PRIMARY KEY,
|
|
project_id TEXT NOT NULL REFERENCES projects(id),
|
|
requirement TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)"
|
|
)
|
|
.execute(&self.pool)
|
|
.await?;
|
|
|
|
sqlx::query(
|
|
"CREATE TABLE IF NOT EXISTS plan_steps (
|
|
id TEXT PRIMARY KEY,
|
|
workflow_id TEXT NOT NULL REFERENCES workflows(id),
|
|
step_order INTEGER NOT NULL,
|
|
description TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
output TEXT NOT NULL DEFAULT ''
|
|
)"
|
|
)
|
|
.execute(&self.pool)
|
|
.await?;
|
|
|
|
sqlx::query(
|
|
"CREATE TABLE IF NOT EXISTS comments (
|
|
id TEXT PRIMARY KEY,
|
|
workflow_id TEXT NOT NULL REFERENCES workflows(id),
|
|
content TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)"
|
|
)
|
|
.execute(&self.pool)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
|
|
pub struct Project {
|
|
pub id: String,
|
|
pub name: String,
|
|
pub description: String,
|
|
pub created_at: String,
|
|
pub updated_at: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
|
|
pub struct Workflow {
|
|
pub id: String,
|
|
pub project_id: String,
|
|
pub requirement: String,
|
|
pub status: String,
|
|
pub created_at: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
|
|
pub struct PlanStep {
|
|
pub id: String,
|
|
pub workflow_id: String,
|
|
pub step_order: i32,
|
|
pub description: String,
|
|
pub status: String,
|
|
pub output: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
|
|
pub struct Comment {
|
|
pub id: String,
|
|
pub workflow_id: String,
|
|
pub content: String,
|
|
pub created_at: String,
|
|
}
|