diff options
Diffstat (limited to 'makima/src/daemon/api')
| -rw-r--r-- | makima/src/daemon/api/chain.rs | 78 | ||||
| -rw-r--r-- | makima/src/daemon/api/directive.rs | 285 | ||||
| -rw-r--r-- | makima/src/daemon/api/mod.rs | 1 |
3 files changed, 285 insertions, 79 deletions
diff --git a/makima/src/daemon/api/chain.rs b/makima/src/daemon/api/chain.rs deleted file mode 100644 index c37c980..0000000 --- a/makima/src/daemon/api/chain.rs +++ /dev/null @@ -1,78 +0,0 @@ -//! Chain API methods. - -use uuid::Uuid; - -use super::client::{ApiClient, ApiError}; -use super::supervisor::JsonValue; -use crate::db::models::CreateChainRequest; - -impl ApiClient { - /// Create a new chain with contracts. - pub async fn create_chain(&self, req: CreateChainRequest) -> Result<JsonValue, ApiError> { - self.post("/api/v1/chains", &req).await - } - - /// List all chains for the authenticated user. - pub async fn list_chains( - &self, - status: Option<&str>, - limit: i32, - ) -> Result<JsonValue, ApiError> { - let mut params = Vec::new(); - if let Some(s) = status { - params.push(format!("status={}", s)); - } - params.push(format!("limit={}", limit)); - let query_string = format!("?{}", params.join("&")); - self.get(&format!("/api/v1/chains{}", query_string)).await - } - - /// Get a chain by ID. - pub async fn get_chain(&self, chain_id: Uuid) -> Result<JsonValue, ApiError> { - self.get(&format!("/api/v1/chains/{}", chain_id)).await - } - - /// Get contracts in a chain. - pub async fn get_chain_contracts(&self, chain_id: Uuid) -> Result<JsonValue, ApiError> { - self.get(&format!("/api/v1/chains/{}/contracts", chain_id)) - .await - } - - /// Get chain DAG structure for visualization. - pub async fn get_chain_graph(&self, chain_id: Uuid) -> Result<JsonValue, ApiError> { - self.get(&format!("/api/v1/chains/{}/graph", chain_id)) - .await - } - - /// Archive a chain. - pub async fn archive_chain(&self, chain_id: Uuid) -> Result<JsonValue, ApiError> { - self.delete_with_response(&format!("/api/v1/chains/{}", chain_id)) - .await - } - - /// Start a chain (creates root contracts and optionally a supervisor). - pub async fn start_chain(&self, chain_id: Uuid) -> Result<JsonValue, ApiError> { - self.post_empty(&format!("/api/v1/chains/{}/start", chain_id)) - .await - } - - /// Start a chain with supervisor enabled. - pub async fn start_chain_with_supervisor( - &self, - chain_id: Uuid, - repository_url: Option<&str>, - ) -> Result<JsonValue, ApiError> { - #[derive(serde::Serialize)] - #[serde(rename_all = "camelCase")] - struct StartRequest<'a> { - with_supervisor: bool, - repository_url: Option<&'a str>, - } - let req = StartRequest { - with_supervisor: true, - repository_url, - }; - self.post(&format!("/api/v1/chains/{}/start", chain_id), &req) - .await - } -} diff --git a/makima/src/daemon/api/directive.rs b/makima/src/daemon/api/directive.rs index 5281d21..48762d6 100644 --- a/makima/src/daemon/api/directive.rs +++ b/makima/src/daemon/api/directive.rs @@ -159,4 +159,289 @@ impl ApiClient { ) .await } + + // ========================================================================= + // Chain operations + // ========================================================================= + + /// Force chain regeneration (replan). + pub async fn replan_directive_chain( + &self, + directive_id: Uuid, + ) -> Result<JsonValue, ApiError> { + self.post_empty(&format!( + "/api/v1/directives/{}/chain/replan", + directive_id + )) + .await + } + + // ========================================================================= + // Step management + // ========================================================================= + + /// Add a step to a directive's chain. + pub async fn add_directive_step( + &self, + directive_id: Uuid, + name: &str, + description: Option<&str>, + step_type: Option<&str>, + depends_on: Option<Vec<Uuid>>, + ) -> Result<JsonValue, ApiError> { + #[derive(serde::Serialize)] + #[serde(rename_all = "camelCase")] + struct AddStepReq<'a> { + name: &'a str, + #[serde(skip_serializing_if = "Option::is_none")] + description: Option<&'a str>, + #[serde(skip_serializing_if = "Option::is_none")] + step_type: Option<&'a str>, + #[serde(skip_serializing_if = "Option::is_none")] + depends_on: Option<Vec<Uuid>>, + } + let req = AddStepReq { + name, + description, + step_type, + depends_on, + }; + self.post( + &format!("/api/v1/directives/{}/chain/steps", directive_id), + &req, + ) + .await + } + + /// Get a step by ID. + pub async fn get_directive_step( + &self, + directive_id: Uuid, + step_id: Uuid, + ) -> Result<JsonValue, ApiError> { + self.get(&format!( + "/api/v1/directives/{}/chain/steps/{}", + directive_id, step_id + )) + .await + } + + /// Update a step. + pub async fn update_directive_step( + &self, + directive_id: Uuid, + step_id: Uuid, + update: serde_json::Value, + ) -> Result<JsonValue, ApiError> { + self.put( + &format!( + "/api/v1/directives/{}/chain/steps/{}", + directive_id, step_id + ), + &update, + ) + .await + } + + /// Delete a step. + pub async fn delete_directive_step( + &self, + directive_id: Uuid, + step_id: Uuid, + ) -> Result<(), ApiError> { + self.delete(&format!( + "/api/v1/directives/{}/chain/steps/{}", + directive_id, step_id + )) + .await + } + + /// Skip a step. + pub async fn skip_directive_step( + &self, + directive_id: Uuid, + step_id: Uuid, + ) -> Result<JsonValue, ApiError> { + self.post_empty(&format!( + "/api/v1/directives/{}/chain/steps/{}/skip", + directive_id, step_id + )) + .await + } + + /// Force re-evaluation of a step. + pub async fn evaluate_directive_step( + &self, + directive_id: Uuid, + step_id: Uuid, + ) -> Result<JsonValue, ApiError> { + self.post_empty(&format!( + "/api/v1/directives/{}/chain/steps/{}/evaluate", + directive_id, step_id + )) + .await + } + + /// Trigger manual rework for a step. + pub async fn rework_directive_step( + &self, + directive_id: Uuid, + step_id: Uuid, + instructions: Option<&str>, + ) -> Result<JsonValue, ApiError> { + #[derive(serde::Serialize)] + #[serde(rename_all = "camelCase")] + struct ReworkReq<'a> { + instructions: Option<&'a str>, + } + let req = ReworkReq { instructions }; + self.post( + &format!( + "/api/v1/directives/{}/chain/steps/{}/rework", + directive_id, step_id + ), + &req, + ) + .await + } + + // ========================================================================= + // Evaluations + // ========================================================================= + + /// List evaluations for a directive. + pub async fn list_directive_evaluations( + &self, + directive_id: Uuid, + ) -> Result<JsonValue, ApiError> { + self.get(&format!( + "/api/v1/directives/{}/evaluations", + directive_id + )) + .await + } + + // ========================================================================= + // Verifiers + // ========================================================================= + + /// List verifiers for a directive. + pub async fn list_directive_verifiers( + &self, + directive_id: Uuid, + ) -> Result<JsonValue, ApiError> { + self.get(&format!("/api/v1/directives/{}/verifiers", directive_id)) + .await + } + + /// Add a verifier to a directive. + pub async fn add_directive_verifier( + &self, + directive_id: Uuid, + name: &str, + verifier_type: &str, + command: Option<&str>, + ) -> Result<JsonValue, ApiError> { + #[derive(serde::Serialize)] + #[serde(rename_all = "camelCase")] + struct CreateVerifierReq<'a> { + name: &'a str, + verifier_type: &'a str, + #[serde(skip_serializing_if = "Option::is_none")] + command: Option<&'a str>, + } + let req = CreateVerifierReq { + name, + verifier_type, + command, + }; + self.post( + &format!("/api/v1/directives/{}/verifiers", directive_id), + &req, + ) + .await + } + + /// Update a verifier. + pub async fn update_directive_verifier( + &self, + directive_id: Uuid, + verifier_id: Uuid, + update: serde_json::Value, + ) -> Result<JsonValue, ApiError> { + self.put( + &format!( + "/api/v1/directives/{}/verifiers/{}", + directive_id, verifier_id + ), + &update, + ) + .await + } + + /// Auto-detect verifiers based on repository content. + pub async fn auto_detect_directive_verifiers( + &self, + directive_id: Uuid, + ) -> Result<JsonValue, ApiError> { + self.post_empty(&format!( + "/api/v1/directives/{}/verifiers/auto-detect", + directive_id + )) + .await + } + + // ========================================================================= + // Requirements & Spec + // ========================================================================= + + /// Update directive requirements. + pub async fn update_directive_requirements( + &self, + directive_id: Uuid, + requirements: serde_json::Value, + ) -> Result<JsonValue, ApiError> { + #[derive(serde::Serialize)] + #[serde(rename_all = "camelCase")] + struct UpdateReq { + requirements: serde_json::Value, + } + let req = UpdateReq { requirements }; + self.put( + &format!("/api/v1/directives/{}/requirements", directive_id), + &req, + ) + .await + } + + /// Update directive acceptance criteria. + pub async fn update_directive_criteria( + &self, + directive_id: Uuid, + acceptance_criteria: serde_json::Value, + ) -> Result<JsonValue, ApiError> { + #[derive(serde::Serialize)] + #[serde(rename_all = "camelCase")] + struct UpdateReq { + acceptance_criteria: serde_json::Value, + } + let req = UpdateReq { acceptance_criteria }; + self.put( + &format!("/api/v1/directives/{}/criteria", directive_id), + &req, + ) + .await + } + + /// Generate a specification from the directive's goal. + pub async fn generate_directive_spec( + &self, + directive_id: Uuid, + ) -> Result<JsonValue, ApiError> { + self.post_empty(&format!( + "/api/v1/directives/{}/generate-spec", + directive_id + )) + .await + } } diff --git a/makima/src/daemon/api/mod.rs b/makima/src/daemon/api/mod.rs index f1f52d0..2d1efbf 100644 --- a/makima/src/daemon/api/mod.rs +++ b/makima/src/daemon/api/mod.rs @@ -1,6 +1,5 @@ //! HTTP API client for makima CLI commands. -pub mod chain; pub mod client; pub mod contract; pub mod directive; |
