Persist custom world asset configs in runtime snapshots

This commit is contained in:
2026-04-18 17:00:46 +08:00
parent 7ce61e9879
commit ac801fe05f
29 changed files with 3397 additions and 400 deletions

View File

@@ -451,24 +451,9 @@ function buildFallbackRoleDraft(
: `长期活跃于当前世界暗面,能补足场景视角的关键角色。`,
60,
),
visualDescription: clampText(
kind === 'playable'
? `他保留着适合长期同行的鲜明外形识别点,服装、装备和体态都能直接看出其职责、出身和会如何与玩家并肩行动。`
: `他身上带着与当前局势强绑定的外观痕迹,衣着、器具和整体气质会暴露其长期活动环境与所站的位置。`,
96,
),
actionDescription: clampText(
kind === 'playable'
? '动作表现偏向协作推进与稳定压制,起手克制,发力明确,收招干净。'
: '动作表现偏向试探、牵制与借势,节奏谨慎,但关键时刻会突然加重攻击或位移。',
72,
),
sceneVisualDescription: clampText(
profile.landmarks[0]?.description
? `他的主要活动空间与${profile.landmarks[0].name}相连,场景里能看到${profile.landmarks[0].description}`
: `他的主要活动空间与${profile.name}当前冲突线直接相关,环境里会留下势力痕迹、旧装置和仍在运转的局势线索。`,
96,
),
visualDescription: '',
actionDescription: '',
sceneVisualDescription: '',
backstory: clampText(
`他与${profile.name}当前正在扩张的冲突链紧密相连,知道一些还未公开的内情。`,
80,
@@ -567,10 +552,7 @@ function buildFallbackLandmarkDraft(profile: ParsedProfile) {
`承接${profile.name}当前主冲突的一处关键新场景,适合继续向外扩张世界关系网。`,
72,
),
visualDescription: clampText(
`这里延续${profile.name}当前主冲突的视觉气质,能看到明确的空间层次、可站立地面、核心建筑或地貌,以及仍在运转的局势痕迹。`,
88,
),
visualDescription: '',
dangerLevel: 'medium',
sceneNpcNames,
connections: targetLandmarkNames.map((targetLandmarkName, index) => ({

View File

@@ -112,7 +112,7 @@ test('generateSceneImage uses wan2.2-t2i-flash text-to-image payload and saves t
if (
req.method === 'POST' &&
url.pathname === '/api/v1/services/aigc/image-generation/generation'
url.pathname === '/api/v1/services/aigc/text2image/image-synthesis'
) {
sendJson(res, {
output: {
@@ -168,27 +168,23 @@ test('generateSceneImage uses wan2.2-t2i-flash text-to-image payload and saves t
assert.equal(result.actualPrompt, '整理后的场景提示词');
const createRequest = capturedRequests.find(
(entry) => entry.pathname === '/api/v1/services/aigc/image-generation/generation',
(entry) => entry.pathname === '/api/v1/services/aigc/text2image/image-synthesis',
);
assert.ok(createRequest?.bodyText);
const createPayload = JSON.parse(createRequest.bodyText) as {
model: string;
input: {
messages: Array<{
content: Array<{ text?: string; image?: string }>;
}>;
};
parameters: {
prompt: string;
negative_prompt?: string;
};
parameters: Record<string, unknown>;
};
const content = createPayload.input.messages[0]?.content ?? [];
assert.equal(createPayload.model, 'wan2.2-t2i-flash');
assert.equal(content[0]?.text, '海雾港口像素风场景');
assert.equal(content.length, 1);
assert.equal(createPayload.parameters.negative_prompt, '模糊');
assert.equal(createPayload.input.prompt, '海雾港口像素风场景');
assert.equal(createPayload.input.negative_prompt, '模糊');
assert.equal(createPayload.parameters.size, '1280*720');
const savedImagePath = path.join(tempRoot, 'public', result.imageSrc.slice(1));
assert.equal(fs.existsSync(savedImagePath), true);

View File

@@ -130,34 +130,32 @@ async function createSceneImageTask(params: {
payload: z.infer<typeof sceneImageSchema>;
}) {
const { baseUrl, apiKey, payload } = params;
const response = await fetch(`${baseUrl}/services/aigc/image-generation/generation`, {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
'X-DashScope-Async': 'enable',
const response = await fetch(
`${baseUrl}/services/aigc/text2image/image-synthesis`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
'X-DashScope-Async': 'enable',
},
body: JSON.stringify({
model: payload.model,
input: {
prompt: payload.prompt,
...(payload.negativePrompt
? { negative_prompt: payload.negativePrompt }
: {}),
},
parameters: {
n: 1,
size: payload.size,
prompt_extend: true,
watermark: false,
},
}),
},
body: JSON.stringify({
model: payload.model,
input: {
messages: [
{
role: 'user',
content: [{ text: payload.prompt }],
},
],
},
parameters: {
n: 1,
size: payload.size,
prompt_extend: true,
watermark: false,
...(payload.negativePrompt
? { negative_prompt: payload.negativePrompt }
: {}),
},
}),
});
);
const responseText = await response.text();
if (!response.ok) {