summaryrefslogblamecommitdiff
path: root/makima/cloudflare-agent/src/types.ts
blob: d2ab20a2a80c7c1e60ca216980d2a9099fb0741b (plain) (tree)



















































































































































                                                                                                                                                                                                    
/**
 * Type definitions for the Makima Cloudflare Agent.
 *
 * These types mirror the daemon-server WebSocket protocol defined in
 * makima/src/daemon/ws/protocol.rs. Only the subset relevant to the
 * edge relay is included here.
 */

// ---------------------------------------------------------------------------
// Worker Environment
// ---------------------------------------------------------------------------

export interface Env {
  /** Durable Object binding for MakimaAgent instances. */
  MAKIMA_AGENT: DurableObjectNamespace;
  /** Makima server WebSocket URL (e.g. wss://api.makima.jp). */
  MAKIMA_SERVER_URL: string;
  /** API key for authenticating with the Makima server. */
  MAKIMA_API_KEY: string;
  /** Optional: human-readable name for this edge agent. */
  MAKIMA_AGENT_NAME?: string;
}

// ---------------------------------------------------------------------------
// Agent State (persisted in Durable Object SQLite)
// ---------------------------------------------------------------------------

export interface AgentState {
  /** Whether the upstream WebSocket is currently connected. */
  connected: boolean;
  /** ISO-8601 timestamp of last successful connection. */
  lastConnectedAt: string | null;
  /** ISO-8601 timestamp of last heartbeat sent. */
  lastHeartbeatAt: string | null;
  /** Number of consecutive reconnect failures. */
  reconnectAttempts: number;
  /** Daemon ID assigned by the server after authentication. */
  daemonId: string | null;
  /** Active task IDs being tracked through this relay. */
  activeTasks: string[];
}

export const DEFAULT_AGENT_STATE: AgentState = {
  connected: false,
  lastConnectedAt: null,
  lastHeartbeatAt: null,
  reconnectAttempts: 0,
  daemonId: null,
  activeTasks: [],
};

// ---------------------------------------------------------------------------
// Daemon → Server Messages (subset used by the relay)
// ---------------------------------------------------------------------------

export type DaemonMessage =
  | { type: "authenticate"; apiKey: string; machineId: string; hostname: string; maxConcurrentTasks: number }
  | { type: "heartbeat"; activeTasks: string[] }
  | { type: "taskOutput"; taskId: string; output: string; isPartial: boolean }
  | { type: "taskStatusChange"; taskId: string; oldStatus: string; newStatus: string }
  | { type: "taskProgress"; taskId: string; summary: string }
  | { type: "taskComplete"; taskId: string; success: boolean; error?: string };

// ---------------------------------------------------------------------------
// Server → Daemon Commands (subset relevant to the relay)
// ---------------------------------------------------------------------------

export type DaemonCommand =
  | { type: "authenticated"; daemonId: string }
  | { type: "spawnTask"; taskId: string; taskName: string; plan: string; repoUrl?: string; baseBranch?: string; targetBranch?: string; contractId?: string; depth: number; isOrchestrator: boolean }
  | { type: "pauseTask"; taskId: string }
  | { type: "resumeTask"; taskId: string }
  | { type: "interruptTask"; taskId: string; graceful: boolean }
  | { type: "sendMessage"; taskId: string; message: string };

// ---------------------------------------------------------------------------
// Task History Record (stored in SQLite)
// ---------------------------------------------------------------------------

export interface TaskRecord {
  /** UUID of the task. */
  taskId: string;
  /** Human-readable task name. */
  taskName: string;
  /** Current status: pending | dispatched | completed | failed. */
  status: string;
  /** Which downstream daemon received this task. */
  dispatchedTo: string | null;
  /** ISO-8601 timestamp when the task was received. */
  receivedAt: string;
  /** ISO-8601 timestamp when the task was dispatched downstream. */
  dispatchedAt: string | null;
  /** ISO-8601 timestamp when the task completed. */
  completedAt: string | null;
  /** Error message if failed. */
  error: string | null;
}

// ---------------------------------------------------------------------------
// Connected Downstream Daemon
// ---------------------------------------------------------------------------

export interface DownstreamDaemon {
  /** Unique ID for this downstream connection. */
  id: string;
  /** WebSocket connection to this daemon. */
  ws: WebSocket;
  /** Human-readable hostname. */
  hostname: string;
  /** Maximum concurrent tasks this daemon supports. */
  maxConcurrentTasks: number;
  /** Currently active task IDs on this daemon. */
  activeTasks: Set<string>;
  /** ISO-8601 timestamp of last heartbeat received. */
  lastHeartbeat: string;
}

// ---------------------------------------------------------------------------
// HTTP API Response Types
// ---------------------------------------------------------------------------

export interface StatusResponse {
  status: "ok" | "degraded" | "disconnected";
  agentName: string;
  upstreamConnected: boolean;
  daemonId: string | null;
  lastHeartbeat: string | null;
  connectedDaemons: number;
  activeTasks: number;
  totalTasksProcessed: number;
}

export interface TaskHistoryResponse {
  tasks: TaskRecord[];
  total: number;
  limit: number;
  offset: number;
}

// ---------------------------------------------------------------------------
// RPC method types for the Agent
// ---------------------------------------------------------------------------

export interface AgentRPC {
  getStatus: () => StatusResponse;
  getTaskHistory: (limit?: number, offset?: number) => TaskHistoryResponse;
  reconnect: () => { success: boolean; message: string };
}