feat: complete Epic 1 production foundation

This commit is contained in:
2026-08-25 01:24:11 +03:00
parent 767428436d
commit 182bde8ac0
298 changed files with 35719 additions and 5299 deletions
@@ -9,16 +9,13 @@ use crank_core::{CorrelationContext, RequestId, TraceContext};
use crank_registry::{ApprovalRequestRecord, FinishApprovalRequest};
use crank_runtime::{RuntimeExecutionRequest, RuntimeRequestContext};
use crank_trace::{DbOperation, ErrorCategory, Stage, StageOutcome, observe_db_query};
use serde_json::json;
use serde_json::{Value, json};
use time::OffsetDateTime;
use tracing::{Instrument, warn};
use crate::{
app::{
AgentRoutePath, AppState, InvocationRecord, build_request_preview, persist_invocation,
resolve_operation_auth, runtime_operation,
},
tool_error::{runtime_error_code, safe_runtime_error_message},
use crate::app::{
AgentRoutePath, AppState, InvocationRecord, persist_invocation, resolve_operation_auth,
runtime_operation,
};
const RECOVERY_INTERVAL: std::time::Duration = std::time::Duration::from_secs(5);
@@ -184,11 +181,6 @@ pub(super) async fn execute_approved_request(
};
let operation = runtime_operation(&tool);
let request_preview = build_request_preview(
&state.runtime,
&operation,
&approval.approval.request_payload,
);
let started_at = Instant::now();
let runtime_request_context = RuntimeRequestContext::from_correlation(&correlation)
.with_response_cache_scope(
@@ -205,42 +197,86 @@ pub(super) async fn execute_approved_request(
resolve_operation_auth(state, &tool.workspace_id, &operation.execution_config).await;
let result = match resolved_auth {
Ok(resolved_auth) => {
state
.runtime
.execute_request(
RuntimeExecutionRequest::new(&operation, &approval.approval.request_payload)
.with_optional_auth(resolved_auth.as_ref())
.with_context(&runtime_request_context),
)
.await
match RuntimeExecutionRequest::try_new(
&tool.workspace_id,
crank_core::ExecutionOrigin::AgentSnapshot,
Some(&tool.agent_id),
&operation,
&approval.approval.request_payload,
crank_runtime::ExecutionAuthorization::Authorized,
resolved_auth.as_ref(),
&runtime_request_context,
Instant::now()
+ std::time::Duration::from_millis(
operation.execution_config.timeout_ms.max(1),
),
) {
Ok(request) => state.runtime.execute_outcome(request).await,
Err(_) => Err(crank_core::ExecutionFailure::new(
crank_core::ExecutionErrorCode::RuntimeInternal,
correlation.clone(),
)),
}
}
Err(error) => Err(error),
Err(error) => Err(crank_runtime::normalize_runtime_error(&error, &correlation)),
};
let (status, response_payload, invocation_status, invocation_level, message, error_kind) =
match result {
Ok(output) => (
let (
status,
response_payload,
invocation_status,
invocation_level,
message,
error_kind,
execution_stage,
execution_error_code,
retryability,
outcome_certainty,
upstream_status,
request_preview,
) = match result {
Ok(success) => {
let request_preview = success.request_preview;
(
ApprovalRequestStatus::Completed,
output,
success.output,
InvocationStatus::Ok,
InvocationLevel::Info,
"approved tool call completed",
None,
),
Err(error) => (
ApprovalRequestStatus::Failed,
json!({
"error": {
"code": runtime_error_code(&error),
"message": safe_runtime_error_message(&error),
}
}),
InvocationStatus::Error,
InvocationLevel::Error,
"approved tool call failed",
Some(runtime_error_code(&error)),
),
};
Some(crank_core::ExecutionStage::Runtime),
None,
Some(crank_core::Retryability::Never),
Some(crank_core::OutcomeCertainty::Certain),
None,
request_preview,
)
}
Err(failure) => (
ApprovalRequestStatus::Failed,
json!({
"error": {
"code": failure.error_code().as_str(),
"message": failure.error_code().message(crank_core::ExecutionLocale::Ru),
"stage": failure.stage().as_str(),
"retryability": failure.retryability().as_str(),
"outcome_certainty": failure.outcome_certainty().as_str(),
"request_id": request_id,
"trace_id": correlation.trace_id().as_str(),
}
}),
InvocationStatus::Error,
InvocationLevel::Error,
"approved tool call failed",
Some(failure.error_code().as_str()),
Some(failure.stage()),
Some(failure.error_code()),
Some(failure.retryability()),
Some(failure.outcome_certainty()),
failure.upstream_status(),
Value::Null,
),
};
persist_invocation(
state,
@@ -252,8 +288,12 @@ pub(super) async fn execute_approved_request(
status: invocation_status,
level: invocation_level,
message,
status_code: None,
status_code: upstream_status,
error_kind,
execution_stage,
execution_error_code,
retryability,
outcome_certainty,
duration: started_at.elapsed(),
request_preview,
response_preview: response_payload.clone(),
@@ -275,8 +315,47 @@ pub(super) async fn execute_approved_request(
}),
)
.await
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR.into_response())?
.ok_or_else(|| StatusCode::CONFLICT.into_response())
.map_err(|_| approved_completion_persistence_error(&correlation))?
.ok_or_else(|| approved_completion_conflict_error(&correlation))
}
fn approved_completion_conflict_error(correlation: &CorrelationContext) -> Response {
(
StatusCode::CONFLICT,
axum::Json(json!({
"error": {
"code": "approval_state_conflict",
"stage": "mandatory_persistence",
"retryability": "manual_reconcile",
"outcome_certainty": "outcome_unknown",
"request_id": correlation.request_id().as_str(),
"trace_id": correlation.trace_id().as_str(),
}
})),
)
.into_response()
}
fn approved_completion_persistence_error(correlation: &CorrelationContext) -> Response {
let failure = crank_core::ExecutionFailure::new(
crank_core::ExecutionErrorCode::PersistenceUnavailable,
correlation.clone(),
)
.with_dispatch_uncertainty();
(
StatusCode::SERVICE_UNAVAILABLE,
axum::Json(json!({
"error": {
"code": failure.error_code().as_str(),
"stage": failure.stage().as_str(),
"retryability": failure.retryability().as_str(),
"outcome_certainty": failure.outcome_certainty().as_str(),
"request_id": failure.correlation().request_id().as_str(),
"trace_id": failure.correlation().trace_id().as_str(),
}
})),
)
.into_response()
}
async fn finish_unavailable_approval(