summaryrefslogtreecommitdiff
path: root/makima/src/server/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'makima/src/server/handlers')
-rw-r--r--makima/src/server/handlers/contracts.rs18
-rw-r--r--makima/src/server/handlers/directives.rs785
-rw-r--r--makima/src/server/handlers/mesh_daemon.rs10
-rw-r--r--makima/src/server/handlers/mod.rs1
4 files changed, 0 insertions, 814 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;