1
This commit is contained in:
@@ -74,7 +74,10 @@ pub(crate) fn build_ai_task_snapshot_from_row(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn build_ai_task_stage_row(task_id: &str, snapshot: &AiTaskStageSnapshot) -> AiTaskStage {
|
||||
pub(crate) fn build_ai_task_stage_row(
|
||||
task_id: &str,
|
||||
snapshot: &AiTaskStageSnapshot,
|
||||
) -> AiTaskStage {
|
||||
AiTaskStage {
|
||||
task_stage_id: generate_ai_task_stage_id(task_id, snapshot.stage_kind),
|
||||
task_id: task_id.to_string(),
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
use crate::*;
|
||||
use module_ai::{generate_ai_result_ref_id, generate_ai_text_chunk_id, normalize_optional_text, normalize_string_list};
|
||||
use module_ai::{
|
||||
generate_ai_result_ref_id, generate_ai_text_chunk_id, normalize_optional_text,
|
||||
normalize_string_list,
|
||||
};
|
||||
|
||||
#[spacetimedb::table(
|
||||
accessor = ai_task_stage,
|
||||
@@ -184,7 +187,9 @@ pub(crate) fn append_ai_text_chunk_tx(
|
||||
delta_text: input.delta_text.trim().to_string(),
|
||||
created_at_micros: input.created_at_micros,
|
||||
};
|
||||
ctx.db.ai_text_chunk().insert(build_ai_text_chunk_row(&chunk));
|
||||
ctx.db
|
||||
.ai_text_chunk()
|
||||
.insert(build_ai_text_chunk_row(&chunk));
|
||||
|
||||
let aggregated_text = collect_ai_stage_text_output(ctx, &chunk.task_id, chunk.stage_kind);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::*;
|
||||
use module_ai::{normalize_optional_text, validate_task_create_input, INITIAL_AI_TASK_VERSION};
|
||||
use module_ai::{INITIAL_AI_TASK_VERSION, normalize_optional_text, validate_task_create_input};
|
||||
|
||||
#[spacetimedb::table(
|
||||
accessor = ai_task,
|
||||
|
||||
@@ -84,6 +84,25 @@ pub fn submit_big_fish_message(
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::procedure]
|
||||
pub fn finalize_big_fish_agent_message_turn(
|
||||
ctx: &mut ProcedureContext,
|
||||
input: BigFishMessageFinalizeInput,
|
||||
) -> BigFishSessionProcedureResult {
|
||||
match ctx.try_with_tx(|tx| finalize_big_fish_agent_message_turn_tx(tx, input.clone())) {
|
||||
Ok(session) => BigFishSessionProcedureResult {
|
||||
ok: true,
|
||||
session: Some(session),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => BigFishSessionProcedureResult {
|
||||
ok: false,
|
||||
session: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::procedure]
|
||||
pub fn compile_big_fish_draft(
|
||||
ctx: &mut ProcedureContext,
|
||||
@@ -247,17 +266,103 @@ pub(crate) fn submit_big_fish_message_tx(
|
||||
created_at: submitted_at,
|
||||
});
|
||||
|
||||
let anchor_pack = infer_anchor_pack(&session.seed_text, Some(&input.user_message_text));
|
||||
let assistant_text =
|
||||
"我已经把这版方向收束成 4 个高杠杆锚点,可以继续细化,也可以直接编译第一版玩法草稿。"
|
||||
.to_string();
|
||||
let next_session = BigFishCreationSession {
|
||||
session_id: session.session_id.clone(),
|
||||
owner_user_id: session.owner_user_id.clone(),
|
||||
seed_text: session.seed_text.clone(),
|
||||
current_turn: session.current_turn,
|
||||
progress_percent: session.progress_percent,
|
||||
stage: BigFishCreationStage::CollectingAnchors,
|
||||
anchor_pack_json: session.anchor_pack_json.clone(),
|
||||
draft_json: session.draft_json.clone(),
|
||||
asset_coverage_json: session.asset_coverage_json.clone(),
|
||||
last_assistant_reply: session.last_assistant_reply.clone(),
|
||||
publish_ready: session.publish_ready,
|
||||
created_at: session.created_at,
|
||||
updated_at: submitted_at,
|
||||
};
|
||||
replace_big_fish_session(ctx, &session, next_session);
|
||||
|
||||
get_big_fish_session_tx(
|
||||
ctx,
|
||||
BigFishSessionGetInput {
|
||||
session_id: input.session_id,
|
||||
owner_user_id: input.owner_user_id,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn finalize_big_fish_agent_message_turn_tx(
|
||||
ctx: &ReducerContext,
|
||||
input: BigFishMessageFinalizeInput,
|
||||
) -> Result<BigFishSessionSnapshot, String> {
|
||||
validate_message_finalize_input(&input).map_err(|error| error.to_string())?;
|
||||
let session = ctx
|
||||
.db
|
||||
.big_fish_creation_session()
|
||||
.session_id()
|
||||
.find(&input.session_id)
|
||||
.filter(|row| row.owner_user_id == input.owner_user_id)
|
||||
.ok_or_else(|| "big_fish_creation_session 不存在".to_string())?;
|
||||
let updated_at = Timestamp::from_micros_since_unix_epoch(input.updated_at_micros);
|
||||
|
||||
if let Some(error_message) = input
|
||||
.error_message
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
{
|
||||
let next_session = BigFishCreationSession {
|
||||
session_id: session.session_id.clone(),
|
||||
owner_user_id: session.owner_user_id.clone(),
|
||||
seed_text: session.seed_text.clone(),
|
||||
current_turn: session.current_turn,
|
||||
progress_percent: session.progress_percent,
|
||||
stage: session.stage,
|
||||
anchor_pack_json: session.anchor_pack_json.clone(),
|
||||
draft_json: session.draft_json.clone(),
|
||||
asset_coverage_json: session.asset_coverage_json.clone(),
|
||||
last_assistant_reply: session.last_assistant_reply.clone(),
|
||||
publish_ready: session.publish_ready,
|
||||
created_at: session.created_at,
|
||||
updated_at,
|
||||
};
|
||||
replace_big_fish_session(ctx, &session, next_session);
|
||||
return Err(error_message.to_string());
|
||||
}
|
||||
|
||||
let assistant_message_id = input
|
||||
.assistant_message_id
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.ok_or_else(|| "big_fish assistant_message_id 不能为空".to_string())?
|
||||
.to_string();
|
||||
let assistant_reply_text = input
|
||||
.assistant_reply_text
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.ok_or_else(|| "big_fish assistant_reply_text 不能为空".to_string())?
|
||||
.to_string();
|
||||
if ctx
|
||||
.db
|
||||
.big_fish_agent_message()
|
||||
.message_id()
|
||||
.find(&assistant_message_id)
|
||||
.is_some()
|
||||
{
|
||||
return Err("big_fish_agent_message.assistant_message_id 已存在".to_string());
|
||||
}
|
||||
let next_anchor_pack =
|
||||
deserialize_anchor_pack(&input.anchor_pack_json).map_err(|error| error.to_string())?;
|
||||
ctx.db.big_fish_agent_message().insert(BigFishAgentMessage {
|
||||
message_id: input.assistant_message_id,
|
||||
message_id: assistant_message_id,
|
||||
session_id: input.session_id.clone(),
|
||||
role: BigFishAgentMessageRole::Assistant,
|
||||
kind: BigFishAgentMessageKind::Summary,
|
||||
text: assistant_text.clone(),
|
||||
created_at: submitted_at,
|
||||
kind: BigFishAgentMessageKind::Chat,
|
||||
text: assistant_reply_text.clone(),
|
||||
created_at: updated_at,
|
||||
});
|
||||
|
||||
let next_session = BigFishCreationSession {
|
||||
@@ -265,15 +370,16 @@ pub(crate) fn submit_big_fish_message_tx(
|
||||
owner_user_id: session.owner_user_id.clone(),
|
||||
seed_text: session.seed_text.clone(),
|
||||
current_turn: session.current_turn.saturating_add(1),
|
||||
progress_percent: 60,
|
||||
stage: BigFishCreationStage::CollectingAnchors,
|
||||
anchor_pack_json: serialize_anchor_pack(&anchor_pack).map_err(|error| error.to_string())?,
|
||||
progress_percent: input.progress_percent.min(100),
|
||||
stage: input.stage,
|
||||
anchor_pack_json: serialize_anchor_pack(&next_anchor_pack)
|
||||
.map_err(|error| error.to_string())?,
|
||||
draft_json: session.draft_json.clone(),
|
||||
asset_coverage_json: session.asset_coverage_json.clone(),
|
||||
last_assistant_reply: Some(assistant_text),
|
||||
last_assistant_reply: Some(assistant_reply_text),
|
||||
publish_ready: session.publish_ready,
|
||||
created_at: session.created_at,
|
||||
updated_at: submitted_at,
|
||||
updated_at,
|
||||
};
|
||||
replace_big_fish_session(ctx, &session, next_session);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1746,7 +1746,6 @@ pub fn turn_in_quest(ctx: &ReducerContext, input: QuestTurnInInput) -> Result<()
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
// M5 Stage 2 先把 library profile upsert 固定成最小正式写入口;已发布作品在这里同步刷新 gallery 投影。
|
||||
#[spacetimedb::reducer]
|
||||
pub fn upsert_custom_world_profile(
|
||||
@@ -2023,7 +2022,6 @@ pub fn execute_custom_world_agent_action(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Stage 3 先把 published profile compile 作为独立 procedure 暴露,避免把编译逻辑和表写入、发布动作强耦合。
|
||||
#[spacetimedb::procedure]
|
||||
pub fn compile_custom_world_published_profile(
|
||||
|
||||
@@ -224,8 +224,9 @@ pub(crate) fn resume_profile_save_archive_record(
|
||||
ctx: &ReducerContext,
|
||||
input: RuntimeProfileSaveArchiveResumeInput,
|
||||
) -> Result<(RuntimeProfileSaveArchiveSnapshot, RuntimeSnapshot), String> {
|
||||
let validated_input = build_runtime_profile_save_archive_resume_input(input.user_id, input.world_key)
|
||||
.map_err(|error| error.to_string())?;
|
||||
let validated_input =
|
||||
build_runtime_profile_save_archive_resume_input(input.user_id, input.world_key)
|
||||
.map_err(|error| error.to_string())?;
|
||||
let archive = ctx
|
||||
.db
|
||||
.profile_save_archive()
|
||||
|
||||
@@ -202,7 +202,8 @@ pub(crate) fn build_runtime_snapshot_from_row(row: &RuntimeSnapshotRow) -> Runti
|
||||
}
|
||||
|
||||
pub(crate) fn parse_json_str(raw: &str) -> Result<JsonValue, String> {
|
||||
serde_json::from_str::<JsonValue>(raw).map_err(|error| format!("game_state_json 解析失败: {error}"))
|
||||
serde_json::from_str::<JsonValue>(raw)
|
||||
.map_err(|error| format!("game_state_json 解析失败: {error}"))
|
||||
}
|
||||
|
||||
pub(crate) fn parse_optional_json_str(raw: Option<&str>) -> Result<Option<JsonValue>, String> {
|
||||
|
||||
Reference in New Issue
Block a user