@@ -32,12 +32,13 @@ import { parseApiErrorMessage } from '../../packages/shared/src/http';
|
||||
import type {
|
||||
AIResponse,
|
||||
Character,
|
||||
CharacterChatTurn,
|
||||
CustomWorldLandmark,
|
||||
CustomWorldNpc,
|
||||
CustomWorldPlayableNpc,
|
||||
CharacterChatTurn,
|
||||
CustomWorldProfile,
|
||||
Encounter,
|
||||
GameState,
|
||||
SceneHostileNpc,
|
||||
StoryMoment,
|
||||
WorldType,
|
||||
@@ -48,7 +49,7 @@ import type {
|
||||
StoryGenerationContext,
|
||||
StoryRequestOptions,
|
||||
TextStreamOptions,
|
||||
} from './ai';
|
||||
} from './aiTypes';
|
||||
import { fetchWithApiAuth, requestJson } from './apiClient';
|
||||
import { type CharacterChatTargetStatus } from './characterChatPrompt';
|
||||
import { parseLineListContent } from './llmParsers';
|
||||
@@ -365,13 +366,18 @@ export async function generateCustomWorldProfile(
|
||||
: {
|
||||
settingText: input.settingText,
|
||||
creatorIntent: input.creatorIntent ?? null,
|
||||
generationMode: input.generationMode === 'fast' ? 'fast' as const : 'full' as const,
|
||||
generationMode:
|
||||
input.generationMode === 'fast'
|
||||
? ('fast' as const)
|
||||
: ('full' as const),
|
||||
};
|
||||
|
||||
const session = await createCustomWorldSession({
|
||||
settingText: normalizedInput.settingText,
|
||||
creatorIntent:
|
||||
normalizedInput.creatorIntent as Record<string, unknown> | null,
|
||||
creatorIntent: normalizedInput.creatorIntent as Record<
|
||||
string,
|
||||
unknown
|
||||
> | null,
|
||||
generationMode: normalizedInput.generationMode,
|
||||
});
|
||||
|
||||
@@ -380,7 +386,8 @@ export async function generateCustomWorldProfile(
|
||||
typeof normalizedInput.creatorIntent?.worldHook === 'string' &&
|
||||
normalizedInput.creatorIntent.worldHook.trim()
|
||||
? normalizedInput.creatorIntent.worldHook.trim()
|
||||
: normalizedInput.settingText.trim().slice(0, 120) || '这是一个围绕失衡秩序展开的世界。',
|
||||
: normalizedInput.settingText.trim().slice(0, 120) ||
|
||||
'这是一个围绕失衡秩序展开的世界。',
|
||||
player_premise:
|
||||
typeof normalizedInput.creatorIntent?.playerPremise === 'string' &&
|
||||
normalizedInput.creatorIntent.playerPremise.trim()
|
||||
@@ -395,9 +402,9 @@ export async function generateCustomWorldProfile(
|
||||
Array.isArray(normalizedInput.creatorIntent?.coreConflicts) &&
|
||||
normalizedInput.creatorIntent.coreConflicts.length > 0
|
||||
? normalizedInput.creatorIntent.coreConflicts
|
||||
.map((item) => (typeof item === 'string' ? item.trim() : ''))
|
||||
.filter(Boolean)
|
||||
.join(';')
|
||||
.map((item) => (typeof item === 'string' ? item.trim() : ''))
|
||||
.filter(Boolean)
|
||||
.join(';')
|
||||
: '旧秩序与新威胁正在同时逼近,各方都在争夺主动权。',
|
||||
};
|
||||
|
||||
@@ -406,7 +413,8 @@ export async function generateCustomWorldProfile(
|
||||
continue;
|
||||
}
|
||||
|
||||
const answer = fallbackAnswerMap[question.id] || normalizedInput.settingText.trim();
|
||||
const answer =
|
||||
fallbackAnswerMap[question.id] || normalizedInput.settingText.trim();
|
||||
await answerCustomWorldSessionQuestion(session.sessionId, {
|
||||
questionId: question.id,
|
||||
answer,
|
||||
@@ -475,20 +483,30 @@ export async function streamCustomWorldSessionGeneration(
|
||||
const payload = JSON.parse(payloadText) as Record<string, unknown>;
|
||||
if (eventName === 'progress') {
|
||||
if (
|
||||
typeof payload.phaseId === 'string'
|
||||
&& typeof payload.phaseLabel === 'string'
|
||||
&& typeof payload.phaseDetail === 'string'
|
||||
&& typeof payload.overallProgress === 'number'
|
||||
&& Array.isArray(payload.steps)
|
||||
typeof payload.phaseId === 'string' &&
|
||||
typeof payload.phaseLabel === 'string' &&
|
||||
typeof payload.phaseDetail === 'string' &&
|
||||
typeof payload.overallProgress === 'number' &&
|
||||
Array.isArray(payload.steps)
|
||||
) {
|
||||
options.onProgress?.(payload as unknown as CustomWorldGenerationProgress);
|
||||
options.onProgress?.(
|
||||
payload as unknown as CustomWorldGenerationProgress,
|
||||
);
|
||||
} else {
|
||||
options.onProgress?.({
|
||||
phaseId: 'finalize',
|
||||
phaseLabel: typeof payload.phase === 'string' ? payload.phase : 'generating',
|
||||
phaseDetail: typeof payload.phase === 'string' ? payload.phase : 'generating',
|
||||
phaseLabel:
|
||||
typeof payload.phase === 'string'
|
||||
? payload.phase
|
||||
: 'generating',
|
||||
phaseDetail:
|
||||
typeof payload.phase === 'string'
|
||||
? payload.phase
|
||||
: 'generating',
|
||||
overallProgress:
|
||||
typeof payload.progress === 'number' ? payload.progress / 100 : 0,
|
||||
typeof payload.progress === 'number'
|
||||
? payload.progress / 100
|
||||
: 0,
|
||||
completedWeight:
|
||||
typeof payload.progress === 'number' ? payload.progress : 0,
|
||||
totalWeight: 100,
|
||||
@@ -499,7 +517,11 @@ export async function streamCustomWorldSessionGeneration(
|
||||
});
|
||||
}
|
||||
}
|
||||
if (eventName === 'result' && payload.profile && typeof payload.profile === 'object') {
|
||||
if (
|
||||
eventName === 'result' &&
|
||||
payload.profile &&
|
||||
typeof payload.profile === 'object'
|
||||
) {
|
||||
latestProfile = payload.profile as Record<string, unknown>;
|
||||
}
|
||||
if (eventName === 'error') {
|
||||
@@ -521,10 +543,17 @@ export async function streamCustomWorldSessionGeneration(
|
||||
}
|
||||
|
||||
export async function generateCustomWorldSceneImage(
|
||||
...args: [CustomWorldSceneImageRequest]
|
||||
payload: CustomWorldSceneImageRequest,
|
||||
) {
|
||||
const aiClient = await loadLegacyAiModule();
|
||||
return aiClient.generateCustomWorldSceneImage(...args);
|
||||
return requestJson<CustomWorldSceneImageResult>(
|
||||
`${CUSTOM_WORLD_API_BASE}/custom-world/scene-image`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
'生成自定义世界场景图失败',
|
||||
);
|
||||
}
|
||||
|
||||
export async function generateCustomWorldSceneNpc(payload: {
|
||||
@@ -779,10 +808,12 @@ export async function getCustomWorldAgentOperation(
|
||||
sessionId: string,
|
||||
operationId: string,
|
||||
): Promise<CustomWorldAgentOperationRecord> {
|
||||
const response = await requestJson<{
|
||||
operation?: CustomWorldAgentOperationRecord;
|
||||
data?: CustomWorldAgentOperationRecord;
|
||||
} & Partial<CustomWorldAgentOperationRecord>>(
|
||||
const response = await requestJson<
|
||||
{
|
||||
operation?: CustomWorldAgentOperationRecord;
|
||||
data?: CustomWorldAgentOperationRecord;
|
||||
} & Partial<CustomWorldAgentOperationRecord>
|
||||
>(
|
||||
`${RUNTIME_API_BASE}/custom-world/agent/sessions/${encodeURIComponent(sessionId)}/operations/${encodeURIComponent(operationId)}`,
|
||||
{
|
||||
method: 'GET',
|
||||
@@ -790,7 +821,9 @@ export async function getCustomWorldAgentOperation(
|
||||
'读取共创操作状态失败',
|
||||
);
|
||||
|
||||
return (response.operation ?? response.data ?? response) as CustomWorldAgentOperationRecord;
|
||||
return (response.operation ??
|
||||
response.data ??
|
||||
response) as CustomWorldAgentOperationRecord;
|
||||
}
|
||||
|
||||
export async function getCustomWorldAgentCardDetail(
|
||||
@@ -827,7 +860,9 @@ export async function answerCustomWorldSessionQuestion(
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload satisfies AnswerCustomWorldSessionQuestionRequest),
|
||||
body: JSON.stringify(
|
||||
payload satisfies AnswerCustomWorldSessionQuestionRequest,
|
||||
),
|
||||
},
|
||||
'提交自定义世界补充设定失败',
|
||||
);
|
||||
@@ -938,6 +973,10 @@ export async function streamNpcChatTurn(
|
||||
npcState: Record<string, unknown>,
|
||||
options: {
|
||||
onReplyUpdate?: (text: string) => void;
|
||||
questOfferContext?: {
|
||||
state: GameState;
|
||||
turnCount: number;
|
||||
} | null;
|
||||
} = {},
|
||||
) {
|
||||
const payload = {
|
||||
@@ -952,13 +991,23 @@ export async function streamNpcChatTurn(
|
||||
dialogue: conversationHistory ?? [],
|
||||
playerMessage,
|
||||
npcState,
|
||||
questOfferContext: options.questOfferContext
|
||||
? {
|
||||
state: options.questOfferContext.state,
|
||||
encounter,
|
||||
turnCount: options.questOfferContext.turnCount,
|
||||
}
|
||||
: null,
|
||||
} satisfies NpcChatTurnRequest;
|
||||
|
||||
const response = await fetchWithApiAuth(`${RUNTIME_API_BASE}/chat/npc/turn/stream`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
const response = await fetchWithApiAuth(
|
||||
`${RUNTIME_API_BASE}/chat/npc/turn/stream`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const responseText = await response.text();
|
||||
@@ -998,7 +1047,10 @@ export async function streamNpcChatTurn(
|
||||
}
|
||||
|
||||
if (parsedEvent.event === 'reply_delta') {
|
||||
const payloadRecord = JSON.parse(parsedEvent.data) as Record<string, unknown>;
|
||||
const payloadRecord = JSON.parse(parsedEvent.data) as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
const nextText =
|
||||
typeof payloadRecord.text === 'string' ? payloadRecord.text : '';
|
||||
accumulatedReply = nextText;
|
||||
@@ -1014,7 +1066,10 @@ export async function streamNpcChatTurn(
|
||||
}
|
||||
|
||||
if (parsedEvent.event === 'error') {
|
||||
const payloadRecord = JSON.parse(parsedEvent.data) as Record<string, unknown>;
|
||||
const payloadRecord = JSON.parse(parsedEvent.data) as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
throw new Error(
|
||||
typeof payloadRecord.message === 'string'
|
||||
? payloadRecord.message
|
||||
|
||||
Reference in New Issue
Block a user