use axum::{ Router, extract::{DefaultBodyLimit, FromRef}, middleware, routing::{get, post}, }; use crate::{ auth::require_bearer_auth, puzzle::{ advance_puzzle_next_level, claim_puzzle_work_point_incentive, create_puzzle_agent_session, delete_puzzle_work, drag_puzzle_piece_or_group, execute_puzzle_agent_action, generate_puzzle_onboarding_work, get_puzzle_agent_session, get_puzzle_gallery_detail, get_puzzle_run, get_puzzle_work_detail, get_puzzle_works, list_puzzle_gallery, put_puzzle_work, record_puzzle_gallery_like, remix_puzzle_gallery_work, save_puzzle_onboarding_work, start_puzzle_run, stream_puzzle_agent_message, submit_puzzle_agent_message, submit_puzzle_leaderboard, swap_puzzle_pieces, update_puzzle_run_pause, use_puzzle_runtime_prop, }, state::{AppState, PuzzleApiState}, }; const PUZZLE_REFERENCE_IMAGE_BODY_LIMIT_BYTES: usize = 12 * 1024 * 1024; pub fn router(state: AppState) -> Router { // 中文注释:拼图 handler 只接收 PuzzleApiState,鉴权层仍使用全局 AppState。 Router::new() .route( "/api/runtime/puzzle/agent/sessions", post(create_puzzle_agent_session) // 中文注释:拼图表单会携带单张参考图 Data URL,需只给该写入入口放宽 body 上限。 .layer(DefaultBodyLimit::max( PUZZLE_REFERENCE_IMAGE_BODY_LIMIT_BYTES, )) .route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/agent/sessions/{session_id}", get(get_puzzle_agent_session).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/agent/sessions/{session_id}/messages", post(submit_puzzle_agent_message).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/agent/sessions/{session_id}/messages/stream", post(stream_puzzle_agent_message).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/agent/sessions/{session_id}/actions", post(execute_puzzle_agent_action) // 中文注释:生成草稿/重新出图会复用 referenceImageSrc,避免默认 2MB JSON limit 拦截。 .layer(DefaultBodyLimit::max( PUZZLE_REFERENCE_IMAGE_BODY_LIMIT_BYTES, )) .route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/onboarding/generate", post(generate_puzzle_onboarding_work).layer(DefaultBodyLimit::max( PUZZLE_REFERENCE_IMAGE_BODY_LIMIT_BYTES, )), ) .route( "/api/runtime/puzzle/onboarding/save", post(save_puzzle_onboarding_work).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/works", get(get_puzzle_works).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/works/{profile_id}", get(get_puzzle_work_detail) .put(put_puzzle_work) .delete(delete_puzzle_work) .route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/works/{profile_id}/point-incentive/claim", post(claim_puzzle_work_point_incentive).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route("/api/runtime/puzzle/gallery", get(list_puzzle_gallery)) .route( "/api/runtime/puzzle/gallery/{profile_id}", get(get_puzzle_gallery_detail), ) .route( "/api/runtime/puzzle/gallery/{profile_id}/remix", post(remix_puzzle_gallery_work).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/gallery/{profile_id}/like", post(record_puzzle_gallery_like).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/runs", post(start_puzzle_run).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/runs/{run_id}", get(get_puzzle_run).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/runs/{run_id}/swap", post(swap_puzzle_pieces).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/runs/{run_id}/drag", post(drag_puzzle_piece_or_group).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/runs/{run_id}/next-level", post(advance_puzzle_next_level).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/runs/{run_id}/pause", post(update_puzzle_run_pause).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/runs/{run_id}/props", post(use_puzzle_runtime_prop).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .route( "/api/runtime/puzzle/runs/{run_id}/leaderboard", post(submit_puzzle_leaderboard).route_layer(middleware::from_fn_with_state( state.clone(), require_bearer_auth, )), ) .with_state(PuzzleApiState::from_ref(&state)) .with_state(state) }