3de9341a9c
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 4m30s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 4m44s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m37s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m6s
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 5m9s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m26s
Project CI / Native shell tests (pull_request) Successful in 19m40s
Project CI / Frontend tests (pull_request) Successful in 21m8s
Project CI / Repository checks (pull_request) Successful in 21m29s
Project CI / Backend tests (pull_request) Successful in 27m41s
Project CI / AI game creator shell web tests (pull_request) Successful in 19m50s
合并 origin/master 的最新功能与测试变更 保留已删除的策划 Agent V1/V2 运行时和旧 GDD 入口 仅解决资源预览类型冲突,不恢复退役策划调用
1702 lines
54 KiB
TypeScript
1702 lines
54 KiB
TypeScript
import {
|
|
type BackgroundMusicPromptAssistRequest,
|
|
type BackgroundMusicPromptAssistResponse,
|
|
type EditorSoundEffectGenerationMetadataV2,
|
|
type EditorSoundEffectGenerationRequest,
|
|
SOUND_EFFECT_DURATION_MAX_SECONDS,
|
|
SOUND_EFFECT_DURATION_MIN_SECONDS,
|
|
type SoundEffectPromptOptimizeRequest,
|
|
type SoundEffectPromptOptimizeResponse,
|
|
} from '../../../packages/shared/src/contracts/editorAudio';
|
|
import type { EditorSceneGenerationRequest } from '../../../packages/shared/src/contracts/editorScene';
|
|
import type { ExternalGenerationJobStatusRecord } from '../../../packages/shared/src/contracts/externalGeneration';
|
|
import { requestJson } from '../apiClient';
|
|
import { EDITOR_GENERATION_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_SHOWCASE_ASSET_API_BASE = '/api/editor/showcase/assets';
|
|
const EDITOR_PROJECT_RESOURCE_API_BASE = '/api/editor/project-resources';
|
|
const EDITOR_IMAGE_GENERATION_API = '/api/editor/images/generations';
|
|
const EDITOR_SCENE_GENERATION_API = '/api/editor/scenes/generations';
|
|
const EDITOR_ICON_SPEC_GENERATION_API = '/api/editor/icon-specs/generations';
|
|
const EDITOR_ICON_SPEC_REFINE_GAME_PLAY_API =
|
|
'/api/editor/llm/icon-specs/refine-game-play';
|
|
const EDITOR_ICON_SPEC_REFINE_ART_STYLE_API =
|
|
'/api/editor/llm/icon-specs/refine-art-style';
|
|
export const EDITOR_ICON_SPEC_PROMPT_MAX_LENGTH = 200;
|
|
export const EDITOR_ICON_DESCRIPTION_LIMIT = 100;
|
|
export const EDITOR_ICON_DESCRIPTION_MAX_CHARS = 200;
|
|
export const EDITOR_ICON_DESCRIPTIONS_MAX_TOTAL_CHARS = 2_000;
|
|
export const EDITOR_ICON_DESCRIPTIONS_MAX_TOTAL_UTF8_BYTES = 6 * 1024;
|
|
const EDITOR_IMAGE_EDIT_API = '/api/editor/images/edits';
|
|
const EDITOR_BACKGROUND_REMOVAL_API = '/api/editor/images/background-removals';
|
|
const EDITOR_PIXEL_ART_SNAP_API = '/api/editor/images/pixel-art-snaps';
|
|
const EDITOR_ICON_SPRITESHEET_GENERATION_API =
|
|
'/api/editor/icon-spritesheets/generations';
|
|
const EDITOR_ICON_SPRITESHEET_SLICE_API =
|
|
'/api/editor/icon-spritesheets/slices';
|
|
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_BACKGROUND_MUSIC_PROMPT_COMPLETION_API =
|
|
'/api/editor/audios/background-music/prompts/completions';
|
|
const EDITOR_BACKGROUND_MUSIC_PROMPT_SIMPLIFICATION_API =
|
|
'/api/editor/audios/background-music/prompts/simplifications';
|
|
const EDITOR_SOUND_EFFECT_PROMPT_OPTIMIZATION_API =
|
|
'/api/editor/audios/sound-effects/prompts/optimizations';
|
|
/**
|
|
* 覆盖简化两个业务语义轮加单轮 transport retry 的服务端预算,同时为浏览器到 BFF 的
|
|
* 悬挂连接提供有界退出;超时后走既有失败路径恢复 idle,不写回候选。
|
|
*/
|
|
export const EDITOR_BACKGROUND_MUSIC_PROMPT_ASSIST_TIMEOUT_MS = 180_000;
|
|
export const EDITOR_SOUND_EFFECT_PROMPT_OPTIMIZE_TIMEOUT_MS = 180_000;
|
|
const EDITOR_GENERATION_PRICING_API = '/api/editor/generation-pricing';
|
|
const EDITOR_IMAGE_MODEL_NANOBANANA2 = 'gemini-3.1-flash-image-preview';
|
|
const EDITOR_IMAGE_REFERENCE_LIMIT = 5;
|
|
const EDITOR_QUICK_EDIT_REFERENCE_LIMIT = 9;
|
|
const EDITOR_IMAGE_EDIT_EXTRA_REFERENCE_LIMIT = 8;
|
|
const EDITOR_ICON_EXTRA_REFERENCE_LIMIT = 8;
|
|
const EDITOR_UI_EXTRA_REFERENCE_LIMIT = 5;
|
|
const EDITOR_VIDEO_REFERENCE_REQUEST_LIMIT_BYTES = 256 * 1024;
|
|
const DEFAULT_PROJECT_TITLE = '未命名画布';
|
|
|
|
function assertStableEditorMediaReference(value: string, fieldLabel: string) {
|
|
const normalized = value.trimStart().toLowerCase();
|
|
if (normalized.startsWith('data:') || normalized.startsWith('blob:')) {
|
|
throw new Error(
|
|
`${fieldLabel}必须先上传 OSS,并使用 objectKey、项目资源、素材 ID 或支持的 URL 引用。`,
|
|
);
|
|
}
|
|
}
|
|
|
|
function assertStableEditorMediaReferences(
|
|
values: readonly string[] | undefined,
|
|
fieldLabel: string,
|
|
) {
|
|
values?.forEach((value) =>
|
|
assertStableEditorMediaReference(value, fieldLabel),
|
|
);
|
|
}
|
|
|
|
function requireEditorIconSpecPromptLength(value: string, fieldLabel: string) {
|
|
const normalized = value.trim();
|
|
if (!normalized) {
|
|
throw new Error(`${fieldLabel}不能为空`);
|
|
}
|
|
if (Array.from(normalized).length > EDITOR_ICON_SPEC_PROMPT_MAX_LENGTH) {
|
|
throw new Error(
|
|
`${fieldLabel}不能超过 ${EDITOR_ICON_SPEC_PROMPT_MAX_LENGTH} 个字符`,
|
|
);
|
|
}
|
|
return normalized;
|
|
}
|
|
|
|
function resolveEditorProviderReferenceLimit(model: string | null | undefined) {
|
|
const normalized = model?.trim();
|
|
return normalized === EDITOR_IMAGE_MODEL_NANOBANANA2 ||
|
|
normalized === 'nanobanana2' ||
|
|
normalized === 'nano-banana'
|
|
? 14
|
|
: 5;
|
|
}
|
|
|
|
function assertEditorReferenceLimit(
|
|
values: readonly string[] | undefined,
|
|
limit: number,
|
|
fieldLabel: string,
|
|
) {
|
|
const count = values?.filter((value) => value.trim()).length ?? 0;
|
|
if (count > limit) {
|
|
throw new Error(`${fieldLabel}最多允许 ${limit} 张,当前选择 ${count} 张`);
|
|
}
|
|
}
|
|
|
|
function normalizeEditorIconDescriptions(values: readonly string[]) {
|
|
const normalized = values.map((value) => value.trim()).filter(Boolean);
|
|
if (
|
|
normalized.length < 1 ||
|
|
normalized.length > EDITOR_ICON_DESCRIPTION_LIMIT
|
|
) {
|
|
throw new Error(
|
|
`图标素材描述数量必须在 1 到 ${EDITOR_ICON_DESCRIPTION_LIMIT} 个之间`,
|
|
);
|
|
}
|
|
normalized.forEach((description, index) => {
|
|
const actualLength = Array.from(description).length;
|
|
if (actualLength > EDITOR_ICON_DESCRIPTION_MAX_CHARS) {
|
|
throw new Error(
|
|
`第 ${index + 1} 条图标素材描述不能超过 ${EDITOR_ICON_DESCRIPTION_MAX_CHARS} 个字符`,
|
|
);
|
|
}
|
|
});
|
|
const prompt = normalized.join('\n');
|
|
const totalLength = Array.from(prompt).length;
|
|
if (totalLength > EDITOR_ICON_DESCRIPTIONS_MAX_TOTAL_CHARS) {
|
|
throw new Error(
|
|
`图标素材描述合计不能超过 ${EDITOR_ICON_DESCRIPTIONS_MAX_TOTAL_CHARS} 个字符`,
|
|
);
|
|
}
|
|
const totalUtf8Bytes = new TextEncoder().encode(prompt).byteLength;
|
|
if (totalUtf8Bytes > EDITOR_ICON_DESCRIPTIONS_MAX_TOTAL_UTF8_BYTES) {
|
|
throw new Error(
|
|
`图标素材描述合计不能超过 ${EDITOR_ICON_DESCRIPTIONS_MAX_TOTAL_UTF8_BYTES} 个 UTF-8 字节`,
|
|
);
|
|
}
|
|
return normalized;
|
|
}
|
|
|
|
function assertStableEditorVideoReferences(input: EditorVideoGenerationInput) {
|
|
const references = [
|
|
...(input.referenceImageSrcs ?? []),
|
|
...(input.referenceVideoSrcs ?? []),
|
|
...(input.referenceAudioSrcs ?? []),
|
|
];
|
|
assertStableEditorMediaReferences(references, '视频参考素材');
|
|
const requestBytes = new TextEncoder().encode(references.join('')).byteLength;
|
|
if (requestBytes > EDITOR_VIDEO_REFERENCE_REQUEST_LIMIT_BYTES) {
|
|
throw new Error('视频参考素材稳定引用字段总长度不能超过 256KB');
|
|
}
|
|
}
|
|
|
|
export type EditorCanvasViewport = {
|
|
x: number;
|
|
y: number;
|
|
scale: number;
|
|
};
|
|
|
|
export type EditorProjectLayerSnapshot = Record<string, unknown> & {
|
|
layerId: string;
|
|
resourceId: string;
|
|
assetKindOverride?: string | null;
|
|
};
|
|
|
|
export type EditorAssetGenerationInputField = {
|
|
id?: string;
|
|
title: string;
|
|
value: string | number | boolean;
|
|
};
|
|
|
|
export type EditorAssetGenerationInputReference = {
|
|
id?: string;
|
|
title: string;
|
|
label?: string;
|
|
refType: 'project-resource' | 'asset';
|
|
refId: string;
|
|
};
|
|
|
|
export type EditorAssetGenerationInputs = {
|
|
version?: 2;
|
|
action?:
|
|
| 'image.generate'
|
|
| 'scene.generate'
|
|
| 'spec.generate'
|
|
| 'character.generate'
|
|
| 'icon.generate'
|
|
| 'ui-design.generate'
|
|
| 'publication.generate'
|
|
| 'video.generate'
|
|
| 'audio.sound-effect.generate'
|
|
| 'audio.background-music.generate'
|
|
| 'character-animation.generate'
|
|
| 'image.edit'
|
|
| 'ui-design.extract-assets'
|
|
| 'image.perfect-pixel'
|
|
| 'spritesheet.split'
|
|
| 'image.remove-background'
|
|
| 'image.crop-expand';
|
|
fields: EditorAssetGenerationInputField[];
|
|
references: EditorAssetGenerationInputReference[];
|
|
soundEffect?: EditorSoundEffectGenerationMetadataV2;
|
|
[key: string]: unknown;
|
|
};
|
|
|
|
export type EditorProjectResourceSourceType =
|
|
'uploaded' | 'generated' | 'mock_generated';
|
|
|
|
export type EditorProjectResourceSnapshot = {
|
|
resourceId: string;
|
|
showcaseId?: string | null;
|
|
assetId?: string | null;
|
|
label?: string | null;
|
|
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;
|
|
imageSequenceFrames?: EditorImageSequenceFrameResult[] | null;
|
|
imageSequenceDurationMs?: number | null;
|
|
sourceResourceId?: string | null;
|
|
assetKind?: string | null;
|
|
showcaseCategory?: string | null;
|
|
generationInputs?: EditorAssetGenerationInputs | null;
|
|
publicShowcaseEnabled?: boolean;
|
|
reviewStatus?: 'pending' | 'approved' | 'rejected' | string | null;
|
|
displayEnabled?: boolean | null;
|
|
likeCount?: number | null;
|
|
generationCostMudPoints?: number;
|
|
refundMudPoints?: number | null;
|
|
createdAt?: string;
|
|
updatedAt?: string;
|
|
};
|
|
|
|
export type EditorPublicShowcaseResourceSnapshot =
|
|
EditorProjectResourceSnapshot & {
|
|
viewerLiked: boolean;
|
|
};
|
|
|
|
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;
|
|
imageSequenceFrames?: EditorImageSequenceFrameResult[] | null;
|
|
imageSequenceDurationMs?: number | null;
|
|
sourceResourceId?: string | null;
|
|
assetKind?: string | null;
|
|
showcaseCategory?: string | null;
|
|
generationInputs?: EditorAssetGenerationInputs | null;
|
|
publicShowcaseEnabled?: boolean | null;
|
|
generationCostMudPoints?: number;
|
|
showcaseId?: string | null;
|
|
showcaseReviewStatus?: 'pending' | 'approved' | 'rejected' | string | null;
|
|
showcaseDisplayEnabled?: boolean | null;
|
|
showcaseLikeCount?: number | null;
|
|
createdAt?: string;
|
|
updatedAt?: string;
|
|
};
|
|
|
|
export type EditorShowcaseCampaignSnapshot = {
|
|
enabled: boolean;
|
|
title: string;
|
|
imageSrc: string;
|
|
imageObjectKey?: string | null;
|
|
imageWidth?: number | null;
|
|
imageHeight?: number | null;
|
|
prompt: string;
|
|
author: string;
|
|
costText: string;
|
|
updatedAt?: string;
|
|
};
|
|
|
|
export type EditorAssetLibrarySnapshot = {
|
|
folders: EditorAssetFolderSnapshot[];
|
|
assets: EditorAssetSnapshot[];
|
|
};
|
|
|
|
export type EditorImageGenerationStyle = 'none' | 'pixelArt';
|
|
|
|
export type EditorImageGenerationInput = {
|
|
prompt: string;
|
|
size?: string;
|
|
kind?:
|
|
'spec' | 'character' | 'quick-edit' | 'ui-design' | 'publication-material';
|
|
model?: string;
|
|
screenColor?: string;
|
|
segModel?: string;
|
|
style?: EditorImageGenerationStyle;
|
|
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 EditorIconSpecGenerationInput = {
|
|
playSetting: string;
|
|
artStyle: string;
|
|
referenceId?: string;
|
|
projectId?: 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 = {
|
|
referenceId: string;
|
|
referenceImageSrcs?: string[];
|
|
iconDescriptions: string[];
|
|
/** 必填且没有默认值:必须显式声明连通域或网格切分。 */
|
|
sliceMode: 'connected-components' | 'grid';
|
|
gridX?: number;
|
|
gridY?: number;
|
|
model?: string;
|
|
screenColor?: string;
|
|
segModel?: string;
|
|
style?: EditorImageGenerationStyle;
|
|
aspectRatio?: string;
|
|
imageSize?: string;
|
|
projectId?: string | null;
|
|
generationInputs?: EditorAssetGenerationInputs | null;
|
|
assetFolderId?: string | null;
|
|
assetLabel?: string | null;
|
|
canvasCompletion?: EditorCanvasGenerationCompletionInput | null;
|
|
};
|
|
|
|
export type EditorIconSpritesheetSliceInput = {
|
|
projectId: string;
|
|
sourceLayerId: string;
|
|
sourceResourceId: string;
|
|
assetFolderId?: string | null;
|
|
canvasCompletion: EditorCanvasGenerationCompletionInput;
|
|
};
|
|
|
|
export type EditorUiDesignAssetExtractionInput = {
|
|
sourceImageSrc: string;
|
|
model?: string;
|
|
screenColor?: string;
|
|
segModel?: 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;
|
|
sourceReferenceId: string;
|
|
size?: string;
|
|
model?: string;
|
|
aspectRatio?: string;
|
|
imageSize?: string;
|
|
referenceImageSrcs?: string[];
|
|
projectId?: string | null;
|
|
generationInputs?: EditorAssetGenerationInputs | null;
|
|
assetFolderId?: string | null;
|
|
assetLabel?: string | null;
|
|
targetLayerId?: string | null;
|
|
canvasCompletion?: EditorCanvasGenerationCompletionInput | null;
|
|
};
|
|
|
|
export type EditorBackgroundRemovalInput = {
|
|
sourceImageSrc: string;
|
|
projectId?: string | null;
|
|
targetLayerId?: string | null;
|
|
assetKind?: string | null;
|
|
generationInputs?: EditorAssetGenerationInputs | null;
|
|
assetFolderId?: string | null;
|
|
assetLabel?: string | null;
|
|
sourceResourceId?: string | null;
|
|
taskId?: string | null;
|
|
canvasCompletion?: EditorCanvasGenerationCompletionInput | null;
|
|
};
|
|
|
|
export type EditorPixelArtSnapInput = {
|
|
sourceImageSrc: string;
|
|
projectId: string;
|
|
sourceResourceId?: string | null;
|
|
assetKind?: string | null;
|
|
generationInputs?: EditorAssetGenerationInputs | null;
|
|
assetFolderId?: string | null;
|
|
assetLabel?: string | null;
|
|
canvasCompletion: EditorCanvasGenerationCompletionInput & {
|
|
dialogId: string;
|
|
};
|
|
};
|
|
|
|
export type EditorImageGenerationResult = {
|
|
imageSrc: string;
|
|
objectKey?: string | null;
|
|
assetObjectId?: string | null;
|
|
width: number;
|
|
height: number;
|
|
sourceType: 'generated';
|
|
prompt: string;
|
|
actualPrompt?: string | null;
|
|
model: string;
|
|
taskId: string;
|
|
resource?: EditorProjectResourceSnapshot | null;
|
|
asset?: EditorAssetSnapshot | null;
|
|
project?: EditorProjectSnapshot | null;
|
|
warning?: EditorGenerationWarning | null;
|
|
queueState?: ExternalGenerationJobStatusRecord | null;
|
|
};
|
|
|
|
export type EditorBackgroundRemovalResult = {
|
|
queueState: ExternalGenerationJobStatusRecord;
|
|
};
|
|
|
|
export type EditorPixelArtSnapResult = {
|
|
imageSrc: string;
|
|
objectKey: string;
|
|
assetObjectId: string;
|
|
width: number;
|
|
height: number;
|
|
sourceType: 'generated';
|
|
taskId: string;
|
|
elapsedMs: number;
|
|
provider: 'Genarrative';
|
|
resource: EditorProjectResourceSnapshot;
|
|
asset: EditorAssetSnapshot;
|
|
project: EditorProjectSnapshot | null;
|
|
};
|
|
|
|
export type EditorIconSpritesheetIconResult = {
|
|
name: string;
|
|
imageSrc: string;
|
|
width: number;
|
|
height: number;
|
|
resource?: EditorProjectResourceSnapshot | null;
|
|
asset?: EditorAssetSnapshot | null;
|
|
};
|
|
|
|
export type EditorGenerationWarning = {
|
|
code: string;
|
|
reason: string;
|
|
};
|
|
|
|
export type EditorIconSpritesheetSliceWarning = EditorGenerationWarning;
|
|
|
|
export type EditorIconSpritesheetGenerationResult = {
|
|
spritesheetImageSrc: string;
|
|
spritesheetWidth: number;
|
|
spritesheetHeight: number;
|
|
iconImageSrcs: EditorIconSpritesheetIconResult[];
|
|
sliceMode?: 'connected-components' | 'grid';
|
|
gridX?: number;
|
|
gridY?: number;
|
|
sliceWarning?: EditorIconSpritesheetSliceWarning | null;
|
|
prompt: string;
|
|
actualPrompt?: string | null;
|
|
model: string;
|
|
taskId: string;
|
|
priceMudPoints: number;
|
|
spritesheetResource?: EditorProjectResourceSnapshot | null;
|
|
spritesheetAsset?: EditorAssetSnapshot | null;
|
|
project?: EditorProjectSnapshot | null;
|
|
warning?: EditorGenerationWarning | null;
|
|
queueState?: ExternalGenerationJobStatusRecord | null;
|
|
};
|
|
|
|
export type EditorIconSpritesheetSliceResult = {
|
|
iconImageSrcs: EditorIconSpritesheetIconResult[];
|
|
project: EditorProjectSnapshot;
|
|
};
|
|
|
|
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;
|
|
/** 纯色抠像背景色(hex 或 'auto'),继承生图的背景色选项行为。 */
|
|
screenColor?: 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;
|
|
assetFolderId?: string | null;
|
|
assetLabel?: string | null;
|
|
};
|
|
|
|
export type EditorImageSequenceFrameResult = {
|
|
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: EditorImageSequenceFrameResult[];
|
|
frameCount: number;
|
|
durationSeconds: number;
|
|
fps: number;
|
|
priceMudPoints: number;
|
|
project?: EditorProjectSnapshot | null;
|
|
resource?: EditorProjectResourceSnapshot | null;
|
|
asset?: EditorAssetSnapshot | 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;
|
|
taskId: string;
|
|
durationSeconds: number;
|
|
priceMudPoints?: number;
|
|
resource?: EditorProjectResourceSnapshot | null;
|
|
asset?: EditorAssetSnapshot | null;
|
|
project?: EditorProjectSnapshot | null;
|
|
queueState?: ExternalGenerationJobStatusRecord | null;
|
|
};
|
|
|
|
export type EditorSoundEffectGenerationInput =
|
|
EditorSoundEffectGenerationRequest & {
|
|
projectId?: string | null;
|
|
canvasCompletion?: EditorCanvasGenerationCompletionInput | null;
|
|
generationInputs?: EditorAssetGenerationInputs | null;
|
|
assetFolderId?: string | null;
|
|
assetLabel?: string | null;
|
|
};
|
|
|
|
export type EditorBackgroundMusicGenerationInput = {
|
|
gptDescriptionPrompt: string;
|
|
makeInstrumental: true;
|
|
projectId?: string | null;
|
|
canvasCompletion?: EditorCanvasGenerationCompletionInput | null;
|
|
generationInputs?: EditorAssetGenerationInputs | null;
|
|
assetFolderId?: string | null;
|
|
assetLabel?: string | null;
|
|
};
|
|
|
|
export type EditorBackgroundMusicPromptAssistOptions = {
|
|
signal?: AbortSignal;
|
|
};
|
|
|
|
export type EditorSoundEffectPromptOptimizeOptions = {
|
|
signal?: AbortSignal;
|
|
};
|
|
|
|
export type EditorAudioGenerationResult = {
|
|
audioSrc: string;
|
|
objectKey?: string | null;
|
|
assetObjectId?: string | null;
|
|
width: number;
|
|
height: number;
|
|
sourceType: 'generated';
|
|
prompt: string;
|
|
actualPrompt?: string | null;
|
|
model: string;
|
|
taskId: string;
|
|
priceMudPoints: number;
|
|
audioKind: 'sound-effect' | 'background-music';
|
|
durationSeconds?: number | null;
|
|
loop?: boolean | null;
|
|
resource?: EditorProjectResourceSnapshot | null;
|
|
asset?: EditorAssetSnapshot | null;
|
|
project?: EditorProjectSnapshot | null;
|
|
queueState?: ExternalGenerationJobStatusRecord | null;
|
|
};
|
|
|
|
export type EditorGenerationPricingUnit = 'perGeneration' | 'perSecond';
|
|
|
|
export type EditorGenerationModelPricing = {
|
|
unit: EditorGenerationPricingUnit;
|
|
price?: number;
|
|
prices?: Record<string, number>;
|
|
};
|
|
|
|
export type EditorGenerationPricingConfig = {
|
|
models: Record<string, EditorGenerationModelPricing>;
|
|
};
|
|
|
|
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[];
|
|
revision?: number;
|
|
layoutStorageVersion?: number;
|
|
backgroundColor?: string | null;
|
|
createdAt?: string;
|
|
updatedAt: string;
|
|
};
|
|
|
|
export type EditorProjectLoadOptions = {
|
|
signal?: AbortSignal;
|
|
timeoutMs?: number;
|
|
deadlineAt?: number;
|
|
};
|
|
|
|
export type EditorProjectCreateInput = {
|
|
title?: string;
|
|
};
|
|
|
|
export type EditorProjectLayoutSaveInput = {
|
|
viewport: EditorCanvasViewport;
|
|
layers: EditorProjectLayerSnapshot[];
|
|
expectedRevision: number;
|
|
};
|
|
|
|
export type EditorProjectLayoutSaveResult = {
|
|
projectId: string;
|
|
canvasId: string;
|
|
revision: number;
|
|
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;
|
|
imageSequenceFrames?: EditorImageSequenceFrameResult[] | null;
|
|
imageSequenceDurationMs?: 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;
|
|
imageSequenceFrames?: EditorImageSequenceFrameResult[] | null;
|
|
imageSequenceDurationMs?: 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: EditorPublicShowcaseResourceSnapshot[];
|
|
nextCursor?: string | null;
|
|
campaign?: EditorShowcaseCampaignSnapshot | null;
|
|
};
|
|
|
|
export type EditorProjectResourceListPage = {
|
|
resources: EditorPublicShowcaseResourceSnapshot[];
|
|
nextCursor: string | null;
|
|
campaign?: EditorShowcaseCampaignSnapshot | null;
|
|
};
|
|
|
|
type EditorAssetLibraryResponse = {
|
|
library: EditorAssetLibrarySnapshot;
|
|
};
|
|
|
|
type EditorAssetFolderResponse = {
|
|
folder: EditorAssetFolderSnapshot;
|
|
};
|
|
|
|
type EditorAssetFolderDeleteResponse = {
|
|
library: EditorAssetLibrarySnapshot;
|
|
};
|
|
|
|
type EditorAssetResponse = {
|
|
asset: EditorAssetSnapshot;
|
|
};
|
|
|
|
type EditorShowcaseAssetResponse = {
|
|
showcaseAsset: EditorProjectResourceSnapshot;
|
|
};
|
|
|
|
type EditorShowcaseAssetViewerResponse = {
|
|
showcaseAsset: EditorPublicShowcaseResourceSnapshot;
|
|
};
|
|
|
|
type EditorImageGenerationResponse = EditorImageGenerationResult;
|
|
type EditorBackgroundRemovalResponse = EditorBackgroundRemovalResult;
|
|
type EditorPixelArtSnapResponse = EditorPixelArtSnapResult;
|
|
type EditorIconSpritesheetGenerationResponse =
|
|
EditorIconSpritesheetGenerationResult;
|
|
type EditorVideoGenerationResponse = EditorVideoGenerationResult;
|
|
type EditorAudioGenerationResponse = EditorAudioGenerationResult;
|
|
|
|
function jsonRequest(method: 'POST' | 'PATCH', body: Record<string, unknown>) {
|
|
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({
|
|
cursor,
|
|
viewer = 'anonymous',
|
|
}: {
|
|
cursor?: string | null;
|
|
viewer?: 'anonymous' | 'authenticated';
|
|
} = {}): Promise<EditorProjectResourceListPage> {
|
|
const params = new URLSearchParams();
|
|
if (cursor?.trim()) {
|
|
params.set('cursor', cursor.trim());
|
|
}
|
|
const url = params.toString()
|
|
? `${EDITOR_SHOWCASE_RESOURCE_API}?${params.toString()}`
|
|
: EDITOR_SHOWCASE_RESOURCE_API;
|
|
const response =
|
|
viewer === 'authenticated'
|
|
? await requestJson<EditorProjectResourceListResponse>(
|
|
url,
|
|
{ method: 'GET' },
|
|
'读取陶泥儿精选素材失败',
|
|
)
|
|
: await requestJson<EditorProjectResourceListResponse>(
|
|
url,
|
|
{ method: 'GET' },
|
|
'读取陶泥儿精选素材失败',
|
|
{
|
|
skipAuth: true,
|
|
skipRefresh: true,
|
|
notifyAuthStateChange: false,
|
|
clearAuthOnUnauthorized: false,
|
|
},
|
|
);
|
|
return {
|
|
resources: response.resources,
|
|
nextCursor: response.nextCursor?.trim() || null,
|
|
campaign: response.campaign ?? null,
|
|
};
|
|
}
|
|
|
|
export async function loadRecentEditorProject() {
|
|
return requestJson<EditorProjectRecentResponse>(
|
|
`${EDITOR_PROJECT_API_BASE}/recent`,
|
|
{ method: 'GET' },
|
|
'读取图片画布工程失败',
|
|
);
|
|
}
|
|
|
|
export async function createEditorProject(
|
|
input: EditorProjectCreateInput = {},
|
|
) {
|
|
const response = await requestJson<EditorProjectResponse>(
|
|
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<EditorGenerationPricingConfig>(
|
|
EDITOR_GENERATION_PRICING_API,
|
|
{ method: 'GET' },
|
|
'读取模型定价失败',
|
|
{
|
|
skipAuth: true,
|
|
skipRefresh: true,
|
|
notifyAuthStateChange: false,
|
|
clearAuthOnUnauthorized: false,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function loadEditorProject(
|
|
projectId: string,
|
|
options: EditorProjectLoadOptions = {},
|
|
) {
|
|
const hasAbsoluteDeadline =
|
|
typeof options.deadlineAt === 'number' &&
|
|
Number.isFinite(options.deadlineAt);
|
|
const response = await requestJson<EditorProjectResponse>(
|
|
`${EDITOR_PROJECT_API_BASE}/${encodeURIComponent(projectId)}`,
|
|
{
|
|
method: 'GET',
|
|
...(options.signal ? { signal: options.signal } : {}),
|
|
},
|
|
'读取图片画布工程失败',
|
|
hasAbsoluteDeadline
|
|
? { deadlineAt: options.deadlineAt }
|
|
: // 中文注释:普通项目读取继续保留既有单次 fetch timeout;完美像素对账显式传
|
|
// deadlineAt,改由 requestJson 从鉴权恢复到响应体读取约束完整生命周期。
|
|
{ timeoutMs: options.timeoutMs ?? 60_000 },
|
|
);
|
|
return response.project;
|
|
}
|
|
|
|
export async function renameEditorProject(projectId: string, title: string) {
|
|
const response = await requestJson<EditorProjectResponse>(
|
|
`${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;
|
|
}
|
|
|
|
// 中文注释:这里曾接受第三参数(调用方注入的 `signal` / `deadlineAt`),只服务于已删除的
|
|
// 严格布局保存通道;该通道删除后全部调用点都只传两个参数,注入分支恒不生效。一并摘掉,
|
|
// 免得后来者以为调用方还能控制这次保存的取消与截止。
|
|
export async function saveEditorProjectLayout(
|
|
projectId: string,
|
|
input: EditorProjectLayoutSaveInput,
|
|
) {
|
|
return requestJson<EditorProjectLayoutSaveResponse>(
|
|
`${EDITOR_PROJECT_API_BASE}/${encodeURIComponent(projectId)}`,
|
|
jsonRequest('PATCH', {
|
|
viewport: input.viewport,
|
|
layers: input.layers,
|
|
expectedRevision: input.expectedRevision,
|
|
}),
|
|
'保存图片画布工程失败',
|
|
// 布局保存会被生成提交链同步等待,必须连鉴权恢复和响应体读取一起有界。
|
|
{ deadlineAt: Date.now() + 60_000 },
|
|
);
|
|
}
|
|
|
|
export async function createEditorProjectResource(
|
|
projectId: string,
|
|
input: EditorProjectResourceCreateInput,
|
|
) {
|
|
const response = await requestJson<EditorProjectResourceResponse>(
|
|
`${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<EditorProjectResourceResponse>(
|
|
`${EDITOR_PROJECT_RESOURCE_API_BASE}/${encodeURIComponent(resourceId)}/showcase`,
|
|
jsonRequest('PATCH', { publicShowcaseEnabled }),
|
|
'更新素材公开展示状态失败',
|
|
);
|
|
return response.resource;
|
|
}
|
|
|
|
export async function loadEditorAssetLibrary() {
|
|
const response = await requestJson<EditorAssetLibraryResponse>(
|
|
`${EDITOR_ASSET_API_BASE}/library`,
|
|
{ method: 'GET' },
|
|
'读取图片画布素材库失败',
|
|
);
|
|
return response.library;
|
|
}
|
|
|
|
export async function createEditorAssetFolder(
|
|
label: string,
|
|
sortOrder?: number,
|
|
) {
|
|
const response = await requestJson<EditorAssetFolderResponse>(
|
|
`${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<EditorAssetFolderResponse>(
|
|
`${EDITOR_ASSET_API_BASE}/folders/${encodeURIComponent(folderId)}`,
|
|
jsonRequest('PATCH', input),
|
|
'更新图片画布素材文件夹失败',
|
|
);
|
|
return response.folder;
|
|
}
|
|
|
|
export async function deleteEditorAssetFolder(folderId: string) {
|
|
const response = await requestJson<EditorAssetFolderDeleteResponse>(
|
|
`${EDITOR_ASSET_API_BASE}/folders/${encodeURIComponent(folderId)}`,
|
|
{ method: 'DELETE' },
|
|
'删除图片画布素材文件夹失败',
|
|
);
|
|
return response.library;
|
|
}
|
|
|
|
export async function createEditorAsset(input: EditorAssetCreateInput) {
|
|
const response = await requestJson<EditorAssetResponse>(
|
|
EDITOR_ASSET_API_BASE,
|
|
jsonRequest('POST', input),
|
|
'创建图片画布素材失败',
|
|
);
|
|
return response.asset;
|
|
}
|
|
|
|
export async function updateEditorAsset(
|
|
assetId: string,
|
|
input: EditorAssetUpdateInput,
|
|
) {
|
|
const response = await requestJson<EditorAssetResponse>(
|
|
`${EDITOR_ASSET_API_BASE}/${encodeURIComponent(assetId)}`,
|
|
jsonRequest('PATCH', input),
|
|
'更新图片画布素材失败',
|
|
);
|
|
return response.asset;
|
|
}
|
|
|
|
export async function deleteEditorAsset(assetId: string) {
|
|
const response = await requestJson<EditorAssetResponse>(
|
|
`${EDITOR_ASSET_API_BASE}/${encodeURIComponent(assetId)}`,
|
|
{ method: 'DELETE' },
|
|
'删除图片画布素材失败',
|
|
);
|
|
return response.asset;
|
|
}
|
|
|
|
export async function submitEditorAssetShowcase(assetId: string) {
|
|
const response = await requestJson<EditorShowcaseAssetResponse>(
|
|
`${EDITOR_ASSET_API_BASE}/${encodeURIComponent(assetId)}/showcase-submissions`,
|
|
{ method: 'POST' },
|
|
'提交精选审核失败',
|
|
);
|
|
return response.showcaseAsset;
|
|
}
|
|
|
|
export async function toggleEditorShowcaseAssetLike(
|
|
showcaseId: string,
|
|
liked: boolean,
|
|
) {
|
|
const response = await requestJson<EditorShowcaseAssetViewerResponse>(
|
|
`${EDITOR_SHOWCASE_ASSET_API_BASE}/${encodeURIComponent(showcaseId)}/likes`,
|
|
jsonRequest('POST', { liked }),
|
|
liked ? '点赞精选素材失败' : '取消点赞精选素材失败',
|
|
);
|
|
return response.showcaseAsset;
|
|
}
|
|
|
|
export type EditorSceneGenerationInput = EditorSceneGenerationRequest;
|
|
|
|
export async function generateEditorScene(input: EditorSceneGenerationInput) {
|
|
assertStableEditorMediaReferences(input.referenceImageSrcs, '场景参考图');
|
|
assertEditorReferenceLimit(
|
|
input.referenceImageSrcs,
|
|
EDITOR_IMAGE_REFERENCE_LIMIT,
|
|
'场景参考图',
|
|
);
|
|
return requestJson<EditorImageGenerationResponse>(
|
|
EDITOR_SCENE_GENERATION_API,
|
|
jsonRequest('POST', {
|
|
sceneContent: input.sceneContent,
|
|
stylePreset: input.stylePreset,
|
|
...(input.customStyle ? { customStyle: input.customStyle } : {}),
|
|
...(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.generationInputs
|
|
? { generationInputs: input.generationInputs }
|
|
: {}),
|
|
...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}),
|
|
...(input.assetLabel ? { assetLabel: input.assetLabel } : {}),
|
|
...(input.canvasCompletion
|
|
? { canvasCompletion: input.canvasCompletion }
|
|
: {}),
|
|
}),
|
|
'生成游戏场景失败',
|
|
{
|
|
timeoutMs: 1_200_000,
|
|
retry: EDITOR_GENERATION_REQUEST_RETRY_OPTIONS,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function generateEditorImage(input: EditorImageGenerationInput) {
|
|
assertStableEditorMediaReferences(input.referenceImageSrcs, '生成参考图');
|
|
const referenceLimit =
|
|
input.kind === 'quick-edit'
|
|
? Math.min(
|
|
EDITOR_QUICK_EDIT_REFERENCE_LIMIT,
|
|
resolveEditorProviderReferenceLimit(input.model),
|
|
)
|
|
: EDITOR_IMAGE_REFERENCE_LIMIT;
|
|
assertEditorReferenceLimit(
|
|
input.referenceImageSrcs,
|
|
referenceLimit,
|
|
'生成参考图',
|
|
);
|
|
return requestJson<EditorImageGenerationResponse>(
|
|
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.screenColor ? { screenColor: input.screenColor } : {}),
|
|
...(input.segModel ? { segModel: input.segModel } : {}),
|
|
...(input.style ? { style: input.style } : {}),
|
|
...(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_GENERATION_REQUEST_RETRY_OPTIONS,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function refineEditorIconSpecPlaySetting(playSetting: string) {
|
|
const validPlaySetting = requireEditorIconSpecPromptLength(
|
|
playSetting,
|
|
'玩法设定',
|
|
);
|
|
const response = await requestJson<{ playSetting: string }>(
|
|
EDITOR_ICON_SPEC_REFINE_GAME_PLAY_API,
|
|
jsonRequest('POST', { playSetting: validPlaySetting }),
|
|
'优化玩法设定失败',
|
|
);
|
|
return requireEditorIconSpecPromptLength(response.playSetting, '玩法设定');
|
|
}
|
|
|
|
export async function refineEditorIconSpecArtStyle(artStyle: string) {
|
|
const validArtStyle = requireEditorIconSpecPromptLength(artStyle, '美术风格');
|
|
const response = await requestJson<{ artStyle: string }>(
|
|
EDITOR_ICON_SPEC_REFINE_ART_STYLE_API,
|
|
jsonRequest('POST', { artStyle: validArtStyle }),
|
|
'优化美术风格失败',
|
|
);
|
|
return requireEditorIconSpecPromptLength(response.artStyle, '美术风格');
|
|
}
|
|
|
|
export async function generateEditorIconSpec(
|
|
input: EditorIconSpecGenerationInput,
|
|
) {
|
|
const playSetting = requireEditorIconSpecPromptLength(
|
|
input.playSetting,
|
|
'玩法设定',
|
|
);
|
|
const artStyle = requireEditorIconSpecPromptLength(
|
|
input.artStyle,
|
|
'美术风格',
|
|
);
|
|
return requestJson<EditorImageGenerationResponse>(
|
|
EDITOR_ICON_SPEC_GENERATION_API,
|
|
jsonRequest('POST', {
|
|
playSetting,
|
|
artStyle,
|
|
...(input.referenceId ? { referenceId: input.referenceId } : {}),
|
|
...(input.projectId ? { projectId: input.projectId } : {}),
|
|
...(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,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function generateEditorIconSpritesheet(
|
|
input: EditorIconSpritesheetGenerationInput,
|
|
) {
|
|
const iconDescriptions = normalizeEditorIconDescriptions(
|
|
input.iconDescriptions,
|
|
);
|
|
const model = input.model?.trim() || EDITOR_IMAGE_MODEL_NANOBANANA2;
|
|
// 切分模式没有默认值:声明必须自洽,网格尺寸只能与 grid 同时提交。
|
|
if (input.sliceMode === 'grid') {
|
|
if (input.gridX === undefined || input.gridY === undefined) {
|
|
throw new Error('sliceMode=grid 必须同时提供 gridX 与 gridY');
|
|
}
|
|
} else if (input.gridX !== undefined || input.gridY !== undefined) {
|
|
throw new Error(
|
|
'sliceMode=connected-components 不接受 gridX/gridY:网格尺寸只能与 grid 同时提交',
|
|
);
|
|
}
|
|
assertStableEditorMediaReferences(input.referenceImageSrcs, '图标素材参考图');
|
|
assertEditorReferenceLimit(
|
|
input.referenceImageSrcs,
|
|
Math.min(
|
|
EDITOR_ICON_EXTRA_REFERENCE_LIMIT,
|
|
resolveEditorProviderReferenceLimit(model) - 1,
|
|
),
|
|
'图标素材参考图',
|
|
);
|
|
return requestJson<EditorIconSpritesheetGenerationResponse>(
|
|
EDITOR_ICON_SPRITESHEET_GENERATION_API,
|
|
jsonRequest('POST', {
|
|
referenceId: input.referenceId,
|
|
...(input.referenceImageSrcs?.length
|
|
? { referenceImageSrcs: input.referenceImageSrcs }
|
|
: {}),
|
|
iconDescriptions,
|
|
sliceMode: input.sliceMode,
|
|
...(input.sliceMode === 'grid' && input.gridX !== undefined
|
|
? { gridX: input.gridX }
|
|
: {}),
|
|
...(input.sliceMode === 'grid' && input.gridY !== undefined
|
|
? { gridY: input.gridY }
|
|
: {}),
|
|
model,
|
|
...(input.screenColor ? { screenColor: input.screenColor } : {}),
|
|
...(input.segModel ? { segModel: input.segModel } : {}),
|
|
...(input.style ? { style: input.style } : {}),
|
|
...(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.assetLabel ? { assetLabel: input.assetLabel } : {}),
|
|
...(input.canvasCompletion
|
|
? { canvasCompletion: input.canvasCompletion }
|
|
: {}),
|
|
}),
|
|
'生成图标素材失败',
|
|
{
|
|
timeoutMs: 1_200_000,
|
|
retry: EDITOR_GENERATION_REQUEST_RETRY_OPTIONS,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function splitEditorIconSpritesheet(
|
|
input: EditorIconSpritesheetSliceInput,
|
|
) {
|
|
return requestJson<EditorIconSpritesheetSliceResult>(
|
|
EDITOR_ICON_SPRITESHEET_SLICE_API,
|
|
jsonRequest('POST', {
|
|
projectId: input.projectId,
|
|
sourceLayerId: input.sourceLayerId,
|
|
sourceResourceId: input.sourceResourceId,
|
|
...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}),
|
|
canvasCompletion: input.canvasCompletion,
|
|
}),
|
|
'拆分图集失败',
|
|
);
|
|
}
|
|
|
|
export async function extractEditorUiDesignAssets(
|
|
input: EditorUiDesignAssetExtractionInput,
|
|
) {
|
|
assertStableEditorMediaReference(input.sourceImageSrc, 'UI设计图');
|
|
assertStableEditorMediaReferences(input.referenceImageSrcs, 'UI素材参考图');
|
|
assertEditorReferenceLimit(
|
|
input.referenceImageSrcs,
|
|
Math.min(
|
|
EDITOR_UI_EXTRA_REFERENCE_LIMIT,
|
|
resolveEditorProviderReferenceLimit(input.model) - 1,
|
|
),
|
|
'UI素材参考图',
|
|
);
|
|
return requestJson<EditorIconSpritesheetGenerationResponse>(
|
|
EDITOR_UI_DESIGN_ASSET_EXTRACTION_API,
|
|
jsonRequest('POST', {
|
|
sourceImageSrc: input.sourceImageSrc,
|
|
...(input.model ? { model: input.model } : {}),
|
|
...(input.screenColor ? { screenColor: input.screenColor } : {}),
|
|
...(input.segModel ? { segModel: input.segModel } : {}),
|
|
...(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_GENERATION_REQUEST_RETRY_OPTIONS,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function editEditorImage(input: EditorImageEditInput) {
|
|
assertStableEditorMediaReferences(input.referenceImageSrcs, '修改参考图');
|
|
assertEditorReferenceLimit(
|
|
input.referenceImageSrcs,
|
|
Math.min(
|
|
EDITOR_IMAGE_EDIT_EXTRA_REFERENCE_LIMIT,
|
|
resolveEditorProviderReferenceLimit(input.model) - 1,
|
|
),
|
|
'修改参考图',
|
|
);
|
|
return requestJson<EditorImageGenerationResponse>(
|
|
EDITOR_IMAGE_EDIT_API,
|
|
jsonRequest('POST', {
|
|
prompt: input.prompt,
|
|
sourceReferenceId: input.sourceReferenceId,
|
|
...(input.size ? { size: input.size } : {}),
|
|
...(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.generationInputs
|
|
? { generationInputs: input.generationInputs }
|
|
: {}),
|
|
...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}),
|
|
...(input.assetLabel ? { assetLabel: input.assetLabel } : {}),
|
|
...(input.targetLayerId ? { targetLayerId: input.targetLayerId } : {}),
|
|
...(input.canvasCompletion
|
|
? { canvasCompletion: input.canvasCompletion }
|
|
: {}),
|
|
}),
|
|
'修改图片失败',
|
|
{
|
|
timeoutMs: 1_200_000,
|
|
retry: EDITOR_GENERATION_REQUEST_RETRY_OPTIONS,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function removeEditorImageBackground(
|
|
input: EditorBackgroundRemovalInput,
|
|
) {
|
|
assertStableEditorMediaReference(input.sourceImageSrc, '待去除背景图片');
|
|
return requestJson<EditorBackgroundRemovalResponse>(
|
|
EDITOR_BACKGROUND_REMOVAL_API,
|
|
jsonRequest('POST', {
|
|
sourceImageSrc: input.sourceImageSrc,
|
|
...(input.projectId ? { projectId: input.projectId } : {}),
|
|
...(input.targetLayerId ? { targetLayerId: input.targetLayerId } : {}),
|
|
...(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.taskId ? { taskId: input.taskId } : {}),
|
|
...(input.canvasCompletion
|
|
? { canvasCompletion: input.canvasCompletion }
|
|
: {}),
|
|
}),
|
|
'去除背景失败',
|
|
{
|
|
timeoutMs: 1_200_000,
|
|
retry: EDITOR_GENERATION_REQUEST_RETRY_OPTIONS,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function snapEditorImageToPixelArt(
|
|
input: EditorPixelArtSnapInput,
|
|
) {
|
|
assertStableEditorMediaReference(input.sourceImageSrc, '待完美像素处理图片');
|
|
return requestJson<EditorPixelArtSnapResponse>(
|
|
EDITOR_PIXEL_ART_SNAP_API,
|
|
jsonRequest('POST', {
|
|
sourceImageSrc: input.sourceImageSrc,
|
|
projectId: input.projectId,
|
|
...(input.sourceResourceId
|
|
? { sourceResourceId: input.sourceResourceId }
|
|
: {}),
|
|
...(input.assetKind ? { assetKind: input.assetKind } : {}),
|
|
...(input.generationInputs
|
|
? { generationInputs: input.generationInputs }
|
|
: {}),
|
|
...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}),
|
|
...(input.assetLabel ? { assetLabel: input.assetLabel } : {}),
|
|
canvasCompletion: input.canvasCompletion,
|
|
}),
|
|
'完美像素处理失败',
|
|
{
|
|
timeoutMs: 120_000,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function generateEditorCharacterAnimation(
|
|
input: EditorCharacterAnimationGenerationInput,
|
|
) {
|
|
assertStableEditorMediaReference(input.sourceImageSrc, '角色动画源图');
|
|
return requestJson<EditorCharacterAnimationGenerationResult>(
|
|
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_GENERATION_REQUEST_RETRY_OPTIONS,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function generateEditorVideo(input: EditorVideoGenerationInput) {
|
|
assertStableEditorVideoReferences(input);
|
|
return requestJson<EditorVideoGenerationResponse>(
|
|
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_GENERATION_REQUEST_RETRY_OPTIONS,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function generateEditorSoundEffect(
|
|
input: EditorSoundEffectGenerationInput,
|
|
) {
|
|
const duration = input.duration ?? null;
|
|
if (
|
|
duration !== null &&
|
|
(!Number.isFinite(duration) ||
|
|
duration < SOUND_EFFECT_DURATION_MIN_SECONDS ||
|
|
duration > SOUND_EFFECT_DURATION_MAX_SECONDS)
|
|
) {
|
|
throw new Error('游戏音效时长必须在 0.5-30 秒之间');
|
|
}
|
|
return requestJson<EditorAudioGenerationResponse>(
|
|
EDITOR_SOUND_EFFECT_GENERATION_API,
|
|
jsonRequest('POST', {
|
|
prompt: input.prompt,
|
|
model: input.model,
|
|
duration,
|
|
loop: input.loop ?? false,
|
|
...(input.projectId ? { projectId: input.projectId } : {}),
|
|
...(input.canvasCompletion
|
|
? { canvasCompletion: input.canvasCompletion }
|
|
: {}),
|
|
...(input.generationInputs
|
|
? { generationInputs: input.generationInputs }
|
|
: {}),
|
|
...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}),
|
|
...(input.assetLabel ? { assetLabel: input.assetLabel } : {}),
|
|
}),
|
|
'生成游戏音效失败',
|
|
{
|
|
timeoutMs: 1_200_000,
|
|
},
|
|
);
|
|
}
|
|
|
|
function requestEditorBackgroundMusicPromptAssist(
|
|
path: string,
|
|
input: BackgroundMusicPromptAssistRequest,
|
|
fallbackMessage: string,
|
|
options: EditorBackgroundMusicPromptAssistOptions,
|
|
) {
|
|
return requestJson<BackgroundMusicPromptAssistResponse>(
|
|
path,
|
|
{
|
|
...jsonRequest('POST', {
|
|
currentPrompt: input.currentPrompt,
|
|
}),
|
|
signal: options.signal,
|
|
},
|
|
fallbackMessage,
|
|
{
|
|
timeoutMs: EDITOR_BACKGROUND_MUSIC_PROMPT_ASSIST_TIMEOUT_MS,
|
|
},
|
|
);
|
|
}
|
|
|
|
export function completeEditorBackgroundMusicPrompt(
|
|
input: BackgroundMusicPromptAssistRequest,
|
|
options: EditorBackgroundMusicPromptAssistOptions = {},
|
|
) {
|
|
return requestEditorBackgroundMusicPromptAssist(
|
|
EDITOR_BACKGROUND_MUSIC_PROMPT_COMPLETION_API,
|
|
input,
|
|
'AI 补全背景音乐提示词失败',
|
|
options,
|
|
);
|
|
}
|
|
|
|
export function simplifyEditorBackgroundMusicPrompt(
|
|
input: BackgroundMusicPromptAssistRequest,
|
|
options: EditorBackgroundMusicPromptAssistOptions = {},
|
|
) {
|
|
return requestEditorBackgroundMusicPromptAssist(
|
|
EDITOR_BACKGROUND_MUSIC_PROMPT_SIMPLIFICATION_API,
|
|
input,
|
|
'简化背景音乐提示词失败',
|
|
options,
|
|
);
|
|
}
|
|
|
|
export function optimizeEditorSoundEffectPrompt(
|
|
input: SoundEffectPromptOptimizeRequest,
|
|
options: EditorSoundEffectPromptOptimizeOptions = {},
|
|
) {
|
|
return requestJson<SoundEffectPromptOptimizeResponse>(
|
|
EDITOR_SOUND_EFFECT_PROMPT_OPTIMIZATION_API,
|
|
{
|
|
...jsonRequest('POST', {
|
|
currentPrompt: input.currentPrompt,
|
|
}),
|
|
signal: options.signal,
|
|
},
|
|
'优化游戏音效提示词失败',
|
|
{
|
|
timeoutMs: EDITOR_SOUND_EFFECT_PROMPT_OPTIMIZE_TIMEOUT_MS,
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function generateEditorBackgroundMusic(
|
|
input: EditorBackgroundMusicGenerationInput,
|
|
) {
|
|
return requestJson<EditorAudioGenerationResponse>(
|
|
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 }
|
|
: {}),
|
|
...(input.assetFolderId ? { assetFolderId: input.assetFolderId } : {}),
|
|
...(input.assetLabel ? { assetLabel: input.assetLabel } : {}),
|
|
}),
|
|
'生成游戏背景音乐失败',
|
|
{
|
|
timeoutMs: 1_200_000,
|
|
},
|
|
);
|
|
}
|