合并最新master到画板抠图背景分支

更新本地 master 到 origin/master 后合入当前 feat/BGfilter 分支。

解决决策记录和图片画布 MVP 文档冲突,保留画布 Agent 与 BGFilter 背景色说明。

补齐画布 Agent 调用生图接口时的默认 screenColor=auto 和 segModel=birefnet。
This commit is contained in:
2026-07-06 12:31:36 +00:00
221 changed files with 19875 additions and 1223 deletions
File diff suppressed because it is too large Load Diff
@@ -33,7 +33,7 @@ impl AiGenerationDraftContext {
Self {
// 生成过程草稿使用稳定 task_id,保证同一模板会话操作重试时能继续定位已有内容。
task_id: format!(
"aitask_draft_{normalized_template}_{normalized_session}_{normalized_operation}"
"task-draft-{normalized_template}-{normalized_session}-{normalized_operation}"
),
owner_user_id: owner_user_id.trim().to_string(),
request_label: request_label.trim().to_string(),
@@ -85,6 +85,14 @@ pub(crate) async fn create_direct_upload_ticket_for_owner(
"supported": platform_oss::LEGACY_PUBLIC_PREFIXES,
}))
})?;
if matches!(legacy_prefix, LegacyAssetPrefix::EditorAgent) {
return Err(
AppError::from_status(StatusCode::BAD_REQUEST).with_details(json!({
"field": "legacyPrefix",
"supported": platform_oss::LEGACY_PUBLIC_PREFIXES,
})),
);
}
let signed = oss_client
.sign_post_object(OssPostObjectRequest {
@@ -905,6 +905,7 @@ pub(crate) async fn generate_editor_video_for_owner(
asset_kind: Some(asset_kind.clone()),
generation_inputs: generation_inputs.clone(),
thumbnail_src: generated.thumbnail_src.clone(),
generation_cost_mud_points: u64::from(normalized.price_mud_points),
},
)
.await
+26 -2
View File
@@ -961,8 +961,21 @@ impl AppConfig {
config.llm_base_url = DEFAULT_ARK_BASE_URL.to_string();
}
config.llm_api_key =
read_first_non_empty_env(&["GENARRATIVE_LLM_API_KEY", "LLM_API_KEY", "ARK_API_KEY"]);
config.llm_api_key = if config.llm_provider == LlmProvider::OpenAiCompatible {
read_first_non_empty_env(&[
"GENARRATIVE_LLM_API_KEY",
"LLM_API_KEY",
"VECTOR_ENGINE_API_KEY",
"ARK_API_KEY",
])
} else {
read_first_non_empty_env(&[
"GENARRATIVE_LLM_API_KEY",
"LLM_API_KEY",
"ARK_API_KEY",
"VECTOR_ENGINE_API_KEY",
])
};
if let Some(llm_model) =
read_first_non_empty_env(&["GENARRATIVE_LLM_MODEL", "LLM_MODEL", "VITE_LLM_MODEL"])
@@ -1660,10 +1673,14 @@ mod tests {
unsafe {
std::env::remove_var("GENARRATIVE_LLM_PROVIDER");
std::env::remove_var("GENARRATIVE_LLM_BASE_URL");
std::env::remove_var("GENARRATIVE_LLM_API_KEY");
std::env::remove_var("LLM_API_KEY");
std::env::remove_var("ARK_API_KEY");
std::env::remove_var("GENARRATIVE_LLM_MODEL");
std::env::remove_var("APIMART_BASE_URL");
std::env::remove_var("APIMART_IMAGE_REQUEST_TIMEOUT_MS");
std::env::remove_var("VECTOR_ENGINE_BASE_URL");
std::env::remove_var("VECTOR_ENGINE_API_KEY");
std::env::remove_var("VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS");
std::env::remove_var("HYPER3D_BASE_URL");
std::env::remove_var("DASHSCOPE_SCENE_IMAGE_MODEL");
@@ -1679,7 +1696,9 @@ mod tests {
std::env::set_var("GENARRATIVE_LLM_MODEL", "internal-text-model");
std::env::set_var("APIMART_BASE_URL", "https://responses.internal.example/v1");
std::env::set_var("APIMART_IMAGE_REQUEST_TIMEOUT_MS", "190000");
std::env::set_var("ARK_API_KEY", "ark-key");
std::env::set_var("VECTOR_ENGINE_BASE_URL", "https://vector.internal.example");
std::env::set_var("VECTOR_ENGINE_API_KEY", "vector-engine-key");
std::env::set_var("VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS", "210000");
std::env::set_var("HYPER3D_BASE_URL", "https://model.internal.example/api/v2");
std::env::set_var("DASHSCOPE_SCENE_IMAGE_MODEL", "scene-model");
@@ -1695,6 +1714,7 @@ mod tests {
let config = AppConfig::from_env();
assert_eq!(config.llm_provider, LlmProvider::OpenAiCompatible);
assert_eq!(config.llm_base_url, "https://llm.internal.example/v1");
assert_eq!(config.llm_api_key.as_deref(), Some("vector-engine-key"));
assert_eq!(config.llm_model, "internal-text-model");
// assert_eq!(
// config.apimart_base_url,
@@ -1725,10 +1745,14 @@ mod tests {
unsafe {
std::env::remove_var("GENARRATIVE_LLM_PROVIDER");
std::env::remove_var("GENARRATIVE_LLM_BASE_URL");
std::env::remove_var("GENARRATIVE_LLM_API_KEY");
std::env::remove_var("LLM_API_KEY");
std::env::remove_var("ARK_API_KEY");
std::env::remove_var("GENARRATIVE_LLM_MODEL");
std::env::remove_var("APIMART_BASE_URL");
std::env::remove_var("APIMART_IMAGE_REQUEST_TIMEOUT_MS");
std::env::remove_var("VECTOR_ENGINE_BASE_URL");
std::env::remove_var("VECTOR_ENGINE_API_KEY");
std::env::remove_var("VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS");
std::env::remove_var("HYPER3D_BASE_URL");
std::env::remove_var("DASHSCOPE_SCENE_IMAGE_MODEL");
File diff suppressed because it is too large Load Diff
@@ -45,7 +45,7 @@ pub(crate) async fn enqueue_editor_generation_job<T>(
where
T: Serialize,
{
let job_id = build_prefixed_uuid_id("extgen-");
let job_id = build_prefixed_uuid_id("task-");
let request_payload_json = serde_json::to_string(payload).map_err(|error| {
AppError::from_status(StatusCode::INTERNAL_SERVER_ERROR).with_details(json!({
"provider": EDITOR_GENERATION_QUEUE_PROVIDER,
File diff suppressed because it is too large Load Diff
@@ -491,6 +491,7 @@ pub async fn create_external_editor_asset(
asset_kind: normalize_optional_string(payload.asset_kind),
generation_inputs_json,
source_resource_id: None,
generation_cost_mud_points: 0,
now_micros: current_utc_micros(),
thumbnail_src: None,
})
+1 -1
View File
@@ -300,7 +300,7 @@ async fn enqueue_jump_hop_compile_draft_job(
owner_user_id: &str,
payload: JumpHopActionRequest,
) -> Result<ExternalGenerationJobRecord, Response> {
let job_id = build_prefixed_uuid_id("extgen-");
let job_id = build_prefixed_uuid_id("task-");
let now_micros = current_utc_micros();
let price_mud_points = resolve_jump_hop_generation_points_cost(state).await;
let request_payload_json = serde_json::to_string(&JumpHopCompileDraftWorkerPayload {
File diff suppressed because it is too large Load Diff
+14 -11
View File
@@ -44,6 +44,8 @@ pub async fn proxy_llm_chat_completions(
max_tokens: None,
enable_web_search: false,
request_timeout_ms: None,
response_reasoning_effort: None,
response_text_verbosity: None,
};
if payload.stream {
@@ -189,13 +191,14 @@ mod tests {
body: r#"{"id":"resp_api_server_01","model":"ark-router-test","choices":[{"message":{"content":"代理成功"},"finish_reason":"stop"}]}"#.to_string(),
extra_headers: Vec::new(),
}]);
let state = seed_authenticated_state(AppConfig {
let (state, user_id) = seed_authenticated_state(AppConfig {
llm_base_url: server_url,
llm_api_key: Some("test-key".to_string()),
llm_model: "test-model".to_string(),
..AppConfig::default()
})
.await;
let token = issue_access_token(&state);
let token = issue_access_token(&state, &user_id);
let app = build_router(state);
let response = app
@@ -264,13 +267,14 @@ mod tests {
.to_string(),
extra_headers: vec![("x-request-id", "req_llm_stream_01")],
}]);
let state = seed_authenticated_state(AppConfig {
let (state, user_id) = seed_authenticated_state(AppConfig {
llm_base_url: server_url,
llm_api_key: Some("test-key".to_string()),
llm_model: "test-model".to_string(),
..AppConfig::default()
})
.await;
let token = issue_access_token(&state);
let token = issue_access_token(&state, &user_id);
let app = build_router(state);
let response = app
@@ -320,21 +324,20 @@ mod tests {
assert!(body_text.contains("data: [DONE]"));
}
async fn seed_authenticated_state(config: AppConfig) -> AppState {
async fn seed_authenticated_state(config: AppConfig) -> (AppState, String) {
let state = AppState::new(config).expect("state should build");
state
let user_id = state
.seed_test_phone_user_with_password("13800138101", "secret123")
.await
.id;
state
(state, user_id)
}
fn issue_access_token(state: &AppState) -> String {
fn issue_access_token(state: &AppState, user_id: &str) -> String {
let claims = AccessTokenClaims::from_input(
AccessTokenClaimsInput {
user_id: "user_00000001".to_string(),
session_id: state
.seed_test_refresh_session_for_user_id("user_00000001", "sess_llm_proxy"),
user_id: user_id.to_string(),
session_id: state.seed_test_refresh_session_for_user_id(user_id, "sess_llm_proxy"),
provider: AuthProvider::Password,
roles: vec!["user".to_string()],
token_version: 2,
+1
View File
@@ -36,6 +36,7 @@ mod custom_world_asset_prompts;
mod custom_world_foundation_draft;
mod custom_world_result_prompts;
mod custom_world_rpg_draft_prompts;
mod editor_agent;
mod editor_generation_config;
mod editor_generation_queue;
mod editor_green_screen;
@@ -6,11 +6,15 @@ use axum::{
use crate::{
admin::{
admin_dashboard, admin_debug_http, admin_get_creation_entry_config,
admin_get_editor_generation_pricing, admin_list_database_table_rows,
admin_list_database_tables, admin_list_tracking_event_keys, admin_list_tracking_events,
admin_list_work_visibility, admin_login, admin_me, admin_overview,
admin_update_work_visibility, admin_upsert_creation_entry_config,
admin_upsert_creation_entry_event_banners_config, admin_upsert_editor_generation_pricing,
admin_create_editor_showcase_campaign_image_upload_ticket,
admin_get_editor_generation_pricing, admin_get_editor_showcase_campaign,
admin_list_database_table_rows, admin_list_database_tables,
admin_list_editor_assets, admin_list_editor_showcase_assets, admin_list_tracking_event_keys,
admin_list_tracking_events, admin_list_work_visibility, admin_login, admin_me,
admin_overview, admin_review_editor_showcase_asset,
admin_update_editor_showcase_asset_display, admin_update_work_visibility,
admin_upsert_creation_entry_config, admin_upsert_creation_entry_event_banners_config,
admin_upsert_editor_generation_pricing, admin_upsert_editor_showcase_campaign,
admin_upsert_public_work_interaction_config, require_admin_auth,
},
runtime_profile::{
@@ -113,6 +117,48 @@ pub fn router(state: AppState) -> Router<AppState> {
require_admin_auth,
)),
)
.route(
"/admin/api/editor-assets",
get(admin_list_editor_assets).route_layer(middleware::from_fn_with_state(
state.clone(),
require_admin_auth,
)),
)
.route(
"/admin/api/editor-showcase/assets",
get(admin_list_editor_showcase_assets).route_layer(middleware::from_fn_with_state(
state.clone(),
require_admin_auth,
)),
)
.route(
"/admin/api/editor-showcase/assets/review",
post(admin_review_editor_showcase_asset).route_layer(middleware::from_fn_with_state(
state.clone(),
require_admin_auth,
)),
)
.route(
"/admin/api/editor-showcase/assets/display",
post(admin_update_editor_showcase_asset_display).route_layer(
middleware::from_fn_with_state(state.clone(), require_admin_auth),
),
)
.route(
"/admin/api/editor-showcase/campaign",
get(admin_get_editor_showcase_campaign)
.post(admin_upsert_editor_showcase_campaign)
.route_layer(middleware::from_fn_with_state(
state.clone(),
require_admin_auth,
)),
)
.route(
"/admin/api/editor-showcase/campaign/image-upload-ticket",
post(admin_create_editor_showcase_campaign_image_upload_ticket).route_layer(
middleware::from_fn_with_state(state.clone(), require_admin_auth),
),
)
.route(
"/admin/api/works/visibility",
get(admin_list_work_visibility)
@@ -7,6 +7,11 @@ use axum::{
use crate::{
auth::require_bearer_auth,
editor_agent::{
create_editor_agent_conversation, delete_editor_agent_conversation,
get_editor_agent_conversation, list_editor_agent_conversations,
stream_editor_agent_message,
},
editor_project::{
create_editor_asset, create_editor_asset_folder, create_editor_project,
create_editor_project_resource, delete_editor_asset, delete_editor_asset_folder,
@@ -15,12 +20,14 @@ use crate::{
get_editor_generation_pricing, get_editor_project, list_editor_projects,
list_public_editor_project_resources, load_recent_editor_project,
remove_editor_image_background, rename_editor_project, save_editor_project_layout,
update_editor_asset, update_editor_asset_folder, update_editor_project_resource_showcase,
submit_editor_asset_showcase, toggle_editor_showcase_asset_like, update_editor_asset,
update_editor_asset_folder, update_editor_project_resource_showcase,
},
state::AppState,
};
const EDITOR_IMAGE_REFERENCE_BODY_LIMIT_BYTES: usize = 12 * 1024 * 1024;
const EDITOR_AGENT_MESSAGE_BODY_LIMIT_BYTES: usize = 2 * 1024 * 1024;
pub fn router(state: AppState) -> Router<AppState> {
Router::new()
@@ -72,6 +79,33 @@ pub fn router(state: AppState) -> Router<AppState> {
require_bearer_auth,
)),
)
.route(
"/api/editor/projects/{project_id}/agent-conversations",
get(list_editor_agent_conversations)
.post(create_editor_agent_conversation)
.route_layer(middleware::from_fn_with_state(
state.clone(),
require_bearer_auth,
)),
)
.route(
"/api/editor/agent-conversations/{conversation_id}",
get(get_editor_agent_conversation)
.delete(delete_editor_agent_conversation)
.route_layer(middleware::from_fn_with_state(
state.clone(),
require_bearer_auth,
)),
)
.route(
"/api/editor/agent-conversations/{conversation_id}/messages/stream",
post(stream_editor_agent_message)
.layer(DefaultBodyLimit::max(EDITOR_AGENT_MESSAGE_BODY_LIMIT_BYTES))
.route_layer(middleware::from_fn_with_state(
state.clone(),
require_bearer_auth,
)),
)
.route(
"/api/editor/project-resources/{resource_id}/showcase",
patch(update_editor_project_resource_showcase).route_layer(
@@ -117,6 +151,20 @@ pub fn router(state: AppState) -> Router<AppState> {
require_bearer_auth,
)),
)
.route(
"/api/editor/assets/{asset_id}/showcase-submissions",
post(submit_editor_asset_showcase).route_layer(middleware::from_fn_with_state(
state.clone(),
require_bearer_auth,
)),
)
.route(
"/api/editor/showcase/assets/{showcase_id}/likes",
post(toggle_editor_showcase_asset_like).route_layer(middleware::from_fn_with_state(
state.clone(),
require_bearer_auth,
)),
)
.route(
"/api/editor/images/generations",
post(generate_editor_image)
@@ -764,7 +764,7 @@ pub async fn execute_puzzle_agent_action(
Some(&request_context),
PuzzleAgentActionResponse {
operation: PuzzleAgentOperationResponse {
operation_id: build_prefixed_uuid_id("extgen-inline-"),
operation_id: build_prefixed_uuid_id("task-inline-"),
operation_type: "compile_puzzle_draft".to_string(),
status: "completed".to_string(),
phase_label: "首关拼图草稿".to_string(),
@@ -803,7 +803,7 @@ pub async fn execute_puzzle_agent_action(
})),
)
})?;
let external_generation_job_id = build_prefixed_uuid_id("extgen-");
let external_generation_job_id = build_prefixed_uuid_id("task-");
let job = state
.spacetime_client()
.enqueue_external_generation_job(ExternalGenerationJobEnqueueRecordInput {
@@ -1002,7 +1002,7 @@ pub async fn execute_puzzle_agent_action(
Some(&request_context),
PuzzleAgentActionResponse {
operation: PuzzleAgentOperationResponse {
operation_id: build_prefixed_uuid_id("extgen-inline-"),
operation_id: build_prefixed_uuid_id("task-inline-"),
operation_type: "generate_puzzle_images".to_string(),
status: "completed".to_string(),
phase_label: "拼图图片生成".to_string(),
@@ -1025,7 +1025,7 @@ pub async fn execute_puzzle_agent_action(
})),
)
})?;
let external_generation_job_id = build_prefixed_uuid_id("extgen-");
let external_generation_job_id = build_prefixed_uuid_id("task-");
let source_entity_id = target_level_id
.as_deref()
.map(|level_id| format!("{session_id}:{level_id}"))
@@ -1145,7 +1145,7 @@ pub async fn execute_puzzle_agent_action(
Some(&request_context),
PuzzleAgentActionResponse {
operation: PuzzleAgentOperationResponse {
operation_id: build_prefixed_uuid_id("extgen-inline-"),
operation_id: build_prefixed_uuid_id("task-inline-"),
operation_type: "generate_puzzle_ui_background".to_string(),
status: "completed".to_string(),
phase_label: "UI 背景图生成".to_string(),
@@ -1168,7 +1168,7 @@ pub async fn execute_puzzle_agent_action(
})),
)
})?;
let external_generation_job_id = build_prefixed_uuid_id("extgen-");
let external_generation_job_id = build_prefixed_uuid_id("task-");
let source_entity_id = target_level_id
.as_deref()
.map(|level_id| format!("{session_id}:{level_id}"))
@@ -267,7 +267,7 @@ async fn enqueue_puzzle_clear_compile_draft_job(
author_display_name: &str,
payload: PuzzleClearActionRequest,
) -> Result<ExternalGenerationJobRecord, Response> {
let job_id = build_prefixed_uuid_id("extgen-");
let job_id = build_prefixed_uuid_id("task-");
let now_micros = current_utc_micros();
let request_payload_json = serde_json::to_string(&PuzzleClearCompileDraftWorkerPayload {
session_id: session_id.to_string(),
@@ -13,19 +13,18 @@ use module_runtime::{
PROFILE_RECHARGE_PAYMENT_CHANNEL_WECHAT_H5,
PROFILE_RECHARGE_PAYMENT_CHANNEL_WECHAT_MINI_PROGRAM,
PROFILE_RECHARGE_PAYMENT_CHANNEL_WECHAT_MINI_PROGRAM_VIRTUAL,
PROFILE_RECHARGE_PAYMENT_CHANNEL_WECHAT_NATIVE, RuntimeProfileFeedbackEvidenceRecord,
RuntimeProfileCodeOperationRecord, RuntimeProfileFeedbackEvidenceSnapshot,
PROFILE_RECHARGE_PAYMENT_CHANNEL_WECHAT_NATIVE, RuntimeProfileCodeOperationRecord,
RuntimeProfileFeedbackEvidenceRecord, RuntimeProfileFeedbackEvidenceSnapshot,
RuntimeProfileFeedbackSubmissionRecord, RuntimeProfileInviteCodeRecord,
RuntimeProfileMembershipBenefitRecord,
RuntimeProfileMembershipTier, RuntimeProfileRechargeCenterRecord,
RuntimeProfileRechargeOrderRecord, RuntimeProfileRechargeOrderStatus,
RuntimeProfileRechargeProductConfigRecord, RuntimeProfileRechargeProductKind,
RuntimeProfileRechargeProductRecord, RuntimeProfileRedeemCodeMode,
RuntimeProfileRedeemCodeRecord, RuntimeProfileRewardCodeRedeemRecord,
RuntimeProfileTaskCenterRecord, RuntimeProfileTaskClaimRecord, RuntimeProfileTaskConfigRecord,
RuntimeProfileTaskCycle, RuntimeProfileTaskItemRecord, RuntimeProfileTaskStatus,
RuntimeProfileWalletLedgerSourceType, RuntimeReferralInviteCenterRecord,
RuntimeTrackingScopeKind,
RuntimeProfileMembershipBenefitRecord, RuntimeProfileMembershipTier,
RuntimeProfileRechargeCenterRecord, RuntimeProfileRechargeOrderRecord,
RuntimeProfileRechargeOrderStatus, RuntimeProfileRechargeProductConfigRecord,
RuntimeProfileRechargeProductKind, RuntimeProfileRechargeProductRecord,
RuntimeProfileRedeemCodeMode, RuntimeProfileRedeemCodeRecord,
RuntimeProfileRewardCodeRedeemRecord, RuntimeProfileTaskCenterRecord,
RuntimeProfileTaskClaimRecord, RuntimeProfileTaskConfigRecord, RuntimeProfileTaskCycle,
RuntimeProfileTaskItemRecord, RuntimeProfileTaskStatus, RuntimeProfileWalletLedgerSourceType,
RuntimeReferralInviteCenterRecord, RuntimeTrackingScopeKind,
};
use platform_wechat::pay::WechatPayNotifyOrder;
use serde::{Deserialize, Serialize};
@@ -53,18 +52,17 @@ use shared_contracts::runtime::{
PROFILE_WALLET_LEDGER_SOURCE_TYPE_POINTS_RECHARGE,
PROFILE_WALLET_LEDGER_SOURCE_TYPE_PUZZLE_AUTHOR_INCENTIVE_CLAIM,
PROFILE_WALLET_LEDGER_SOURCE_TYPE_REDEEM_CODE_REWARD,
PROFILE_WALLET_LEDGER_SOURCE_TYPE_SNAPSHOT_SYNC, ProfileDashboardSummaryResponse,
ProfileCodeOperationAdminResponse, ProfileFeedbackEvidenceItemResponse,
PROFILE_WALLET_LEDGER_SOURCE_TYPE_SNAPSHOT_SYNC, ProfileCodeOperationAdminResponse,
ProfileDashboardSummaryResponse, ProfileFeedbackEvidenceItemResponse,
ProfileFeedbackSubmissionResponse, ProfileInviteCodeAdminListResponse,
ProfileInviteCodeAdminResponse,
ProfileMembershipBenefitResponse, ProfileMembershipResponse, ProfilePlayStatsResponse,
ProfilePlayedWorkSummaryResponse, ProfileRechargeCenterResponse, ProfileRechargeOrderResponse,
ProfileRechargeProductConfigAdminListResponse, ProfileRechargeProductConfigAdminResponse,
ProfileRechargeProductResponse, ProfileRedeemCodeAdminListResponse,
ProfileRedeemCodeAdminResponse, ProfileReferralInviteCenterResponse,
ProfileReferralInvitedUserResponse, ProfileTaskCenterResponse,
ProfileTaskConfigAdminListResponse, ProfileTaskConfigAdminResponse, ProfileTaskItemResponse,
ProfileWalletConfigAdminResponse, ProfileWalletLedgerEntryResponse,
ProfileInviteCodeAdminResponse, ProfileMembershipBenefitResponse, ProfileMembershipResponse,
ProfilePlayStatsResponse, ProfilePlayedWorkSummaryResponse, ProfileRechargeCenterResponse,
ProfileRechargeOrderResponse, ProfileRechargeProductConfigAdminListResponse,
ProfileRechargeProductConfigAdminResponse, ProfileRechargeProductResponse,
ProfileRedeemCodeAdminListResponse, ProfileRedeemCodeAdminResponse,
ProfileReferralInviteCenterResponse, ProfileReferralInvitedUserResponse,
ProfileTaskCenterResponse, ProfileTaskConfigAdminListResponse, ProfileTaskConfigAdminResponse,
ProfileTaskItemResponse, ProfileWalletConfigAdminResponse, ProfileWalletLedgerEntryResponse,
ProfileWalletLedgerResponse, RedeemProfileReferralInviteCodeRequest,
RedeemProfileReferralInviteCodeResponse, RedeemProfileRewardCodeRequest,
RedeemProfileRewardCodeResponse, SubmitProfileFeedbackRequest, SubmitProfileFeedbackResponse,
+4 -5
View File
@@ -1507,8 +1507,7 @@ fn build_creative_agent_gpt5_client(
config.llm_request_timeout_ms,
0,
config.llm_retry_backoff_ms,
)?
.with_official_fallback(true);
)?;
Ok(Some(LlmClient::new(llm_config)?))
}
@@ -1641,10 +1640,10 @@ mod tests {
platform_agent::CREATIVE_AGENT_GPT5_MODEL
);
assert_eq!(
client.config().responses_url(),
"https://api.vectorengine.test/v1/responses"
client.config().chat_completions_url(),
"https://api.vectorengine.test/v1/chat/completions"
);
assert!(client.config().official_fallback());
assert!(!client.config().official_fallback());
}
#[test]
@@ -268,6 +268,7 @@ pub(crate) async fn generate_editor_sound_effect_for_owner(
asset_kind: Some("sound-effect".to_string()),
generation_inputs: generation_inputs.clone(),
thumbnail_src: None,
generation_cost_mud_points: u64::from(normalized.price_mud_points),
},
)
.await
@@ -486,6 +487,7 @@ pub(crate) async fn generate_editor_background_music_for_owner(
asset_kind: Some("background-music".to_string()),
generation_inputs: generation_inputs.clone(),
thumbnail_src: None,
generation_cost_mud_points: u64::from(normalized.price_mud_points),
},
)
.await
@@ -285,7 +285,7 @@ async fn enqueue_wooden_fish_generate_image_assets_job(
author_display_name: &str,
payload: WoodenFishActionRequest,
) -> Result<ExternalGenerationJobRecord, Response> {
let job_id = build_prefixed_uuid_id("extgen-");
let job_id = build_prefixed_uuid_id("task-");
let now_micros = current_utc_micros();
let price_mud_points = resolve_wooden_fish_generation_points_cost(state).await;
let request_payload_json = serde_json::to_string(&WoodenFishGenerateImageAssetsWorkerPayload {