1pub mod config_api;
2pub mod harvester_api;
3
4use axum::{
5 response::{Html, Json},
6 routing::{get, post, put},
7 Router,
8};
9use serde_json::{json, Value};
10use std::sync::Arc;
11use tower_http::cors::CorsLayer;
12use tower_http::services::ServeDir;
13
14use crate::memory::{MemoryRepository, SilentHarvesterService};
15
16#[derive(Clone)]
18pub struct AppState {
19 pub repository: Arc<MemoryRepository>,
20 pub harvester_service: Option<Arc<SilentHarvesterService>>,
21}
22
23pub fn create_api_router(state: AppState) -> Router {
25 Router::new()
26 .route("/api/health", get(health_check))
28 .route(
30 "/api/config/harvester",
31 get(config_api::get_harvester_config),
32 )
33 .route(
34 "/api/config/harvester",
35 put(config_api::update_harvester_config),
36 )
37 .route("/api/harvester/status", get(harvester_api::get_status))
39 .route(
40 "/api/harvester/toggle",
41 post(harvester_api::toggle_harvester),
42 )
43 .route("/api/harvester/stats", get(harvester_api::get_statistics))
44 .route(
45 "/api/harvester/recent",
46 get(harvester_api::get_recent_memories),
47 )
48 .route("/api/harvester/export", get(harvester_api::export_history))
49 .nest_service("/", ServeDir::new("static"))
51 .route("/", get(serve_dashboard))
52 .with_state(state)
53 .layer(CorsLayer::permissive())
54}
55
56async fn health_check() -> Json<Value> {
58 Json(json!({
59 "status": "ok",
60 "service": "codex-memory-api",
61 "version": env!("CARGO_PKG_VERSION")
62 }))
63}
64
65async fn serve_dashboard() -> Html<&'static str> {
67 Html(include_str!("../../static/index.html"))
68}