diff options
Diffstat (limited to 'makima/src/server')
| -rw-r--r-- | makima/src/server/handlers/contracts.rs | 18 | ||||
| -rw-r--r-- | makima/src/server/handlers/directives.rs | 785 | ||||
| -rw-r--r-- | makima/src/server/handlers/mesh_daemon.rs | 10 | ||||
| -rw-r--r-- | makima/src/server/handlers/mod.rs | 1 | ||||
| -rw-r--r-- | makima/src/server/mod.rs | 19 | ||||
| -rw-r--r-- | makima/src/server/openapi.rs | 44 |
6 files changed, 8 insertions, 869 deletions
diff --git a/makima/src/server/handlers/contracts.rs b/makima/src/server/handlers/contracts.rs index ad0a1ff..dc15923 100644 --- a/makima/src/server/handlers/contracts.rs +++ b/makima/src/server/handlers/contracts.rs @@ -575,24 +575,6 @@ pub async fn update_contract( }), ).await; - // Directive engine integration — process planning/step/monitoring completion - if contract.is_directive_orchestrator || contract.directive_id.is_some() { - let pool_clone = pool.clone(); - let state_clone = state.clone(); - let contract_clone = contract.clone(); - let owner = auth.owner_id; - tokio::spawn(async move { - if let Err(e) = crate::orchestration::directive::on_contract_completed( - &pool_clone, &state_clone, &contract_clone, owner, - ).await { - tracing::warn!( - contract_id = %contract_clone.id, - error = %e, - "Failed to process directive contract completion" - ); - } - }); - } } // Get summary with counts diff --git a/makima/src/server/handlers/directives.rs b/makima/src/server/handlers/directives.rs deleted file mode 100644 index 3f62a33..0000000 --- a/makima/src/server/handlers/directives.rs +++ /dev/null @@ -1,785 +0,0 @@ -//! HTTP handlers for directive CRUD operations. - -use axum::{ - extract::{Path, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use uuid::Uuid; - -use std::collections::HashMap; - -use crate::db::models::{ - ChainStep, ChainStepWithContract, ChainWithSteps, CreateDirectiveRequest, Directive, - DirectiveChain, DirectiveListResponse, DirectiveWithChains, EvaluationListResponse, - StepContractSummary, SubmitPlanRequest, UpdateDirectiveRequest, -}; -use crate::db::repository::{self, RepositoryError}; -use crate::orchestration; -use crate::server::auth::Authenticated; -use crate::server::messages::ApiError; -use crate::server::state::SharedState; - -/// List all directives for the authenticated user's owner. -#[utoipa::path( - get, - path = "/api/v1/directives", - responses( - (status = 200, description = "List of directives", body = DirectiveListResponse), - (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 = "Directives" -)] -pub async fn list_directives( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - match repository::list_directives_for_owner(pool, auth.owner_id).await { - Ok(directives) => { - let total = directives.len() as i64; - Json(DirectiveListResponse { directives, total }).into_response() - } - Err(e) => { - tracing::error!("Failed to list directives: {}", e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("DB_ERROR", e.to_string())), - ) - .into_response() - } - } -} - -/// Get a directive by ID with its chains. -#[utoipa::path( - get, - path = "/api/v1/directives/{id}", - params( - ("id" = Uuid, Path, description = "Directive ID") - ), - responses( - (status = 200, description = "Directive details with chains", body = DirectiveWithChains), - (status = 401, description = "Unauthorized", body = ApiError), - (status = 404, description = "Directive not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - (status = 500, description = "Internal server error", body = ApiError), - ), - security( - ("bearer_auth" = []), - ("api_key" = []) - ), - tag = "Directives" -)] -pub async fn get_directive( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path(id): Path<Uuid>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - let directive = match repository::get_directive_for_owner(pool, id, auth.owner_id).await { - Ok(Some(d)) => d, - Ok(None) => { - return ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Directive not found")), - ) - .into_response(); - } - Err(e) => { - tracing::error!("Failed to get directive {}: {}", id, e); - return ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("DB_ERROR", e.to_string())), - ) - .into_response(); - } - }; - - let chains = match repository::list_chains_for_directive(pool, id).await { - Ok(c) => c, - Err(e) => { - tracing::warn!("Failed to get chains for directive {}: {}", id, e); - Vec::new() - } - }; - - // Build chains with steps - let mut all_steps_by_chain = Vec::new(); - for chain in &chains { - let steps = match repository::list_steps_for_chain(pool, chain.id).await { - Ok(s) => s, - Err(e) => { - tracing::warn!("Failed to get steps for chain {}: {}", chain.id, e); - Vec::new() - } - }; - all_steps_by_chain.push(steps); - } - - // Collect all contract IDs (from steps + orchestrator) - let mut contract_ids: Vec<Uuid> = all_steps_by_chain - .iter() - .flat_map(|steps| steps.iter().filter_map(|s| s.contract_id)) - .collect(); - if let Some(orch_id) = directive.orchestrator_contract_id { - contract_ids.push(orch_id); - } - - // Batch fetch contract summaries - let mut summary_map: HashMap<Uuid, StepContractSummary> = if contract_ids.is_empty() { - HashMap::new() - } else { - match repository::get_contract_summaries_batch(pool, &contract_ids).await { - Ok(summaries) => summaries.into_iter().map(|s| (s.id, s)).collect(), - Err(e) => { - tracing::warn!("Failed to fetch contract summaries: {}", e); - HashMap::new() - } - } - }; - - // Build enriched chains - let chains_with_steps: Vec<ChainWithSteps> = chains - .into_iter() - .zip(all_steps_by_chain.into_iter()) - .map(|(chain, steps)| { - let enriched_steps = steps - .into_iter() - .map(|step| { - let contract_summary = - step.contract_id.and_then(|id| summary_map.remove(&id)); - ChainStepWithContract { - step, - contract_summary, - } - }) - .collect(); - ChainWithSteps { - chain, - steps: enriched_steps, - } - }) - .collect(); - - let orchestrator_contract_summary = directive - .orchestrator_contract_id - .and_then(|id| summary_map.remove(&id)); - - Json(DirectiveWithChains { - directive, - orchestrator_contract_summary, - chains: chains_with_steps, - }) - .into_response() -} - -/// Create a new directive. -#[utoipa::path( - post, - path = "/api/v1/directives", - request_body = CreateDirectiveRequest, - responses( - (status = 201, description = "Directive created", body = Directive), - (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 = "Directives" -)] -pub async fn create_directive( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Json(req): Json<CreateDirectiveRequest>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - match repository::create_directive_for_owner(pool, auth.owner_id, req).await { - Ok(directive) => (StatusCode::CREATED, Json(directive)).into_response(), - Err(e) => { - tracing::error!("Failed to create directive: {}", e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("DB_ERROR", e.to_string())), - ) - .into_response() - } - } -} - -/// Update an existing directive. -#[utoipa::path( - put, - path = "/api/v1/directives/{id}", - params( - ("id" = Uuid, Path, description = "Directive ID") - ), - request_body = UpdateDirectiveRequest, - responses( - (status = 200, description = "Directive updated", body = Directive), - (status = 401, description = "Unauthorized", body = ApiError), - (status = 404, description = "Directive not found", body = ApiError), - (status = 409, description = "Version conflict", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - (status = 500, description = "Internal server error", body = ApiError), - ), - security( - ("bearer_auth" = []), - ("api_key" = []) - ), - tag = "Directives" -)] -pub async fn update_directive( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path(id): Path<Uuid>, - Json(req): Json<UpdateDirectiveRequest>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - match repository::update_directive_for_owner(pool, id, auth.owner_id, req).await { - Ok(Some(directive)) => Json(directive).into_response(), - Ok(None) => ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Directive not found")), - ) - .into_response(), - Err(RepositoryError::VersionConflict { expected, actual }) => ( - StatusCode::CONFLICT, - Json(ApiError::new( - "VERSION_CONFLICT", - format!( - "Version conflict: expected {}, actual {}", - expected, actual - ), - )), - ) - .into_response(), - Err(RepositoryError::Database(e)) => { - tracing::error!("Failed to update directive {}: {}", id, e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("DB_ERROR", e.to_string())), - ) - .into_response() - } - } -} - -/// Delete a directive. -#[utoipa::path( - delete, - path = "/api/v1/directives/{id}", - params( - ("id" = Uuid, Path, description = "Directive ID") - ), - responses( - (status = 204, description = "Directive deleted"), - (status = 401, description = "Unauthorized", body = ApiError), - (status = 404, description = "Directive not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - (status = 500, description = "Internal server error", body = ApiError), - ), - security( - ("bearer_auth" = []), - ("api_key" = []) - ), - tag = "Directives" -)] -pub async fn delete_directive( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path(id): Path<Uuid>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - match repository::delete_directive_for_owner(pool, id, auth.owner_id).await { - Ok(true) => StatusCode::NO_CONTENT.into_response(), - Ok(false) => ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Directive not found")), - ) - .into_response(), - Err(e) => { - tracing::error!("Failed to delete directive {}: {}", id, e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("DB_ERROR", e.to_string())), - ) - .into_response() - } - } -} - -/// List chains for a directive. -#[utoipa::path( - get, - path = "/api/v1/directives/{id}/chains", - params( - ("id" = Uuid, Path, description = "Directive ID") - ), - responses( - (status = 200, description = "List of chains", body = Vec<DirectiveChain>), - (status = 401, description = "Unauthorized", body = ApiError), - (status = 404, description = "Directive not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - (status = 500, description = "Internal server error", body = ApiError), - ), - security( - ("bearer_auth" = []), - ("api_key" = []) - ), - tag = "Directives" -)] -pub async fn list_chains( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path(id): Path<Uuid>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - // Verify directive exists and belongs to owner - match repository::get_directive_for_owner(pool, id, auth.owner_id).await { - Ok(Some(_)) => {} - Ok(None) => { - return ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Directive not found")), - ) - .into_response(); - } - Err(e) => { - tracing::error!("Failed to get directive {}: {}", id, e); - return ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("DB_ERROR", e.to_string())), - ) - .into_response(); - } - } - - match repository::list_chains_for_directive(pool, id).await { - Ok(chains) => Json(chains).into_response(), - Err(e) => { - tracing::error!("Failed to list chains for directive {}: {}", id, e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("DB_ERROR", e.to_string())), - ) - .into_response() - } - } -} - -/// Get a chain with its steps. -#[utoipa::path( - get, - path = "/api/v1/directives/{id}/chains/{chain_id}", - params( - ("id" = Uuid, Path, description = "Directive ID"), - ("chain_id" = Uuid, Path, description = "Chain ID") - ), - responses( - (status = 200, description = "Chain with steps", body = ChainWithSteps), - (status = 401, description = "Unauthorized", body = ApiError), - (status = 404, description = "Chain not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - (status = 500, description = "Internal server error", body = ApiError), - ), - security( - ("bearer_auth" = []), - ("api_key" = []) - ), - tag = "Directives" -)] -pub async fn get_chain( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path((id, chain_id)): Path<(Uuid, Uuid)>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - // Verify directive exists and belongs to owner - match repository::get_directive_for_owner(pool, id, auth.owner_id).await { - Ok(Some(_)) => {} - Ok(None) => { - return ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Directive not found")), - ) - .into_response(); - } - Err(e) => { - tracing::error!("Failed to get directive {}: {}", id, e); - return ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("DB_ERROR", e.to_string())), - ) - .into_response(); - } - } - - // Get the chain and verify it belongs to this directive - let chains = match repository::list_chains_for_directive(pool, id).await { - Ok(c) => c, - Err(e) => { - tracing::error!("Failed to list chains: {}", e); - return ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("DB_ERROR", e.to_string())), - ) - .into_response(); - } - }; - - let chain = match chains.into_iter().find(|c| c.id == chain_id) { - Some(c) => c, - None => { - return ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Chain not found")), - ) - .into_response(); - } - }; - - let steps = match repository::list_steps_for_chain(pool, chain_id).await { - Ok(s) => s, - Err(e) => { - tracing::warn!("Failed to get steps for chain {}: {}", chain_id, e); - Vec::new() - } - }; - - // Collect contract IDs from steps - let contract_ids: Vec<Uuid> = steps.iter().filter_map(|s| s.contract_id).collect(); - - let mut summary_map: HashMap<Uuid, StepContractSummary> = if contract_ids.is_empty() { - HashMap::new() - } else { - match repository::get_contract_summaries_batch(pool, &contract_ids).await { - Ok(summaries) => summaries.into_iter().map(|s| (s.id, s)).collect(), - Err(e) => { - tracing::warn!("Failed to fetch contract summaries: {}", e); - HashMap::new() - } - } - }; - - let enriched_steps = steps - .into_iter() - .map(|step| { - let contract_summary = step.contract_id.and_then(|id| summary_map.remove(&id)); - ChainStepWithContract { - step, - contract_summary, - } - }) - .collect(); - - Json(ChainWithSteps { - chain, - steps: enriched_steps, - }) - .into_response() -} - -/// Start a directive: create a planning contract and begin orchestration. -#[utoipa::path( - post, - path = "/api/v1/directives/{id}/start", - params( - ("id" = Uuid, Path, description = "Directive ID") - ), - responses( - (status = 200, description = "Directive started", body = Directive), - (status = 400, description = "Directive not in draft status", body = ApiError), - (status = 401, description = "Unauthorized", body = ApiError), - (status = 404, description = "Directive not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - (status = 500, description = "Internal server error", body = ApiError), - ), - security( - ("bearer_auth" = []), - ("api_key" = []) - ), - tag = "Directives" -)] -pub async fn start_directive( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path(id): Path<Uuid>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - match orchestration::directive::init_directive(pool, &state, auth.owner_id, id).await { - Ok(directive) => Json(directive).into_response(), - Err(e) if e.contains("not found") => ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", e)), - ) - .into_response(), - Err(e) if e.contains("must be in 'draft'") => ( - StatusCode::BAD_REQUEST, - Json(ApiError::new("INVALID_STATUS", e)), - ) - .into_response(), - Err(e) => { - tracing::error!("Failed to start directive {}: {}", id, e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("START_FAILED", e)), - ) - .into_response() - } - } -} - -/// Trigger a manual evaluation for a step. -#[utoipa::path( - post, - path = "/api/v1/directives/{id}/steps/{step_id}/evaluate", - params( - ("id" = Uuid, Path, description = "Directive ID"), - ("step_id" = Uuid, Path, description = "Step ID") - ), - responses( - (status = 200, description = "Evaluation triggered", body = ChainStep), - (status = 400, description = "Step cannot be evaluated", body = ApiError), - (status = 401, description = "Unauthorized", body = ApiError), - (status = 404, description = "Not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - (status = 500, description = "Internal server error", body = ApiError), - ), - security( - ("bearer_auth" = []), - ("api_key" = []) - ), - tag = "Directives" -)] -pub async fn evaluate_step( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path((id, step_id)): Path<(Uuid, Uuid)>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - match orchestration::directive::trigger_manual_evaluation(pool, &state, auth.owner_id, id, step_id).await { - Ok(step) => Json(step).into_response(), - Err(e) if e.contains("not found") || e.contains("Not found") => ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", e)), - ) - .into_response(), - Err(e) if e.contains("hasn't been executed") || e.contains("no active chain") => ( - StatusCode::BAD_REQUEST, - Json(ApiError::new("INVALID_STATE", e)), - ) - .into_response(), - Err(e) => { - tracing::error!("Failed to trigger evaluation for step {}: {}", step_id, e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("EVALUATION_FAILED", e)), - ) - .into_response() - } - } -} - -/// List evaluations for a step. -#[utoipa::path( - get, - path = "/api/v1/directives/{id}/steps/{step_id}/evaluations", - params( - ("id" = Uuid, Path, description = "Directive ID"), - ("step_id" = Uuid, Path, description = "Step ID") - ), - responses( - (status = 200, description = "List of evaluations", body = EvaluationListResponse), - (status = 401, description = "Unauthorized", body = ApiError), - (status = 404, description = "Not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - (status = 500, description = "Internal server error", body = ApiError), - ), - security( - ("bearer_auth" = []), - ("api_key" = []) - ), - tag = "Directives" -)] -pub async fn list_evaluations( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path((id, step_id)): Path<(Uuid, Uuid)>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - // Verify directive exists and belongs to owner - match repository::get_directive_for_owner(pool, id, auth.owner_id).await { - Ok(Some(_)) => {} - Ok(None) => { - return ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", "Directive not found")), - ) - .into_response(); - } - Err(e) => { - tracing::error!("Failed to get directive {}: {}", id, e); - return ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("DB_ERROR", e.to_string())), - ) - .into_response(); - } - } - - match repository::list_evaluations_for_step(pool, step_id).await { - Ok(evaluations) => { - let total = evaluations.len() as i64; - Json(EvaluationListResponse { evaluations, total }).into_response() - } - Err(e) => { - tracing::error!("Failed to list evaluations for step {}: {}", step_id, e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("DB_ERROR", e.to_string())), - ) - .into_response() - } - } -} - -/// Submit a chain plan for a directive. -#[utoipa::path( - post, - path = "/api/v1/directives/{id}/submit-plan", - params( - ("id" = Uuid, Path, description = "Directive ID") - ), - request_body = SubmitPlanRequest, - responses( - (status = 200, description = "Plan submitted, directive active", body = Directive), - (status = 400, description = "Invalid request or status", body = ApiError), - (status = 401, description = "Unauthorized", body = ApiError), - (status = 404, description = "Directive not found", body = ApiError), - (status = 503, description = "Database not configured", body = ApiError), - (status = 500, description = "Internal server error", body = ApiError), - ), - security( - ("bearer_auth" = []), - ("api_key" = []) - ), - tag = "Directives" -)] -pub async fn submit_plan( - State(state): State<SharedState>, - Authenticated(auth): Authenticated, - Path(id): Path<Uuid>, - Json(req): Json<SubmitPlanRequest>, -) -> impl IntoResponse { - let Some(ref pool) = state.db_pool else { - return ( - StatusCode::SERVICE_UNAVAILABLE, - Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")), - ) - .into_response(); - }; - - match orchestration::directive::submit_plan(pool, &state, auth.owner_id, id, &req.plan).await { - Ok(directive) => Json(directive).into_response(), - Err(e) if e.contains("not found") || e.contains("Not found") => ( - StatusCode::NOT_FOUND, - Json(ApiError::new("NOT_FOUND", e)), - ) - .into_response(), - Err(e) if e.contains("must be in 'planning'") || e.contains("no steps") => ( - StatusCode::BAD_REQUEST, - Json(ApiError::new("INVALID_REQUEST", e)), - ) - .into_response(), - Err(e) => { - tracing::error!("Failed to submit plan for directive {}: {}", id, e); - ( - StatusCode::INTERNAL_SERVER_ERROR, - Json(ApiError::new("SUBMIT_PLAN_FAILED", e)), - ) - .into_response() - } - } -} diff --git a/makima/src/server/handlers/mesh_daemon.rs b/makima/src/server/handlers/mesh_daemon.rs index 767d059..87b5e44 100644 --- a/makima/src/server/handlers/mesh_daemon.rs +++ b/makima/src/server/handlers/mesh_daemon.rs @@ -1303,16 +1303,6 @@ async fn handle_daemon_connection(socket: WebSocket, state: SharedState, auth_re }), ).await; - // Directive engine integration - if let Err(e) = crate::orchestration::directive::on_task_completed( - &pool, &state, &updated_task, owner_id, - ).await { - tracing::warn!( - task_id = %task_id, - error = %e, - "Failed to process directive task completion" - ); - } } Ok(None) => { tracing::warn!( diff --git a/makima/src/server/handlers/mod.rs b/makima/src/server/handlers/mod.rs index 29cd09f..ae370c9 100644 --- a/makima/src/server/handlers/mod.rs +++ b/makima/src/server/handlers/mod.rs @@ -6,7 +6,6 @@ pub mod contract_chat; pub mod contract_daemon; pub mod contract_discuss; pub mod contracts; -pub mod directives; pub mod file_ws; pub mod files; pub mod history; diff --git a/makima/src/server/mod.rs b/makima/src/server/mod.rs index 0cad050..b7a4156 100644 --- a/makima/src/server/mod.rs +++ b/makima/src/server/mod.rs @@ -18,7 +18,7 @@ use tower_http::trace::TraceLayer; use utoipa::OpenApi; use utoipa_swagger_ui::SwaggerUi; -use crate::server::handlers::{api_keys, chat, contract_chat, contract_daemon, contract_discuss, contracts, directives, file_ws, files, history, listen, mesh, mesh_chat, mesh_daemon, mesh_merge, mesh_supervisor, mesh_ws, repository_history, speak, templates, transcript_analysis, users, versions}; +use crate::server::handlers::{api_keys, chat, contract_chat, contract_daemon, contract_discuss, contracts, file_ws, files, history, listen, mesh, mesh_chat, mesh_daemon, mesh_merge, mesh_supervisor, mesh_ws, repository_history, speak, templates, transcript_analysis, users, versions}; use crate::server::openapi::ApiDoc; use crate::server::state::SharedState; @@ -170,23 +170,6 @@ pub fn make_router(state: SharedState) -> Router { "/contracts/{id}/chat/history", get(contract_chat::get_contract_chat_history).delete(contract_chat::clear_contract_chat_history), ) - // Directive endpoints - .route( - "/directives", - get(directives::list_directives).post(directives::create_directive), - ) - .route( - "/directives/{id}", - get(directives::get_directive) - .put(directives::update_directive) - .delete(directives::delete_directive), - ) - .route("/directives/{id}/start", post(directives::start_directive)) - .route("/directives/{id}/chains", get(directives::list_chains)) - .route("/directives/{id}/chains/{chain_id}", get(directives::get_chain)) - .route("/directives/{id}/submit-plan", post(directives::submit_plan)) - .route("/directives/{id}/steps/{step_id}/evaluate", post(directives::evaluate_step)) - .route("/directives/{id}/steps/{step_id}/evaluations", get(directives::list_evaluations)) // Contract supervisor resume endpoints .route("/contracts/{id}/supervisor/resume", post(mesh_supervisor::resume_supervisor)) .route("/contracts/{id}/supervisor/conversation/rewind", post(mesh_supervisor::rewind_conversation)) diff --git a/makima/src/server/openapi.rs b/makima/src/server/openapi.rs index 888269f..0b6bfba 100644 --- a/makima/src/server/openapi.rs +++ b/makima/src/server/openapi.rs @@ -4,28 +4,27 @@ use utoipa::OpenApi; use crate::db::models::{ AddLocalRepositoryRequest, AddRemoteRepositoryRequest, BranchInfo, BranchListResponse, - BranchTaskRequest, BranchTaskResponse, ChainStep, ChainStepWithContract, ChainWithSteps, + BranchTaskRequest, BranchTaskResponse, ChangePhaseRequest, Contract, ContractChatHistoryResponse, ContractChatMessageRecord, ContractEvent, ContractListResponse, ContractRepository, ContractSummary, ContractWithRelations, - CreateContractRequest, CreateDirectiveRequest, CreateFileRequest, + CreateContractRequest, CreateFileRequest, CreateManagedRepositoryRequest, CreateTaskRequest, Daemon, DaemonDirectoriesResponse, - DaemonDirectory, DaemonListResponse, Directive, DirectiveChain, DirectiveEvaluation, - DirectiveEvent, DirectiveListResponse, DirectiveSummary, DirectiveWithChains, - EvaluationListResponse, File, FileListResponse, FileSummary, + DaemonDirectory, DaemonListResponse, + File, FileListResponse, FileSummary, MergeCommitRequest, MergeCompleteCheckResponse, MergeResolveRequest, MergeResultResponse, MergeSkipRequest, MergeStartRequest, MergeStatusResponse, MeshChatConversation, MeshChatHistoryResponse, MeshChatMessageRecord, RepositoryHistoryEntry, RepositoryHistoryListResponse, RepositorySuggestionsQuery, SendMessageRequest, - StepContractSummary, SubmitPlanRequest, Task, + Task, TaskEventListResponse, TaskListResponse, TaskSummary, TaskWithSubtasks, TranscriptEntry, - UpdateContractRequest, UpdateDirectiveRequest, UpdateFileRequest, UpdateTaskRequest, + UpdateContractRequest, UpdateFileRequest, UpdateTaskRequest, }; use crate::server::auth::{ ApiKey, ApiKeyInfoResponse, CreateApiKeyRequest, CreateApiKeyResponse, RefreshApiKeyRequest, RefreshApiKeyResponse, RevokeApiKeyResponse, }; -use crate::server::handlers::{api_keys, contract_chat, contract_discuss, contracts, directives, files, listen, mesh, mesh_chat, mesh_merge, repository_history, users}; +use crate::server::handlers::{api_keys, contract_chat, contract_discuss, contracts, files, listen, mesh, mesh_chat, mesh_merge, repository_history, users}; use crate::server::messages::{ApiError, AudioEncoding, StartMessage, StopMessage, TranscriptMessage}; #[derive(OpenApi)] @@ -108,18 +107,6 @@ use crate::server::messages::{ApiError, AudioEncoding, StartMessage, StopMessage repository_history::list_repository_history, repository_history::get_repository_suggestions, repository_history::delete_repository_history, - // Directive endpoints - directives::list_directives, - directives::get_directive, - directives::create_directive, - directives::update_directive, - directives::delete_directive, - directives::start_directive, - directives::list_chains, - directives::get_chain, - directives::evaluate_step, - directives::list_evaluations, - directives::submit_plan, ), components( schemas( @@ -204,22 +191,6 @@ use crate::server::messages::{ApiError, AudioEncoding, StartMessage, StopMessage RepositoryHistoryEntry, RepositoryHistoryListResponse, RepositorySuggestionsQuery, - // Directive schemas - Directive, - DirectiveSummary, - DirectiveListResponse, - DirectiveWithChains, - DirectiveChain, - ChainStep, - ChainStepWithContract, - ChainWithSteps, - StepContractSummary, - CreateDirectiveRequest, - UpdateDirectiveRequest, - SubmitPlanRequest, - DirectiveEvaluation, - DirectiveEvent, - EvaluationListResponse, ) ), tags( @@ -230,7 +201,6 @@ use crate::server::messages::{ApiError, AudioEncoding, StartMessage, StopMessage (name = "API Keys", description = "API key management for programmatic access"), (name = "Users", description = "User account management"), (name = "Settings", description = "User settings including repository history"), - (name = "Directives", description = "Directive management for autonomous goal-driven execution"), ) )] pub struct ApiDoc; |
