diff options
Diffstat (limited to 'makima/src/server/handlers/chains.rs')
| -rw-r--r-- | makima/src/server/handlers/chains.rs | 62 |
1 files changed, 61 insertions, 1 deletions
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<SharedState>, + Authenticated(auth): Authenticated, + Json(req): Json<InitChainRequest>, +) -> 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} |
