import { requestJson } from '../apiClient'; import type { ExternalGenerationJobStatusRecord } from '../../../packages/shared/src/contracts/externalGeneration'; import { EDITOR_REQUEST_RETRY_OPTIONS } from './editorRetryOptions'; const EDITOR_PROJECT_API_BASE = '/api/editor/projects'; const EDITOR_ASSET_API_BASE = '/api/editor/assets'; const EDITOR_SHOWCASE_RESOURCE_API = '/api/editor/showcase/resources'; const EDITOR_PROJECT_RESOURCE_API_BASE = '/api/editor/project-resources'; const EDITOR_IMAGE_GENERATION_API = '/api/editor/images/generations'; const EDITOR_IMAGE_EDIT_API = '/api/editor/images/edits'; const EDITOR_ICON_SPRITESHEET_GENERATION_API = '/api/editor/icon-spritesheets/generations'; const EDITOR_UI_DESIGN_ASSET_EXTRACTION_API = '/api/editor/ui-designs/assets/extractions'; const EDITOR_CHARACTER_ANIMATION_GENERATION_API = '/api/editor/character-animations/generations'; const EDITOR_VIDEO_GENERATION_API = '/api/editor/videos/generations'; const EDITOR_SOUND_EFFECT_GENERATION_API = '/api/editor/audios/sound-effects/generations'; const EDITOR_BACKGROUND_MUSIC_GENERATION_API = '/api/editor/audios/background-music/generations'; const EDITOR_GENERATION_PRICING_API = '/api/editor/generation-pricing'; const EDITOR_IMAGE_MODEL_NANOBANANA2 = 'gemini-3.1-flash-image-preview'; const DEFAULT_PROJECT_TITLE = '未命名画布'; export type EditorCanvasViewport = { x: number; y: number; scale: number; }; export type EditorProjectLayerSnapshot = Record & { layerId: string; resourceId: string; }; export type EditorAssetGenerationInputField = { title: string; value: string; }; export type EditorAssetGenerationInputReference = { title: string; label: string; refType: 'project-resource' | 'asset'; refId: string; }; export type EditorAssetGenerationInputs = { fields: EditorAssetGenerationInputField[]; references: EditorAssetGenerationInputReference[]; }; export type EditorProjectResourceSourceType = | 'uploaded' | 'generated' | 'mock_generated'; export type EditorProjectResourceSnapshot = { resourceId: string; projectId: string; ownerUserId?: string | null; authorDisplayName?: string | null; authorPublicUserCode?: string | null; imageSrc: string; objectKey?: string | null; assetObjectId?: string | null; width: number; height: number; sourceType: EditorProjectResourceSourceType; prompt?: string | null; actualPrompt?: string | null; model?: string | null; provider?: string | null; taskId?: string | null; durationSeconds?: number | null; sourceResourceId?: string | null; assetKind?: string | null; generationInputs?: EditorAssetGenerationInputs | null; publicShowcaseEnabled?: boolean; createdAt?: string; updatedAt?: string; }; export type EditorAssetFolderSnapshot = { folderId: string; label: string; sortOrder: number; collapsed: boolean; systemDefault: boolean; createdAt?: string; updatedAt?: string; }; export type EditorAssetSnapshot = { assetId: string; folderId: string; label: string; imageSrc: string; thumbnailSrc?: string | null; objectKey?: string | null; assetObjectId?: string | null; width: number; height: number; sourceType: EditorProjectResourceSourceType; prompt?: string | null; actualPrompt?: string | null; model?: string | null; provider?: string | null; taskId?: string | null; durationSeconds?: number | null; sourceResourceId?: string | null; assetKind?: string | null; generationInputs?: EditorAssetGenerationInputs | null; publicShowcaseEnabled?: boolean | null; createdAt?: string; updatedAt?: string; }; export type EditorAssetLibrarySnapshot = { folders: EditorAssetFolderSnapshot[]; assets: EditorAssetSnapshot[]; }; export type EditorImageGenerationInput = { prompt: string; size?: string; kind?: | 'spec' | 'character' | 'quick-edit' | 'ui-design' | 'publication-material'; model?: string; aspectRatio?: string; imageSize?: string; referenceImageSrcs?: string[]; projectId?: string | null; assetKind?: string | null; generationInputs?: EditorAssetGenerationInputs | null; assetFolderId?: string | null; assetLabel?: string | null; sourceResourceId?: string | null; canvasCompletion?: EditorCanvasGenerationCompletionInput | null; }; export type EditorCanvasGenerationCompletionInput = { dialogId?: string; title: string; placeholder: { x: number; y: number; width: number; height: number; originalWidth: number; originalHeight: number; }; }; export type EditorIconSpritesheetGenerationInput = { referenceImageSrc: string; referenceImageSrcs?: string[]; iconDescriptions: string[]; model?: string; aspectRatio?: string; imageSize?: string; projectId?: string | null; generationInputs?: EditorAssetGenerationInputs | null; assetFolderId?: string | null; canvasCompletion?: EditorCanvasGenerationCompletionInput | null; }; export type EditorUiDesignAssetExtractionInput = { sourceImageSrc: string; model?: string; referenceImageSrcs?: string[]; aspectRatio?: string; imageSize?: string; projectId?: string | null; generationInputs?: EditorAssetGenerationInputs | null; assetFolderId?: string | null; spritesheetLabel?: string | null; canvasCompletion?: EditorCanvasGenerationCompletionInput | null; }; export type EditorImageEditInput = { prompt: string; sourceImageSrc: string; size?: string; model?: string; projectId?: string | null; assetKind?: string | null; generationInputs?: EditorAssetGenerationInputs | null; assetFolderId?: string | null; assetLabel?: string | null; sourceResourceId?: string | null; canvasCompletion?: EditorCanvasGenerationCompletionInput | null; }; export type EditorImageGenerationResult = { imageSrc: string; objectKey?: string | null; assetObjectId?: string | null; width: number; height: number; sourceType: 'generated'; prompt: string; actualPrompt?: string | null; model: string; provider: string; taskId: string; resource?: EditorProjectResourceSnapshot | null; asset?: EditorAssetSnapshot | null; project?: EditorProjectSnapshot | null; queueState?: ExternalGenerationJobStatusRecord | null; }; export type EditorIconSpritesheetIconResult = { name: string; imageSrc: string; width: number; height: number; resource?: EditorProjectResourceSnapshot | null; asset?: EditorAssetSnapshot | null; }; export type EditorIconSpritesheetGenerationResult = { spritesheetImageSrc: string; spritesheetWidth: number; spritesheetHeight: number; iconImageSrcs: EditorIconSpritesheetIconResult[]; prompt: string; actualPrompt?: string | null; model: string; provider: string; taskId: string; priceMudPoints: number; spritesheetResource?: EditorProjectResourceSnapshot | null; spritesheetAsset?: EditorAssetSnapshot | null; project?: EditorProjectSnapshot | null; queueState?: ExternalGenerationJobStatusRecord | null; }; export type EditorCharacterAnimationResolution = '480p' | '720p'; export type EditorCharacterAnimationRatio = | 'same' | '1:1' | '4:3' | '16:9' | '9:16' | '3:4'; export type EditorCharacterAnimationFrameCount = 32 | 40 | 48; export type EditorCharacterAnimationDurationSeconds = 4 | 5 | 6; export type EditorCharacterAnimationGenerationInput = { sourceLayerId: string; sourceImageSrc: string; sourceWidth: number; sourceHeight: number; promptText: string; resolution: EditorCharacterAnimationResolution; ratio: EditorCharacterAnimationRatio; frameCount: EditorCharacterAnimationFrameCount; durationSeconds: EditorCharacterAnimationDurationSeconds; model: 'seedance2.0-fast'; projectId?: string | null; canvasCompletion?: EditorCanvasGenerationCompletionInput | null; generationInputs?: EditorAssetGenerationInputs | null; sourceResourceId?: string | null; }; export type EditorCharacterAnimationFrameResult = { frameIndex: number; imageSrc: string; objectKey?: string | null; assetObjectId?: string | null; width: number; height: number; }; export type EditorCharacterAnimationGenerationResult = { taskId: string; model: 'seedance2.0-fast'; prompt: string; previewVideoPath: string; frames: EditorCharacterAnimationFrameResult[]; frameCount: number; durationSeconds: number; fps: number; priceMudPoints: number; project?: EditorProjectSnapshot | null; queueState?: ExternalGenerationJobStatusRecord | null; }; export type EditorVideoModel = | 'seedance2.0' | 'seedance2.0-fast' | 'kling3.0' | 'kling3.0-omni' | 'veo3.1' | 'veo3.1-fast'; export type EditorVideoResolution = '480p' | '720p' | '1080p'; export type EditorVideoSoundMode = 'on' | 'off'; export type EditorVideoAspectRatio = | '16:9' | '9:16' | '1:1' | '4:3' | '3:4' | '21:9'; export type EditorVideoGenerationInput = { prompt: string; model: EditorVideoModel; aspectRatio: EditorVideoAspectRatio; durationSeconds: number; resolution: EditorVideoResolution; mode: 'std'; sound: EditorVideoSoundMode; webSearchEnabled?: boolean; referenceImageSrcs?: string[]; referenceVideoSrcs?: string[]; referenceAudioSrcs?: string[]; projectId?: string | null; canvasCompletion?: EditorCanvasGenerationCompletionInput | null; generationInputs?: EditorAssetGenerationInputs | null; sourceResourceId?: string | null; assetKind?: string | null; assetFolderId?: string | null; assetLabel?: string | null; }; export type EditorVideoGenerationResult = { videoSrc: string; thumbnailSrc?: string | null; objectKey?: string | null; assetObjectId?: string | null; width: number; height: number; sourceType: 'generated'; prompt: string; actualPrompt?: string | null; model: string; provider: string; taskId: string; durationSeconds: number; priceMudPoints?: number; project?: EditorProjectSnapshot | null; asset?: EditorAssetSnapshot | null; queueState?: ExternalGenerationJobStatusRecord | null; }; export type EditorSoundEffectGenerationInput = { prompt: string; model: 'audio1.0'; duration: number; projectId?: string | null; canvasCompletion?: EditorCanvasGenerationCompletionInput | null; generationInputs?: EditorAssetGenerationInputs | null; }; export type EditorBackgroundMusicGenerationInput = { gptDescriptionPrompt: string; makeInstrumental: true; projectId?: string | null; canvasCompletion?: EditorCanvasGenerationCompletionInput | null; generationInputs?: EditorAssetGenerationInputs | null; }; export type EditorAudioGenerationResult = { audioSrc: string; objectKey?: string | null; assetObjectId?: string | null; width: number; height: number; sourceType: 'generated'; prompt: string; actualPrompt?: string | null; model: string; provider: string; taskId: string; priceMudPoints: number; audioKind: 'sound-effect' | 'background-music'; durationSeconds?: number | null; project?: EditorProjectSnapshot | null; queueState?: ExternalGenerationJobStatusRecord | null; }; export type EditorGenerationPricingUnit = 'perGeneration' | 'perSecond'; export type EditorGenerationModelPricing = { unit: EditorGenerationPricingUnit; price?: number; prices?: Record; }; export type EditorGenerationPricingConfig = { models: Record; }; export type EditorProjectSnapshot = { projectId: string; title: string; canvas?: EditorCanvasSnapshot; viewport: EditorCanvasViewport; layers: EditorProjectLayerSnapshot[]; resources: EditorProjectResourceSnapshot[]; updatedAt: string; }; export type EditorCanvasSnapshot = { canvasId: string; projectId: string; title: string; viewport: EditorCanvasViewport; layers: EditorProjectLayerSnapshot[]; createdAt?: string; updatedAt: string; }; export type EditorProjectCreateInput = { title?: string; }; export type EditorProjectLayoutSaveInput = { viewport: EditorCanvasViewport; layers: EditorProjectLayerSnapshot[]; }; export type EditorProjectLayoutSaveResult = { projectId: string; canvasId: string; updatedAt: string; }; export type EditorProjectResourceCreateInput = { imageSrc: string; objectKey?: string | null; assetObjectId?: string | null; width: number; height: number; sourceType: EditorProjectResourceSourceType; prompt?: string | null; actualPrompt?: string | null; model?: string | null; provider?: string | null; taskId?: string | null; durationSeconds?: number | null; sourceResourceId?: string | null; assetKind?: string | null; generationInputs?: EditorAssetGenerationInputs | null; }; export type EditorAssetCreateInput = { folderId: string; label: string; imageSrc: string; objectKey?: string | null; assetObjectId?: string | null; width: number; height: number; sourceType: EditorProjectResourceSourceType; prompt?: string | null; actualPrompt?: string | null; model?: string | null; provider?: string | null; taskId?: string | null; durationSeconds?: number | null; assetKind?: string | null; generationInputs?: EditorAssetGenerationInputs | null; }; export type EditorAssetUpdateInput = { label?: string; folderId?: string; }; type EditorProjectResponse = { project: EditorProjectSnapshot; }; type EditorProjectLayoutSaveResponse = EditorProjectLayoutSaveResult; type EditorProjectRecentResponse = { project: EditorProjectSnapshot | null; }; type EditorProjectResourceResponse = { resource: EditorProjectResourceSnapshot; }; type EditorProjectResourceListResponse = { resources: EditorProjectResourceSnapshot[]; }; type EditorAssetLibraryResponse = { library: EditorAssetLibrarySnapshot; }; type EditorAssetFolderResponse = { folder: EditorAssetFolderSnapshot; }; type EditorAssetFolderDeleteResponse = { library: EditorAssetLibrarySnapshot; }; type EditorAssetResponse = { asset: EditorAssetSnapshot; }; type EditorImageGenerationResponse = EditorImageGenerationResult; type EditorIconSpritesheetGenerationResponse = EditorIconSpritesheetGenerationResult; type EditorVideoGenerationResponse = EditorVideoGenerationResult; type EditorAudioGenerationResponse = EditorAudioGenerationResult; function jsonRequest(method: 'POST' | 'PATCH', body: Record) { return { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }; } export async function listEditorProjects() { const response = await requestJson<{ projects: EditorProjectSnapshot[] }>( EDITOR_PROJECT_API_BASE, { method: 'GET' }, '读取图片画布工程列表失败', ); return response.projects; } export async function listPublicEditorProjectResources() { const response = await requestJson( EDITOR_SHOWCASE_RESOURCE_API, { method: 'GET' }, '读取陶泥儿精选素材失败', { skipAuth: true, skipRefresh: true, notifyAuthStateChange: false, clearAuthOnUnauthorized: false, }, ); return response.resources; } export async function loadRecentEditorProject() { return requestJson( `${EDITOR_PROJECT_API_BASE}/recent`, { method: 'GET' }, '读取图片画布工程失败', ); } export async function createEditorProject( input: EditorProjectCreateInput = {}, ) { const response = await requestJson( EDITOR_PROJECT_API_BASE, jsonRequest('POST', { title: input.title?.trim() || DEFAULT_PROJECT_TITLE, }), '创建图片画布工程失败', ); return response.project; } export async function loadOrCreateRecentEditorProject() { const response = await loadRecentEditorProject(); if (response.project) { return response.project; } return createEditorProject({ title: DEFAULT_PROJECT_TITLE }); } export async function loadEditorGenerationPricing() { return requestJson( EDITOR_GENERATION_PRICING_API, { method: 'GET' }, '读取模型定价失败', { skipAuth: true, skipRefresh: true, notifyAuthStateChange: false, clearAuthOnUnauthorized: false, }, ); } export async function loadEditorProject(projectId: string) { const response = await requestJson( `${EDITOR_PROJECT_API_BASE}/${encodeURIComponent(projectId)}`, { method: 'GET' }, '读取图片画布工程失败', ); return response.project; } export async function renameEditorProject(projectId: string, title: string) { const response = await requestJson( `${EDITOR_PROJECT_API_BASE}/${encodeURIComponent(projectId)}/metadata`, jsonRequest('PATCH', { title }), '重命名图片画布工程失败', ); return response.project; } export async function deleteEditorProject(projectId: string) { const response = await requestJson<{ deletedProjectId: string }>( `${EDITOR_PROJECT_API_BASE}/${encodeURIComponent(projectId)}`, { method: 'DELETE' }, '删除图片画布工程失败', ); return response.deletedProjectId; } export async function saveEditorProjectLayout( projectId: string, input: EditorProjectLayoutSaveInput, ) { return requestJson( `${EDITOR_PROJECT_API_BASE}/${encodeURIComponent(projectId)}`, jsonRequest('PATCH', { viewport: input.viewport, layers: input.layers, }), '保存图片画布工程失败', ); } export async function createEditorProjectResource( projectId: string, input: EditorProjectResourceCreateInput, ) { const response = await requestJson( `${EDITOR_PROJECT_API_BASE}/${encodeURIComponent(projectId)}/resources`, jsonRequest('POST', { ...input }), '创建图片画布资源失败', ); return response.resource; } export async function updateEditorProjectResourceShowcase( resourceId: string, publicShowcaseEnabled: boolean, ) { const response = await requestJson( `${EDITOR_PROJECT_RESOURCE_API_BASE}/${encodeURIComponent(resourceId)}/showcase`, jsonRequest('PATCH', { publicShowcaseEnabled }), '更新素材公开展示状态失败', ); return response.resource; } export async function loadEditorAssetLibrary() { const response = await requestJson( `${EDITOR_ASSET_API_BASE}/library`, { method: 'GET' }, '读取图片画布素材库失败', ); return response.library; } export async function createEditorAssetFolder( label: string, sortOrder?: number, ) { const response = await requestJson( `${EDITOR_ASSET_API_BASE}/folders`, jsonRequest('POST', { label, sortOrder }), '创建图片画布素材文件夹失败', ); return response.folder; } export async function updateEditorAssetFolder( folderId: string, input: { label?: string; collapsed?: boolean }, ) { const response = await requestJson( `${EDITOR_ASSET_API_BASE}/folders/${encodeURIComponent(folderId)}`, jsonRequest('PATCH', input), '更新图片画布素材文件夹失败', ); return response.folder; } export async function deleteEditorAssetFolder(folderId: string) { const response = await requestJson( `${EDITOR_ASSET_API_BASE}/folders/${encodeURIComponent(folderId)}`, { method: 'DELETE' }, '删除图片画布素材文件夹失败', ); return response.library; } export async function createEditorAsset(input: EditorAssetCreateInput) { const response = await requestJson( EDITOR_ASSET_API_BASE, jsonRequest('POST', input), '创建图片画布素材失败', ); return response.asset; } export async function updateEditorAsset( assetId: string, input: EditorAssetUpdateInput, ) { const response = await requestJson( `${EDITOR_ASSET_API_BASE}/${encodeURIComponent(assetId)}`, jsonRequest('PATCH', input), '更新图片画布素材失败', ); return response.asset; } export async function deleteEditorAsset(assetId: string) { const response = await requestJson( `${EDITOR_ASSET_API_BASE}/${encodeURIComponent(assetId)}`, { method: 'DELETE' }, '删除图片画布素材失败', ); return response.asset; } export async function generateEditorImage(input: EditorImageGenerationInput) { return requestJson( EDITOR_IMAGE_GENERATION_API, jsonRequest('POST', { prompt: input.prompt, ...(input.size ? { size: input.size } : {}), ...(input.kind ? { kind: input.kind } : {}), ...(input.model ? { model: input.model } : {}), ...(input.aspectRatio ? { aspectRatio: input.aspectRatio } : {}), ...(input.imageSize ? { imageSize: input.imageSize } : {}), ...(input.referenceImageSrcs?.length ? { referenceImageSrcs: input.referenceImageSrcs } : {}), ...(input.projectId ? { projectId: input.projectId } : {}), ...(input.assetKind ? { assetKind: input.assetKind } : {}), ...(input.generationInputs ? { generationInputs: input.generationInputs } : {}), ...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}), ...(input.assetLabel ? { assetLabel: input.assetLabel } : {}), ...(input.sourceResourceId ? { sourceResourceId: input.sourceResourceId } : {}), ...(input.canvasCompletion ? { canvasCompletion: input.canvasCompletion } : {}), }), '生成图片失败', { timeoutMs: 1_200_000, retry: EDITOR_REQUEST_RETRY_OPTIONS, }, ); } export async function generateEditorIconSpritesheet( input: EditorIconSpritesheetGenerationInput, ) { return requestJson( EDITOR_ICON_SPRITESHEET_GENERATION_API, jsonRequest('POST', { referenceImageSrc: input.referenceImageSrc, ...(input.referenceImageSrcs?.length ? { referenceImageSrcs: input.referenceImageSrcs } : {}), iconDescriptions: input.iconDescriptions, model: input.model?.trim() || EDITOR_IMAGE_MODEL_NANOBANANA2, ...(input.aspectRatio ? { aspectRatio: input.aspectRatio } : {}), ...(input.imageSize ? { imageSize: input.imageSize } : {}), ...(input.projectId ? { projectId: input.projectId } : {}), ...(input.generationInputs ? { generationInputs: input.generationInputs } : {}), ...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}), ...(input.canvasCompletion ? { canvasCompletion: input.canvasCompletion } : {}), }), '生成图标素材失败', { timeoutMs: 1_200_000, retry: EDITOR_REQUEST_RETRY_OPTIONS, }, ); } export async function extractEditorUiDesignAssets( input: EditorUiDesignAssetExtractionInput, ) { return requestJson( EDITOR_UI_DESIGN_ASSET_EXTRACTION_API, jsonRequest('POST', { sourceImageSrc: input.sourceImageSrc, ...(input.model ? { model: input.model } : {}), ...(input.referenceImageSrcs?.length ? { referenceImageSrcs: input.referenceImageSrcs } : {}), ...(input.projectId ? { projectId: input.projectId } : {}), ...(input.generationInputs ? { generationInputs: input.generationInputs } : {}), ...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}), ...(input.spritesheetLabel ? { spritesheetLabel: input.spritesheetLabel } : {}), ...(input.aspectRatio ? { aspectRatio: input.aspectRatio } : {}), ...(input.imageSize ? { imageSize: input.imageSize } : {}), ...(input.canvasCompletion ? { canvasCompletion: input.canvasCompletion } : {}), }), '提取UI设计图素材失败', { timeoutMs: 1_200_000, retry: EDITOR_REQUEST_RETRY_OPTIONS, }, ); } export async function editEditorImage(input: EditorImageEditInput) { return requestJson( EDITOR_IMAGE_EDIT_API, jsonRequest('POST', { prompt: input.prompt, sourceImageSrc: input.sourceImageSrc, ...(input.size ? { size: input.size } : {}), ...(input.model ? { model: input.model } : {}), ...(input.projectId ? { projectId: input.projectId } : {}), ...(input.assetKind ? { assetKind: input.assetKind } : {}), ...(input.generationInputs ? { generationInputs: input.generationInputs } : {}), ...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}), ...(input.assetLabel ? { assetLabel: input.assetLabel } : {}), ...(input.sourceResourceId ? { sourceResourceId: input.sourceResourceId } : {}), ...(input.canvasCompletion ? { canvasCompletion: input.canvasCompletion } : {}), }), '修改图片失败', { timeoutMs: 1_200_000, retry: EDITOR_REQUEST_RETRY_OPTIONS, }, ); } export async function generateEditorCharacterAnimation( input: EditorCharacterAnimationGenerationInput, ) { return requestJson( EDITOR_CHARACTER_ANIMATION_GENERATION_API, jsonRequest('POST', { ...input, ...(input.projectId ? { projectId: input.projectId } : {}), ...(input.canvasCompletion ? { canvasCompletion: input.canvasCompletion } : {}), ...(input.generationInputs ? { generationInputs: input.generationInputs } : {}), ...(input.sourceResourceId ? { sourceResourceId: input.sourceResourceId } : {}), }), '生成角色动画失败', { timeoutMs: 1_200_000, retry: EDITOR_REQUEST_RETRY_OPTIONS, }, ); } export async function generateEditorVideo(input: EditorVideoGenerationInput) { return requestJson( EDITOR_VIDEO_GENERATION_API, jsonRequest('POST', { prompt: input.prompt, model: input.model, aspectRatio: input.aspectRatio, durationSeconds: input.durationSeconds, resolution: input.resolution, mode: input.mode, sound: input.sound, webSearchEnabled: input.webSearchEnabled ?? true, ...(input.referenceImageSrcs?.length ? { referenceImageSrcs: input.referenceImageSrcs } : {}), ...(input.referenceVideoSrcs?.length ? { referenceVideoSrcs: input.referenceVideoSrcs } : {}), ...(input.referenceAudioSrcs?.length ? { referenceAudioSrcs: input.referenceAudioSrcs } : {}), ...(input.projectId ? { projectId: input.projectId } : {}), ...(input.canvasCompletion ? { canvasCompletion: input.canvasCompletion } : {}), ...(input.generationInputs ? { generationInputs: input.generationInputs } : {}), ...(input.sourceResourceId ? { sourceResourceId: input.sourceResourceId } : {}), ...(input.assetKind ? { assetKind: input.assetKind } : {}), ...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}), ...(input.assetLabel ? { assetLabel: input.assetLabel } : {}), }), '生成视频失败', { timeoutMs: 1_200_000, retry: EDITOR_REQUEST_RETRY_OPTIONS, }, ); } export async function generateEditorSoundEffect( input: EditorSoundEffectGenerationInput, ) { return requestJson( EDITOR_SOUND_EFFECT_GENERATION_API, jsonRequest('POST', { prompt: input.prompt, model: input.model, duration: input.duration, ...(input.projectId ? { projectId: input.projectId } : {}), ...(input.canvasCompletion ? { canvasCompletion: input.canvasCompletion } : {}), ...(input.generationInputs ? { generationInputs: input.generationInputs } : {}), }), '生成游戏音效失败', { timeoutMs: 1_200_000, retry: EDITOR_REQUEST_RETRY_OPTIONS, }, ); } export async function generateEditorBackgroundMusic( input: EditorBackgroundMusicGenerationInput, ) { return requestJson( EDITOR_BACKGROUND_MUSIC_GENERATION_API, jsonRequest('POST', { gptDescriptionPrompt: input.gptDescriptionPrompt, makeInstrumental: input.makeInstrumental, ...(input.projectId ? { projectId: input.projectId } : {}), ...(input.canvasCompletion ? { canvasCompletion: input.canvasCompletion } : {}), ...(input.generationInputs ? { generationInputs: input.generationInputs } : {}), }), '生成游戏背景音乐失败', { timeoutMs: 1_200_000, retry: EDITOR_REQUEST_RETRY_OPTIONS, }, ); }