收口后端创作游玩流程主干
新增 play_flow 统一承接创作游玩与支撑路由 将 app.rs 的逐玩法挂载改为统一主干分发 将平台与资产及个人侧游玩支撑路由迁入 play_flow 抽出 visual_novel 路由模块并复用原有 handler 统一入口熔断路径解析并补充目标回归测试 更新后端契约、玩法链路和团队决策记录
This commit is contained in:
@@ -6,7 +6,7 @@ use axum::{
|
||||
use crate::{
|
||||
assets::{
|
||||
bind_asset_object_to_entity, confirm_asset_object, create_direct_upload_ticket,
|
||||
create_sts_upload_credentials, get_asset_history, get_asset_read_bytes, get_asset_read_url,
|
||||
create_sts_upload_credentials, get_asset_read_bytes, get_asset_read_url,
|
||||
},
|
||||
auth::require_bearer_auth,
|
||||
state::AppState,
|
||||
@@ -44,11 +44,4 @@ pub fn router(state: AppState) -> Router<AppState> {
|
||||
)
|
||||
.route("/api/assets/read-url", get(get_asset_read_url))
|
||||
.route("/api/assets/read-bytes", get(get_asset_read_bytes))
|
||||
.route(
|
||||
"/api/assets/history",
|
||||
get(get_asset_history).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,40 +1,11 @@
|
||||
use axum::{
|
||||
Router,
|
||||
extract::DefaultBodyLimit,
|
||||
middleware,
|
||||
Router, middleware,
|
||||
routing::{get, post},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
ai_tasks::{
|
||||
append_ai_text_chunk, attach_ai_result_reference, cancel_ai_task, complete_ai_stage,
|
||||
complete_ai_task, create_ai_task, fail_ai_task, start_ai_task, start_ai_task_stage,
|
||||
},
|
||||
auth::require_bearer_auth,
|
||||
character_animation_assets::{
|
||||
generate_character_animation, get_character_animation_job, get_character_workflow_cache,
|
||||
import_character_animation_video, list_character_animation_templates,
|
||||
publish_character_animation, put_role_asset_workflow, resolve_role_asset_workflow,
|
||||
save_character_workflow_cache,
|
||||
},
|
||||
character_visual_assets::{
|
||||
generate_character_visual, get_character_visual_job, publish_character_visual,
|
||||
},
|
||||
creation_agent_document_input::parse_creation_agent_document_input,
|
||||
creation_entry_config::get_creation_entry_config_handler,
|
||||
hyper3d_generation::{
|
||||
get_hyper3d_downloads, get_hyper3d_task_status, submit_hyper3d_image_to_model,
|
||||
submit_hyper3d_text_to_model,
|
||||
},
|
||||
llm::proxy_llm_chat_completions,
|
||||
runtime_chat::stream_runtime_npc_chat_turn,
|
||||
runtime_chat_plain::{
|
||||
generate_runtime_character_chat_suggestions, generate_runtime_character_chat_summary,
|
||||
stream_runtime_character_chat_reply, stream_runtime_npc_chat_dialogue,
|
||||
stream_runtime_npc_recruit_dialogue,
|
||||
},
|
||||
runtime_save::{delete_runtime_snapshot, get_runtime_snapshot, put_runtime_snapshot},
|
||||
runtime_settings::{get_runtime_settings, put_runtime_settings},
|
||||
state::AppState,
|
||||
volcengine_speech::{
|
||||
get_volcengine_speech_config, stream_volcengine_asr, stream_volcengine_tts_bidirection,
|
||||
@@ -42,8 +13,6 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
const HYPER3D_IMAGE_TO_MODEL_BODY_LIMIT_BYTES: usize = 56 * 1024 * 1024;
|
||||
|
||||
pub fn router(state: AppState) -> Router<AppState> {
|
||||
Router::new()
|
||||
.route(
|
||||
@@ -81,213 +50,4 @@ pub fn router(state: AppState) -> Router<AppState> {
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/chat/character/suggestions",
|
||||
post(generate_runtime_character_chat_suggestions).route_layer(
|
||||
middleware::from_fn_with_state(state.clone(), require_bearer_auth),
|
||||
),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/chat/character/summary",
|
||||
post(generate_runtime_character_chat_summary).route_layer(
|
||||
middleware::from_fn_with_state(state.clone(), require_bearer_auth),
|
||||
),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/chat/character/reply/stream",
|
||||
post(stream_runtime_character_chat_reply).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/chat/npc/dialogue/stream",
|
||||
post(stream_runtime_npc_chat_dialogue).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/chat/npc/turn/stream",
|
||||
post(stream_runtime_npc_chat_turn).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/chat/npc/recruit/stream",
|
||||
post(stream_runtime_npc_recruit_dialogue).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/creation-agent/document-inputs/parse",
|
||||
post(parse_creation_agent_document_input).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/ai/tasks",
|
||||
post(create_ai_task).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/ai/tasks/{task_id}/start",
|
||||
post(start_ai_task).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/ai/tasks/{task_id}/stages/{stage_kind}/start",
|
||||
post(start_ai_task_stage).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/ai/tasks/{task_id}/chunks",
|
||||
post(append_ai_text_chunk).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/ai/tasks/{task_id}/stages/{stage_kind}/complete",
|
||||
post(complete_ai_stage).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/ai/tasks/{task_id}/references",
|
||||
post(attach_ai_result_reference).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/ai/tasks/{task_id}/complete",
|
||||
post(complete_ai_task).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/ai/tasks/{task_id}/fail",
|
||||
post(fail_ai_task).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/ai/tasks/{task_id}/cancel",
|
||||
post(cancel_ai_task).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/character-visual/generate",
|
||||
post(generate_character_visual),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/character-visual/jobs/{task_id}",
|
||||
get(get_character_visual_job),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/character-visual/publish",
|
||||
post(publish_character_visual),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/character-animation/generate",
|
||||
post(generate_character_animation),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/character-animation/jobs/{task_id}",
|
||||
get(get_character_animation_job),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/character-animation/publish",
|
||||
post(publish_character_animation),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/character-animation/import-video",
|
||||
post(import_character_animation_video),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/character-animation/templates",
|
||||
get(list_character_animation_templates),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/character-workflow-cache",
|
||||
post(save_character_workflow_cache),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/character-workflow-cache/{character_id}",
|
||||
get(get_character_workflow_cache),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/custom-world/asset-studio/role/{character_id}/workflow",
|
||||
post(resolve_role_asset_workflow).put(put_role_asset_workflow),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/hyper3d/text-to-model",
|
||||
post(submit_hyper3d_text_to_model).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/hyper3d/image-to-model",
|
||||
post(submit_hyper3d_image_to_model)
|
||||
.layer(DefaultBodyLimit::max(
|
||||
HYPER3D_IMAGE_TO_MODEL_BODY_LIMIT_BYTES,
|
||||
))
|
||||
.route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/hyper3d/status",
|
||||
post(get_hyper3d_task_status).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/assets/hyper3d/download",
|
||||
post(get_hyper3d_downloads).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation-entry/config",
|
||||
get(get_creation_entry_config_handler),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/settings",
|
||||
get(get_runtime_settings)
|
||||
.put(put_runtime_settings)
|
||||
.route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/save/snapshot",
|
||||
get(get_runtime_snapshot)
|
||||
.put(put_runtime_snapshot)
|
||||
.delete(delete_runtime_snapshot)
|
||||
.route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
}
|
||||
|
||||
1028
server-rs/crates/api-server/src/modules/play_flow.rs
Normal file
1028
server-rs/crates/api-server/src/modules/play_flow.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,18 +6,13 @@ use axum::{
|
||||
use crate::{
|
||||
auth::require_bearer_auth,
|
||||
profile_identity::update_profile_identity,
|
||||
runtime_browse_history::{
|
||||
delete_runtime_browse_history, get_runtime_browse_history, post_runtime_browse_history,
|
||||
},
|
||||
runtime_profile::{
|
||||
claim_profile_task_reward, confirm_wechat_profile_recharge_order,
|
||||
create_profile_recharge_order, get_profile_analytics_metric, get_profile_dashboard,
|
||||
get_profile_play_stats, get_profile_recharge_center, get_profile_referral_invite_center,
|
||||
get_profile_task_center, get_profile_wallet_ledger, redeem_profile_referral_invite_code,
|
||||
redeem_profile_reward_code, stream_wechat_profile_recharge_order_events,
|
||||
submit_profile_feedback,
|
||||
get_profile_recharge_center, get_profile_referral_invite_center, get_profile_task_center,
|
||||
get_profile_wallet_ledger, redeem_profile_referral_invite_code, redeem_profile_reward_code,
|
||||
stream_wechat_profile_recharge_order_events, submit_profile_feedback,
|
||||
},
|
||||
runtime_save::{list_profile_save_archives, resume_profile_save_archive},
|
||||
state::AppState,
|
||||
};
|
||||
|
||||
@@ -30,16 +25,6 @@ pub fn router(state: AppState) -> Router<AppState> {
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/profile/browse-history",
|
||||
get(get_runtime_browse_history)
|
||||
.post(post_runtime_browse_history)
|
||||
.delete(delete_runtime_browse_history)
|
||||
.route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/profile/dashboard",
|
||||
get(get_profile_dashboard).route_layer(middleware::from_fn_with_state(
|
||||
@@ -131,25 +116,4 @@ pub fn router(state: AppState) -> Router<AppState> {
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/profile/save-archives",
|
||||
get(list_profile_save_archives).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/profile/save-archives/{world_key}",
|
||||
post(resume_profile_save_archive).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/profile/play-stats",
|
||||
get(get_profile_play_stats).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
}
|
||||
|
||||
183
server-rs/crates/api-server/src/modules/visual_novel.rs
Normal file
183
server-rs/crates/api-server/src/modules/visual_novel.rs
Normal file
@@ -0,0 +1,183 @@
|
||||
use axum::{
|
||||
Router, middleware,
|
||||
routing::{get, post},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
auth::require_bearer_auth,
|
||||
state::AppState,
|
||||
vector_engine_audio_generation::{
|
||||
create_background_music_task, create_sound_effect_task,
|
||||
create_visual_novel_background_music_task, create_visual_novel_sound_effect_task,
|
||||
publish_background_music_asset, publish_sound_effect_asset,
|
||||
publish_visual_novel_background_music_asset, publish_visual_novel_sound_effect_asset,
|
||||
},
|
||||
visual_novel::{
|
||||
compile_visual_novel_session, create_visual_novel_session, delete_visual_novel_work,
|
||||
execute_visual_novel_action, get_visual_novel_run, get_visual_novel_session,
|
||||
get_visual_novel_work, list_visual_novel_gallery, list_visual_novel_history,
|
||||
list_visual_novel_works, publish_visual_novel_work, regenerate_visual_novel_run,
|
||||
start_visual_novel_run, stream_visual_novel_action, stream_visual_novel_message,
|
||||
submit_visual_novel_message, update_visual_novel_work,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn router(state: AppState) -> Router<AppState> {
|
||||
Router::new()
|
||||
.route(
|
||||
"/api/creation/visual-novel/sessions",
|
||||
post(create_visual_novel_session).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/visual-novel/sessions/{session_id}",
|
||||
get(get_visual_novel_session).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/visual-novel/sessions/{session_id}/messages",
|
||||
post(submit_visual_novel_message).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/visual-novel/sessions/{session_id}/messages/stream",
|
||||
post(stream_visual_novel_message).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/visual-novel/sessions/{session_id}/actions",
|
||||
post(execute_visual_novel_action).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/visual-novel/sessions/{session_id}/compile",
|
||||
post(compile_visual_novel_session).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/visual-novel/works",
|
||||
get(list_visual_novel_works).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/visual-novel/works/{profile_id}",
|
||||
get(get_visual_novel_work)
|
||||
.put(update_visual_novel_work)
|
||||
.patch(update_visual_novel_work)
|
||||
.delete(delete_visual_novel_work)
|
||||
.route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/visual-novel/works/{profile_id}/publish",
|
||||
post(publish_visual_novel_work).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/visual-novel/audio/background-music",
|
||||
post(create_visual_novel_background_music_task).route_layer(
|
||||
middleware::from_fn_with_state(state.clone(), require_bearer_auth),
|
||||
),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/visual-novel/audio/background-music/{task_id}/asset",
|
||||
post(publish_visual_novel_background_music_asset).route_layer(
|
||||
middleware::from_fn_with_state(state.clone(), require_bearer_auth),
|
||||
),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/visual-novel/audio/sound-effect",
|
||||
post(create_visual_novel_sound_effect_task).route_layer(
|
||||
middleware::from_fn_with_state(state.clone(), require_bearer_auth),
|
||||
),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/visual-novel/audio/sound-effect/{task_id}/asset",
|
||||
post(publish_visual_novel_sound_effect_asset).route_layer(
|
||||
middleware::from_fn_with_state(state.clone(), require_bearer_auth),
|
||||
),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/audio/background-music",
|
||||
post(create_background_music_task).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/audio/background-music/{task_id}/asset",
|
||||
post(publish_background_music_asset).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/audio/sound-effect",
|
||||
post(create_sound_effect_task).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/creation/audio/sound-effect/{task_id}/asset",
|
||||
post(publish_sound_effect_asset).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/visual-novel/gallery",
|
||||
get(list_visual_novel_gallery),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/visual-novel/works/{profile_id}/runs",
|
||||
post(start_visual_novel_run).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/visual-novel/runs/{run_id}",
|
||||
get(get_visual_novel_run).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/visual-novel/runs/{run_id}/actions/stream",
|
||||
post(stream_visual_novel_action).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/visual-novel/runs/{run_id}/history",
|
||||
get(list_visual_novel_history).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/runtime/visual-novel/runs/{run_id}/regenerate",
|
||||
post(regenerate_visual_novel_run)
|
||||
.route_layer(middleware::from_fn_with_state(state, require_bearer_auth)),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user