From 87044a747b47bd83249d61a45842c7f7b2eae56d Mon Sep 17 00:00:00 2001 From: soryu Date: Sun, 11 Jan 2026 05:52:14 +0000 Subject: Contract system --- makima/src/daemon/api/supervisor.rs | 186 ++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 makima/src/daemon/api/supervisor.rs (limited to 'makima/src/daemon/api/supervisor.rs') diff --git a/makima/src/daemon/api/supervisor.rs b/makima/src/daemon/api/supervisor.rs new file mode 100644 index 0000000..b691cc4 --- /dev/null +++ b/makima/src/daemon/api/supervisor.rs @@ -0,0 +1,186 @@ +//! Supervisor API methods. + +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +use super::client::{ApiClient, ApiError}; + +// Request/Response types + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct SpawnTaskRequest { + pub name: String, + pub plan: String, + pub contract_id: Uuid, + #[serde(skip_serializing_if = "Option::is_none")] + pub parent_task_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub checkpoint_sha: Option, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct WaitRequest { + pub timeout_seconds: i32, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct ReadFileRequest { + pub file_path: String, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CreateBranchRequest { + pub branch_name: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub from_ref: Option, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct MergeRequest { + pub squash: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pub target_branch: Option, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CreatePrRequest { + pub task_id: Uuid, + pub title: String, + pub body: String, + pub base_branch: String, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct CheckpointRequest { + pub message: String, +} + +// Generic response type for JSON output +#[derive(Deserialize, Serialize)] +pub struct JsonValue(pub serde_json::Value); + +impl ApiClient { + /// Get all tasks in a contract. + pub async fn supervisor_tasks(&self, contract_id: Uuid) -> Result { + self.get(&format!("/api/v1/mesh/supervisor/contracts/{}/tasks", contract_id)) + .await + } + + /// Get task tree structure. + pub async fn supervisor_tree(&self, contract_id: Uuid) -> Result { + self.get(&format!("/api/v1/mesh/supervisor/contracts/{}/tree", contract_id)) + .await + } + + /// Spawn a new task. + pub async fn supervisor_spawn(&self, req: SpawnTaskRequest) -> Result { + self.post("/api/v1/mesh/supervisor/tasks", &req).await + } + + /// Wait for a task to complete. + pub async fn supervisor_wait( + &self, + task_id: Uuid, + timeout_seconds: i32, + ) -> Result { + let req = WaitRequest { timeout_seconds }; + self.post(&format!("/api/v1/mesh/supervisor/tasks/{}/wait", task_id), &req) + .await + } + + /// Read a file from a task's worktree. + pub async fn supervisor_read_file( + &self, + task_id: Uuid, + file_path: &str, + ) -> Result { + let req = ReadFileRequest { + file_path: file_path.to_string(), + }; + self.post(&format!("/api/v1/mesh/supervisor/tasks/{}/read-file", task_id), &req) + .await + } + + /// Create a new branch. + pub async fn supervisor_branch( + &self, + branch_name: &str, + from_ref: Option, + ) -> Result { + let req = CreateBranchRequest { + branch_name: branch_name.to_string(), + from_ref, + }; + self.post("/api/v1/mesh/supervisor/branches", &req).await + } + + /// Merge a task's changes. + pub async fn supervisor_merge( + &self, + task_id: Uuid, + target_branch: Option, + squash: bool, + ) -> Result { + let req = MergeRequest { + squash, + target_branch, + }; + self.post(&format!("/api/v1/mesh/supervisor/tasks/{}/merge", task_id), &req) + .await + } + + /// Create a pull request. + pub async fn supervisor_pr( + &self, + task_id: Uuid, + title: &str, + body: &str, + base_branch: &str, + ) -> Result { + let req = CreatePrRequest { + task_id, + title: title.to_string(), + body: body.to_string(), + base_branch: base_branch.to_string(), + }; + self.post("/api/v1/mesh/supervisor/pr", &req).await + } + + /// Get task diff. + pub async fn supervisor_diff(&self, task_id: Uuid) -> Result { + self.get(&format!("/api/v1/mesh/supervisor/tasks/{}/diff", task_id)) + .await + } + + /// Create a checkpoint. + pub async fn supervisor_checkpoint( + &self, + task_id: Uuid, + message: &str, + ) -> Result { + let req = CheckpointRequest { + message: message.to_string(), + }; + self.post(&format!("/api/v1/mesh/tasks/{}/checkpoint", task_id), &req) + .await + } + + /// List checkpoints. + pub async fn supervisor_checkpoints(&self, task_id: Uuid) -> Result { + self.get(&format!("/api/v1/mesh/tasks/{}/checkpoints", task_id)) + .await + } + + /// Get contract status. + pub async fn supervisor_status(&self, contract_id: Uuid) -> Result { + self.get(&format!("/api/v1/contracts/{}/daemon/status", contract_id)) + .await + } +} -- cgit v1.2.3