This commit is contained in:
2026-05-09 17:15:23 +08:00
parent 80a4183b45
commit a0ed128bde
43 changed files with 2573 additions and 381 deletions

View File

@@ -1,6 +1,6 @@
use std::{
collections::BTreeMap,
time::{Duration, Instant, SystemTime, UNIX_EPOCH},
time::{Duration, SystemTime, UNIX_EPOCH},
};
use axum::{
@@ -68,7 +68,6 @@ use spacetime_client::{
PuzzleWorkUpsertRecordInput, SpacetimeClientError,
};
use std::convert::Infallible;
use tokio::time::sleep;
use crate::{
ai_generation_drafts::{AiGenerationDraftContext, AiGenerationDraftWriter},
@@ -80,6 +79,7 @@ use crate::{
auth::AuthenticatedAccessToken,
http_error::AppError,
llm_model_routing::{CREATION_TEMPLATE_LLM_MODEL, PUZZLE_LEVEL_NAME_VISION_LLM_MODEL},
openai_image_generation::VECTOR_ENGINE_GPT_IMAGE_2_MODEL,
platform_errors::map_oss_error,
prompt::puzzle::{
draft::{
@@ -112,8 +112,8 @@ const PUZZLE_IMAGE_GENERATION_POINTS_COST: u64 = 2;
const PUZZLE_ENTITY_KIND: &str = "puzzle_work";
#[cfg(test)]
const PUZZLE_GENERATED_IMAGE_SIZE: &str = "1024*1024";
const PUZZLE_APIMART_GENERATED_IMAGE_SIZE: &str = "1:1";
const PUZZLE_APIMART_GEMINI_RESOLUTION: &str = "1K";
const PUZZLE_VECTOR_ENGINE_GENERATED_IMAGE_SIZE: &str = "1024x1024";
const VECTOR_ENGINE_PROVIDER: &str = "vector-engine";
const PUZZLE_LEVEL_NAME_VISION_IMAGE_MAX_SIDE: u32 = 768;
pub async fn create_puzzle_agent_session(
@@ -941,7 +941,7 @@ pub async fn execute_puzzle_agent_action(
Err(error)
if should_skip_asset_operation_billing_for_connectivity(&error) =>
{
// 中文注释:APIMart/OSS 已生成真实图片时,Maincloud 短暂 503 不应让前端看不到本次图片;先返回内存合成快照,待后续操作恢复正常持久化。
// 中文注释:VectorEngine/OSS 已生成真实图片时,SpacetimeDB 短暂 503 不应让前端看不到本次图片;先返回内存合成快照,待后续操作恢复正常持久化。
tracing::warn!(
provider = PUZZLE_AGENT_API_BASE_PROVIDER,
session_id = %session.session_id,
@@ -3172,7 +3172,7 @@ async fn compile_puzzle_draft_with_initial_cover(
.map(|session| (session, false))
.or_else(|error| {
if is_spacetimedb_connectivity_app_error(&error) {
// 中文注释:首图已落 OSS 时,Maincloud 短暂不可用先返回本地快照,避免整次 APIMart 生图被判失败。
// 中文注释:首图已落 OSS 时,SpacetimeDB 短暂不可用先返回本地快照,避免整次 VectorEngine 生图被判失败。
tracing::warn!(
provider = PUZZLE_AGENT_API_BASE_PROVIDER,
session_id = %compiled_session.session_id,
@@ -3271,7 +3271,7 @@ async fn compile_puzzle_draft_with_uploaded_cover(
&target_level.picture_description,
&draft.summary,
);
// 中文注释:关闭 AI 重绘时不请求 APIMart,也不进入光点扣费流程;上传图直接成为首关正式图候选。
// 中文注释:关闭 AI 重绘时不请求 VectorEngine,也不进入光点扣费流程;上传图直接成为首关正式图候选。
let candidate_id = format!(
"{}-candidate-{}",
compiled_session.session_id,
@@ -3874,18 +3874,23 @@ fn is_missing_puzzle_form_draft_procedure_error(error: &SpacetimeClientError) ->
fn map_puzzle_compile_error(error: SpacetimeClientError) -> AppError {
let message = error.to_string();
let provider = if message.contains("APIMart")
let provider = if message.contains("VectorEngine")
|| message.contains("vector-engine")
|| message.contains("VECTOR_ENGINE")
|| message.contains("APIMart")
|| message.contains("apimart")
|| message.contains("APIMART")
{
"apimart"
VECTOR_ENGINE_PROVIDER
} else if message.contains("OSS") || message.contains("oss") || message.contains("参考图") {
"puzzle-assets"
} else {
"spacetimedb"
};
let status = if provider == "apimart"
&& (message.contains("APIMART_API_KEY")
let status = if provider == VECTOR_ENGINE_PROVIDER
&& (message.contains("VECTOR_ENGINE_API_KEY")
|| message.contains("VECTOR_ENGINE_BASE_URL")
|| message.contains("APIMART_API_KEY")
|| message.contains("APIMART_BASE_URL")
|| message.contains("未配置"))
{
@@ -3899,6 +3904,9 @@ fn map_puzzle_compile_error(error: SpacetimeClientError) -> AppError {
} else if matches!(error, SpacetimeClientError::Runtime(_))
&& (message.contains("生成")
|| message.contains("上游")
|| message.contains("VectorEngine")
|| message.contains("vector-engine")
|| message.contains("VECTOR_ENGINE")
|| message.contains("APIMart")
|| message.contains("apimart")
|| message.contains("APIMART")