use std::collections::HashMap;
use axum::{Json, response::IntoResponse};
use http::StatusCode;
use log::{debug, error, info};
use run_code_rmcp::{CodeExecutor, LanguageScript, RunCodeHttpResult};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::AppError;
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct RunCodeMessageRequest {
pub json_param: HashMap<String, Value>,
pub code: String,
pub uid: String,
pub engine_type: String,
}
impl RunCodeMessageRequest {
pub fn get_language_script(&self) -> LanguageScript {
match self.engine_type.as_str() {
"js" => LanguageScript::Js,
"ts" => LanguageScript::Ts,
"python" => LanguageScript::Python,
_ => LanguageScript::Js,
}
}
}
#[utoipa::path(
post,
path = "/api/run_code_with_log",
tag = "code-run",
request_body = RunCodeMessageRequest,
responses(
(status = 200, description = "代码执行结果:data 为脚本约定入口(JS/TS 为 handler,Python 为 handler/main)的返回值,success=false 时 error 携带错误日志",
body = RunCodeHttpResult)
)
)]
pub async fn run_code_handler(
Json(run_code_message_request): Json<RunCodeMessageRequest>,
) -> Result<impl IntoResponse, AppError> {
let params = match serde_json::to_value(run_code_message_request.json_param.clone()) {
Ok(v) => v,
Err(e) => {
error!("Run_code_handler parameter serialization failed: {e:?}");
return Err(AppError::from(e));
}
};
let code = run_code_message_request.code.clone();
let language = run_code_message_request.get_language_script();
debug!("run_code_handler language:{language:?}");
debug!("run_code_handler code:{code:?}");
debug!("run_code_handler params:{params:?}");
let result = match CodeExecutor::execute_with_params(&code, language, Some(params), None).await
{
Ok(result) => result,
Err(e) => {
error!("run_code_handler execution failed: {e:?}");
return Err(AppError::from(e));
}
};
if !result.success {
let error_message = result
.error
.as_deref()
.unwrap_or("run_code_handler执行失败但未提供错误信息");
error!("run_code_handler execution returns failure: {error_message}");
}
let data = match serde_json::to_value(&result) {
Ok(data) => data,
Err(e) => {
error!("run_code_handler serialization result failed: {e:?}");
return Err(AppError::from(e));
}
};
info!("run_code_handler result:{:?}", result.success);
debug!("run_code_handler result:{:?}", data);
let run_code_http_result = RunCodeHttpResult {
data,
success: result.success,
error: result.error.clone(),
};
let body = serde_json::to_string(&run_code_http_result)?;
Ok((StatusCode::OK, body).into_response())
}