From 6a0c912a3fbd8e9b3e87ef40e960803d819d966d Mon Sep 17 00:00:00 2001 From: soryu Date: Thu, 5 Feb 2026 01:42:59 +0000 Subject: Add makima directives --- makima/src/server/handlers/chains.rs | 62 +++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) (limited to 'makima/src/server/handlers/chains.rs') diff --git a/makima/src/server/handlers/chains.rs b/makima/src/server/handlers/chains.rs index 9b32495..b8716ca 100644 --- a/makima/src/server/handlers/chains.rs +++ b/makima/src/server/handlers/chains.rs @@ -16,7 +16,8 @@ use crate::db::models::{ AddChainRepositoryRequest, AddContractDefinitionRequest, ChainContractDefinition, ChainContractDetail, ChainDefinitionGraphResponse, ChainEditorData, ChainEvent, ChainGraphResponse, ChainRepository, ChainSummary, ChainWithContracts, CreateChainRequest, - StartChainRequest, StartChainResponse, UpdateChainRequest, UpdateContractDefinitionRequest, + InitChainRequest, InitChainResponse, StartChainRequest, StartChainResponse, UpdateChainRequest, + UpdateContractDefinitionRequest, }; use crate::db::repository::{self, RepositoryError}; use crate::server::auth::Authenticated; @@ -172,6 +173,65 @@ pub async fn create_chain( } } +/// Initialize a directive-driven chain. +/// +/// Creates a directive contract that will research, plan, create, and orchestrate +/// a chain of contracts to accomplish the given goal. The directive contract goes +/// through Research -> Specify -> Plan -> Execute -> Review phases. +/// +/// POST /api/v1/chains/init +#[utoipa::path( + post, + path = "/api/v1/chains/init", + request_body = InitChainRequest, + responses( + (status = 201, description = "Directive chain initialized", body = InitChainResponse), + (status = 400, description = "Invalid request", body = ApiError), + (status = 401, description = "Unauthorized", body = ApiError), + (status = 503, description = "Database not configured", body = ApiError), + (status = 500, description = "Internal server error", body = ApiError) + ), + security( + ("bearer_auth" = []), + ("api_key" = []) + ), + tag = "Chains" +)] +pub async fn init_chain( + State(state): State, + Authenticated(auth): Authenticated, + Json(req): Json, +) -> impl IntoResponse { + let Some(ref pool) = state.db_pool else { + return ( + StatusCode::SERVICE_UNAVAILABLE, + Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), + ) + .into_response(); + }; + + // Validate the request + if req.goal.trim().is_empty() { + return ( + StatusCode::BAD_REQUEST, + Json(ApiError::new("VALIDATION_ERROR", "Goal cannot be empty")), + ) + .into_response(); + } + + match repository::init_chain_for_owner(pool, auth.owner_id, req).await { + Ok(response) => (StatusCode::CREATED, Json(response)).into_response(), + Err(e) => { + tracing::error!("Failed to initialize directive chain: {}", e); + ( + StatusCode::INTERNAL_SERVER_ERROR, + Json(ApiError::new("DB_ERROR", e.to_string())), + ) + .into_response() + } + } +} + /// Get a chain by ID. /// /// GET /api/v1/chains/{id} -- cgit v1.2.3