Integrate unfinished server-rs refactor worklists
This commit is contained in:
@@ -1,3 +1,148 @@
|
||||
//! 剧情写入命令过渡落位。
|
||||
//! 剧情写入命令与输入归一化。
|
||||
//!
|
||||
//! 用于表达开启剧情会话、继续剧情和归档会话等输入。
|
||||
//! 命令层只处理 story session scoped 的输入结构、字段裁剪和基础校验,不读取数据库,
|
||||
//! 也不兼容旧 `/api/runtime/story/*` 总入口。
|
||||
|
||||
use crate::errors::StorySessionFieldError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use shared_kernel::{
|
||||
normalize_optional_string as normalize_shared_optional_string, normalize_required_string,
|
||||
};
|
||||
#[cfg(feature = "spacetime-types")]
|
||||
use spacetimedb::SpacetimeType;
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct StorySessionInput {
|
||||
pub story_session_id: String,
|
||||
pub runtime_session_id: String,
|
||||
pub actor_user_id: String,
|
||||
pub world_profile_id: String,
|
||||
pub initial_prompt: String,
|
||||
pub opening_summary: Option<String>,
|
||||
pub created_at_micros: i64,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct StoryContinueInput {
|
||||
pub story_session_id: String,
|
||||
pub event_id: String,
|
||||
pub narrative_text: String,
|
||||
pub choice_function_id: Option<String>,
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct StorySessionStateInput {
|
||||
pub story_session_id: String,
|
||||
}
|
||||
|
||||
pub fn build_story_session_input(
|
||||
story_session_id: String,
|
||||
runtime_session_id: String,
|
||||
actor_user_id: String,
|
||||
world_profile_id: String,
|
||||
initial_prompt: String,
|
||||
opening_summary: Option<String>,
|
||||
created_at_micros: i64,
|
||||
) -> Result<StorySessionInput, StorySessionFieldError> {
|
||||
let input = StorySessionInput {
|
||||
story_session_id: normalize_required_string(story_session_id).unwrap_or_default(),
|
||||
runtime_session_id: normalize_required_string(runtime_session_id).unwrap_or_default(),
|
||||
actor_user_id: normalize_required_string(actor_user_id).unwrap_or_default(),
|
||||
world_profile_id: normalize_required_string(world_profile_id).unwrap_or_default(),
|
||||
initial_prompt: normalize_required_string(initial_prompt).unwrap_or_default(),
|
||||
opening_summary: normalize_optional_value(opening_summary),
|
||||
created_at_micros,
|
||||
};
|
||||
|
||||
validate_story_session_input(&input)?;
|
||||
|
||||
Ok(input)
|
||||
}
|
||||
|
||||
pub fn build_story_session_state_input(
|
||||
story_session_id: String,
|
||||
) -> Result<StorySessionStateInput, StorySessionFieldError> {
|
||||
let input = StorySessionStateInput {
|
||||
story_session_id: normalize_required_string(story_session_id).unwrap_or_default(),
|
||||
};
|
||||
|
||||
validate_story_session_state_input(&input)?;
|
||||
|
||||
Ok(input)
|
||||
}
|
||||
|
||||
pub fn build_story_continue_input(
|
||||
story_session_id: String,
|
||||
event_id: String,
|
||||
narrative_text: String,
|
||||
choice_function_id: Option<String>,
|
||||
updated_at_micros: i64,
|
||||
) -> Result<StoryContinueInput, StorySessionFieldError> {
|
||||
let input = StoryContinueInput {
|
||||
story_session_id: normalize_required_string(story_session_id).unwrap_or_default(),
|
||||
event_id: normalize_required_string(event_id).unwrap_or_default(),
|
||||
narrative_text: normalize_required_string(narrative_text).unwrap_or_default(),
|
||||
choice_function_id: normalize_optional_value(choice_function_id),
|
||||
updated_at_micros,
|
||||
};
|
||||
|
||||
validate_story_continue_input(&input)?;
|
||||
|
||||
Ok(input)
|
||||
}
|
||||
|
||||
pub fn validate_story_session_input(
|
||||
input: &StorySessionInput,
|
||||
) -> Result<(), StorySessionFieldError> {
|
||||
if normalize_required_string(&input.story_session_id).is_none() {
|
||||
return Err(StorySessionFieldError::MissingSessionId);
|
||||
}
|
||||
if normalize_required_string(&input.runtime_session_id).is_none() {
|
||||
return Err(StorySessionFieldError::MissingRuntimeSessionId);
|
||||
}
|
||||
if normalize_required_string(&input.actor_user_id).is_none() {
|
||||
return Err(StorySessionFieldError::MissingActorUserId);
|
||||
}
|
||||
if normalize_required_string(&input.world_profile_id).is_none() {
|
||||
return Err(StorySessionFieldError::MissingWorldProfileId);
|
||||
}
|
||||
if normalize_required_string(&input.initial_prompt).is_none() {
|
||||
return Err(StorySessionFieldError::MissingInitialPrompt);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn validate_story_session_state_input(
|
||||
input: &StorySessionStateInput,
|
||||
) -> Result<(), StorySessionFieldError> {
|
||||
if normalize_required_string(&input.story_session_id).is_none() {
|
||||
return Err(StorySessionFieldError::MissingSessionId);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn validate_story_continue_input(
|
||||
input: &StoryContinueInput,
|
||||
) -> Result<(), StorySessionFieldError> {
|
||||
if normalize_required_string(&input.story_session_id).is_none() {
|
||||
return Err(StorySessionFieldError::MissingSessionId);
|
||||
}
|
||||
if normalize_required_string(&input.event_id).is_none() {
|
||||
return Err(StorySessionFieldError::MissingEventId);
|
||||
}
|
||||
if normalize_required_string(&input.narrative_text).is_none() {
|
||||
return Err(StorySessionFieldError::MissingNarrativeText);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn normalize_optional_value(value: Option<String>) -> Option<String> {
|
||||
normalize_shared_optional_string(value)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user