import { useState, useEffect, useCallback } from "react"; import { useAuth } from "../contexts/AuthContext"; import { useNavigate } from "react-router"; import { Masthead } from "../components/Masthead"; import { listDaemons, restartDaemon, listDaemonPlatforms, API_BASE, type Daemon, type DaemonListResponse, type DaemonPlatform, type RestartDaemonResponse, } from "../lib/api"; // ============================================================================= // Section Header Component // ============================================================================= function SectionHeader({ children }: { children: React.ReactNode }) { return (

{children}

); } // ============================================================================= // Alert Component // ============================================================================= function ErrorAlert({ children }: { children: React.ReactNode }) { return (
{children}
); } // ============================================================================= // Daemons Page // ============================================================================= export default function DaemonsPage() { const { isAuthenticated, isAuthConfigured } = useAuth(); const navigate = useNavigate(); // Daemon state const [daemons, setDaemons] = useState([]); const [daemonsLoading, setDaemonsLoading] = useState(true); const [daemonsError, setDaemonsError] = useState(null); const [restartingDaemonId, setRestartingDaemonId] = useState(null); const [restartConfirmDaemonId, setRestartConfirmDaemonId] = useState(null); // Platform availability state const [platforms, setPlatforms] = useState([]); const [platformsLoading, setPlatformsLoading] = useState(true); // Redirect if not authenticated useEffect(() => { if (isAuthConfigured && !isAuthenticated) { navigate("/login"); } }, [isAuthConfigured, isAuthenticated, navigate]); const loadDaemons = async () => { try { setDaemonsError(null); const response: DaemonListResponse = await listDaemons(); setDaemons(response.daemons); } catch (err) { setDaemonsError(err instanceof Error ? err.message : "Failed to load daemons"); } finally { setDaemonsLoading(false); } }; const handleRestartDaemon = async (id: string) => { try { setRestartingDaemonId(id); setDaemonsError(null); const _response: RestartDaemonResponse = await restartDaemon(id); // Daemon will restart, so refresh the list after a short delay setTimeout(() => { loadDaemons(); }, 2000); } catch (err) { setDaemonsError(err instanceof Error ? err.message : "Failed to restart daemon"); } finally { setRestartingDaemonId(null); setRestartConfirmDaemonId(null); } }; // Friendly labels for platform identifiers const platformLabels: Record = { "linux-x86_64": "Linux (Intel/AMD)", "linux-arm64": "Linux (ARM64)", "macos-x86_64": "macOS (Intel)", "macos-arm64": "macOS (Apple Silicon)", }; const loadPlatforms = useCallback(async () => { try { setPlatformsLoading(true); const response = await listDaemonPlatforms(); setPlatforms(response.platforms); } catch { // Fallback: show all platforms as unavailable if API endpoint is missing setPlatforms([ { platform: "linux-x86_64", available: false, downloadUrl: "/api/v1/daemon/download/linux-x86_64" }, { platform: "linux-arm64", available: false, downloadUrl: "/api/v1/daemon/download/linux-arm64" }, { platform: "macos-x86_64", available: false, downloadUrl: "/api/v1/daemon/download/macos-x86_64" }, { platform: "macos-arm64", available: false, downloadUrl: "/api/v1/daemon/download/macos-arm64" }, ]); } finally { setPlatformsLoading(false); } }, []); // Initial load useEffect(() => { loadDaemons(); loadPlatforms(); }, []); // Auto-refresh daemons every 30 seconds useEffect(() => { const interval = setInterval(() => { loadDaemons(); }, 30000); return () => clearInterval(interval); }, []); return (
{/* Page Header */}

Daemons

Daemons are worker processes that connect to Makima and execute tasks on your machines.

{/* Left Column */}
{/* Download Section */}
Download Daemon

Download the pre-compiled daemon binary for your platform. The daemon connects to the Makima server and executes tasks.

{platformsLoading ? (

Loading platforms...

) : ( platforms.map((p) => ( {platformLabels[p.platform] || p.platform} {p.available ? "Available" : "Not bundled"} )) )}

Quick Install

curl -fsSL https://raw.githubusercontent.com/soryu-co/soryu/master/install.sh | bash
{/* Daemon Setup */}
Daemon Setup

Set your API key as an environment variable:

export MAKIMA_API_KEY="your-key"

Then run: makima-daemon

{/* Kubernetes Section */}
Run in Kubernetes

Deploy daemons as containers in Kubernetes for scalable task execution.

Pull Container Image

docker pull ghcr.io/soryu-co/makima-daemon:latest

Environment Variables

MAKIMA_API_KEY="your-key"
MAKIMA_SERVER_URL="https://your-server"
GITHUB_TOKEN="ghp_..." # optional, for repo access

Kubernetes manifests available in the repository under k8s/daemon/

{/* Right Column */}
{/* Connected Daemons */}

Connected Daemons

{daemons.length > 0 && ( ({daemons.filter(d => d.status === "connected").length} connected / {daemons.length} total) )}
{daemonsError && {daemonsError}} {daemonsLoading && daemons.length === 0 ? (

Loading...

) : daemons.length === 0 ? (

No daemons connected

Start a daemon to enable task execution

) : (
{daemons.map((daemon) => (
{daemon.hostname || "Unknown Host"}
{daemon.status}
Tasks {daemon.currentTaskCount} / {daemon.maxConcurrentTasks}
Connected {new Date(daemon.connectedAt).toLocaleString()}
{daemon.machineId && (
Machine {daemon.machineId.substring(0, 16)}...
)}
{/* Restart Section */} {daemon.status === "connected" && (
{restartConfirmDaemonId === daemon.id ? (
Restart daemon? Running tasks will be interrupted.
) : ( )}
)}
))}
)}
); }