summaryrefslogtreecommitdiff
path: root/makima/src/daemon/api/supervisor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'makima/src/daemon/api/supervisor.rs')
-rw-r--r--makima/src/daemon/api/supervisor.rs186
1 files changed, 186 insertions, 0 deletions
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<Uuid>,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub checkpoint_sha: Option<String>,
+}
+
+#[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<String>,
+}
+
+#[derive(Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct MergeRequest {
+ pub squash: bool,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub target_branch: Option<String>,
+}
+
+#[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<JsonValue, ApiError> {
+ 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<JsonValue, ApiError> {
+ 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<JsonValue, ApiError> {
+ 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<JsonValue, ApiError> {
+ 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<JsonValue, ApiError> {
+ 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<String>,
+ ) -> Result<JsonValue, ApiError> {
+ 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<String>,
+ squash: bool,
+ ) -> Result<JsonValue, ApiError> {
+ 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<JsonValue, ApiError> {
+ 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<JsonValue, ApiError> {
+ 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<JsonValue, ApiError> {
+ 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<JsonValue, ApiError> {
+ self.get(&format!("/api/v1/mesh/tasks/{}/checkpoints", task_id))
+ .await
+ }
+
+ /// Get contract status.
+ pub async fn supervisor_status(&self, contract_id: Uuid) -> Result<JsonValue, ApiError> {
+ self.get(&format!("/api/v1/contracts/{}/daemon/status", contract_id))
+ .await
+ }
+}