summaryrefslogtreecommitdiff
path: root/makima/src/server/handlers/directives.rs
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-08 12:32:53 +0000
committersoryu <soryu@soryu.co>2026-02-08 12:32:53 +0000
commit657a8e55796c9f0cc6f30937de545ed91f052063 (patch)
tree7944d9e3a4d9e38216fd6358f85d1636d2f75d1e /makima/src/server/handlers/directives.rs
parentf0a92073702d614302deff5e83c14ffec3ae6db0 (diff)
downloadsoryu-657a8e55796c9f0cc6f30937de545ed91f052063.tar.gz
soryu-657a8e55796c9f0cc6f30937de545ed91f052063.zip
Fixes for directive chain init
Diffstat (limited to 'makima/src/server/handlers/directives.rs')
-rw-r--r--makima/src/server/handlers/directives.rs61
1 files changed, 60 insertions, 1 deletions
diff --git a/makima/src/server/handlers/directives.rs b/makima/src/server/handlers/directives.rs
index 65f32d5..3f62a33 100644
--- a/makima/src/server/handlers/directives.rs
+++ b/makima/src/server/handlers/directives.rs
@@ -13,7 +13,7 @@ use std::collections::HashMap;
use crate::db::models::{
ChainStep, ChainStepWithContract, ChainWithSteps, CreateDirectiveRequest, Directive,
DirectiveChain, DirectiveListResponse, DirectiveWithChains, EvaluationListResponse,
- StepContractSummary, UpdateDirectiveRequest,
+ StepContractSummary, SubmitPlanRequest, UpdateDirectiveRequest,
};
use crate::db::repository::{self, RepositoryError};
use crate::orchestration;
@@ -724,3 +724,62 @@ pub async fn list_evaluations(
}
}
}
+
+/// 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()
+ }
+ }
+}