summaryrefslogtreecommitdiff
path: root/makima/src/server/handlers/chains.rs
diff options
context:
space:
mode:
Diffstat (limited to 'makima/src/server/handlers/chains.rs')
-rw-r--r--makima/src/server/handlers/chains.rs62
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}