summaryrefslogtreecommitdiff
path: root/makima/src/server/handlers
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-21 23:51:11 +0000
committerGitHub <noreply@github.com>2026-02-21 23:51:11 +0000
commit0523765af84492640928d571f481e17b26008b13 (patch)
tree644e0bac90c1945120df27dea36d18c81f4470e9 /makima/src/server/handlers
parentd670dcb72984cfa483063d161bb468704038895c (diff)
downloadsoryu-0523765af84492640928d571f481e17b26008b13.tar.gz
soryu-0523765af84492640928d571f481e17b26008b13.zip
feat: Add daemon health monitoring page, downloads & K8s support (#76)
* feat: soryu-co/soryu - makima: Add server-side daemon binary download endpoint * feat: soryu-co/soryu - makima: Create Kubernetes daemon manifests and Dockerfile * feat: soryu-co/soryu - makima: Create dedicated Daemons page with health monitoring UI * WIP: heartbeat checkpoint * feat: soryu-co/soryu - makima: Integrate daemon platform availability into frontend downloads
Diffstat (limited to 'makima/src/server/handlers')
-rw-r--r--makima/src/server/handlers/daemon_download.rs163
-rw-r--r--makima/src/server/handlers/mod.rs1
2 files changed, 164 insertions, 0 deletions
diff --git a/makima/src/server/handlers/daemon_download.rs b/makima/src/server/handlers/daemon_download.rs
new file mode 100644
index 0000000..1575d8b
--- /dev/null
+++ b/makima/src/server/handlers/daemon_download.rs
@@ -0,0 +1,163 @@
+//! HTTP handlers for daemon binary downloads.
+//!
+//! Serves pre-compiled daemon binaries for download. Binaries are read from
+//! disk at a configurable path (default: `/app/daemon-binaries`), overridable
+//! via the `DAEMON_BINARIES_DIR` environment variable.
+
+use axum::{
+ extract::Path,
+ http::{header, StatusCode},
+ response::IntoResponse,
+ Json,
+};
+use serde::Serialize;
+
+/// Default directory where daemon binaries are stored.
+const DEFAULT_BINARIES_DIR: &str = "/app/daemon-binaries";
+
+/// Supported platforms for daemon binary downloads.
+const SUPPORTED_PLATFORMS: &[&str] = &[
+ "linux-x86_64",
+ "linux-arm64",
+ "macos-x86_64",
+ "macos-arm64",
+];
+
+/// Response for listing available daemon platforms.
+#[derive(Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct PlatformInfo {
+ /// Platform identifier (e.g., "linux-x86_64")
+ pub platform: String,
+ /// Whether a binary is available for this platform
+ pub available: bool,
+ /// Download URL path for this platform
+ pub download_url: String,
+}
+
+/// Response for the list platforms endpoint.
+#[derive(Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ListPlatformsResponse {
+ /// List of supported platforms and their availability
+ pub platforms: Vec<PlatformInfo>,
+}
+
+/// Get the binaries directory from environment or use default.
+fn get_binaries_dir() -> String {
+ std::env::var("DAEMON_BINARIES_DIR").unwrap_or_else(|_| DEFAULT_BINARIES_DIR.to_string())
+}
+
+/// Get the binary file path for a given platform.
+fn get_binary_path(platform: &str) -> std::path::PathBuf {
+ let dir = get_binaries_dir();
+ std::path::PathBuf::from(dir).join(format!("makima-{}", platform))
+}
+
+/// List available daemon platforms and their download availability.
+///
+/// Returns a list of all supported platforms with availability status
+/// based on whether the binary file exists on disk.
+pub async fn list_daemon_platforms() -> impl IntoResponse {
+ let mut platforms = Vec::with_capacity(SUPPORTED_PLATFORMS.len());
+
+ for &platform in SUPPORTED_PLATFORMS {
+ let path = get_binary_path(platform);
+ let available = path.exists();
+
+ platforms.push(PlatformInfo {
+ platform: platform.to_string(),
+ available,
+ download_url: format!("/api/v1/daemon/download/{}", platform),
+ });
+ }
+
+ (
+ StatusCode::OK,
+ Json(ListPlatformsResponse { platforms }),
+ )
+ .into_response()
+}
+
+/// Download a daemon binary for the specified platform.
+///
+/// Reads the binary from disk and returns it with appropriate headers
+/// for file download. Returns 404 if the binary is not available.
+pub async fn download_daemon(
+ Path(platform): Path<String>,
+) -> impl IntoResponse {
+ // Validate platform
+ if !SUPPORTED_PLATFORMS.contains(&platform.as_str()) {
+ return (
+ StatusCode::BAD_REQUEST,
+ Json(serde_json::json!({
+ "code": "INVALID_PLATFORM",
+ "message": format!(
+ "Unsupported platform '{}'. Supported platforms: {}",
+ platform,
+ SUPPORTED_PLATFORMS.join(", ")
+ )
+ })),
+ )
+ .into_response();
+ }
+
+ let binary_path = get_binary_path(&platform);
+
+ // Read binary from disk
+ let binary_data = match tokio::fs::read(&binary_path).await {
+ Ok(data) => data,
+ Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
+ return (
+ StatusCode::NOT_FOUND,
+ Json(serde_json::json!({
+ "code": "BINARY_NOT_FOUND",
+ "message": format!(
+ "Daemon binary for platform '{}' is not available for download",
+ platform
+ )
+ })),
+ )
+ .into_response();
+ }
+ Err(e) => {
+ tracing::error!(
+ platform = %platform,
+ path = %binary_path.display(),
+ error = %e,
+ "Failed to read daemon binary"
+ );
+ return (
+ StatusCode::INTERNAL_SERVER_ERROR,
+ Json(serde_json::json!({
+ "code": "READ_ERROR",
+ "message": "Failed to read daemon binary"
+ })),
+ )
+ .into_response();
+ }
+ };
+
+ let filename = format!("makima-{}", platform);
+
+ // Return binary with download headers
+ (
+ StatusCode::OK,
+ [
+ (
+ header::CONTENT_TYPE,
+ "application/octet-stream".to_string(),
+ ),
+ (
+ header::CONTENT_DISPOSITION,
+ format!("attachment; filename=\"{}\"", filename),
+ ),
+ (
+ header::CONTENT_LENGTH,
+ binary_data.len().to_string(),
+ ),
+ ],
+ binary_data,
+ )
+ .into_response()
+}
diff --git a/makima/src/server/handlers/mod.rs b/makima/src/server/handlers/mod.rs
index 8b06a28..4bdb424 100644
--- a/makima/src/server/handlers/mod.rs
+++ b/makima/src/server/handlers/mod.rs
@@ -5,6 +5,7 @@ pub mod chat;
pub mod contract_chat;
pub mod contract_daemon;
pub mod contract_discuss;
+pub mod daemon_download;
pub mod contracts;
pub mod directives;
pub mod file_ws;