@@ -17,6 +17,7 @@ import type {
|
||||
import { badRequest, notFound } from '../errors.js';
|
||||
import { prepareEventStreamResponse } from '../http.js';
|
||||
import { CustomWorldAgentAssetBridgeService } from './customWorldAgentAssetBridgeService.js';
|
||||
import { CustomWorldAgentAutoAssetService } from './customWorldAgentAutoAssetService.js';
|
||||
import { CustomWorldAgentChangeSummaryService } from './customWorldAgentChangeSummaryService.js';
|
||||
import {
|
||||
buildPendingClarifications,
|
||||
@@ -274,10 +275,12 @@ function buildWelcomeMessage(params: {
|
||||
function buildFoundationDraftAssistantMessage(params: {
|
||||
relatedOperationId: string;
|
||||
draftProfile: unknown;
|
||||
warnings?: string[];
|
||||
}) {
|
||||
const profile = normalizeFoundationDraftProfile(params.draftProfile);
|
||||
const leadCharacter = profile?.playableNpcs[0];
|
||||
const leadLandmark = profile?.landmarks[0];
|
||||
const warnings = (params.warnings ?? []).filter(Boolean);
|
||||
|
||||
return {
|
||||
id: `message-${crypto.randomBytes(8).toString('hex')}`,
|
||||
@@ -288,6 +291,12 @@ function buildFoundationDraftAssistantMessage(params: {
|
||||
'',
|
||||
`当前已经落下来的第一批对象数量是:关键角色 ${profile?.playableNpcs.length ?? 0} 个,关键地点 ${profile?.landmarks.length ?? 0} 个,势力 ${profile?.factions.length ?? 0} 个。`,
|
||||
`建议你先从“${profile?.name || '世界总卡'}”这张世界总卡看起${leadCharacter ? `,再顺着角色「${leadCharacter.name}」往下细修` : ''}${leadLandmark ? `,地点可以先看「${leadLandmark.name}」` : ''}。`,
|
||||
...(warnings.length > 0
|
||||
? [
|
||||
'',
|
||||
`这一轮有 ${warnings.length} 项资产补齐未完成,但不影响世界底稿继续精修。`,
|
||||
]
|
||||
: []),
|
||||
].join('\n'),
|
||||
createdAt: new Date().toISOString(),
|
||||
relatedOperationId: params.relatedOperationId,
|
||||
@@ -332,6 +341,8 @@ export class CustomWorldAgentOrchestrator {
|
||||
|
||||
private readonly assetBridgeService: CustomWorldAgentAssetBridgeService;
|
||||
|
||||
private readonly autoAssetService: CustomWorldAgentAutoAssetService | null;
|
||||
|
||||
private readonly eightAnchorSingleTurnService: EightAnchorSingleTurnService;
|
||||
|
||||
constructor(
|
||||
@@ -339,6 +350,7 @@ export class CustomWorldAgentOrchestrator {
|
||||
llmClient: UpstreamLlmClient | null = null,
|
||||
options: {
|
||||
singleTurnLlmClient?: UpstreamLlmClient | null;
|
||||
autoAssetService?: CustomWorldAgentAutoAssetService | null;
|
||||
} = {},
|
||||
) {
|
||||
this.foundationDraftService = new CustomWorldAgentFoundationDraftService(
|
||||
@@ -350,6 +362,8 @@ export class CustomWorldAgentOrchestrator {
|
||||
);
|
||||
this.changeSummaryService = new CustomWorldAgentChangeSummaryService();
|
||||
this.assetBridgeService = new CustomWorldAgentAssetBridgeService();
|
||||
this.autoAssetService =
|
||||
options.autoAssetService ?? null;
|
||||
this.eightAnchorSingleTurnService = new EightAnchorSingleTurnService(
|
||||
(options.singleTurnLlmClient ?? llmClient) ?? undefined,
|
||||
);
|
||||
@@ -844,9 +858,9 @@ export class CustomWorldAgentOrchestrator {
|
||||
try {
|
||||
await this.sessionStore.updateOperation(userId, sessionId, operationId, {
|
||||
status: 'running',
|
||||
phaseLabel: '生成世界底稿',
|
||||
phaseDetail: '正在根据已确认设定编译第一版世界结构。',
|
||||
progress: 38,
|
||||
phaseLabel: '整理世界骨架',
|
||||
phaseDetail: '正在校验已确认锚点,并准备第一版世界框架生成链路。',
|
||||
progress: 12,
|
||||
});
|
||||
|
||||
await sleep(30);
|
||||
@@ -890,19 +904,44 @@ export class CustomWorldAgentOrchestrator {
|
||||
},
|
||||
});
|
||||
|
||||
const draftWithAssets = this.autoAssetService
|
||||
? await this.autoAssetService.populateDraftAssets({
|
||||
draftProfile,
|
||||
onProgress: async (progress) => {
|
||||
await this.sessionStore.updateOperation(
|
||||
userId,
|
||||
sessionId,
|
||||
operationId,
|
||||
{
|
||||
status: 'running',
|
||||
phaseLabel: progress.phaseLabel,
|
||||
phaseDetail: progress.phaseDetail,
|
||||
progress: progress.progress,
|
||||
},
|
||||
);
|
||||
},
|
||||
})
|
||||
: {
|
||||
draftProfile,
|
||||
assetCoverage: rebuildRoleAssetCoverage(draftProfile),
|
||||
warnings: [],
|
||||
};
|
||||
|
||||
await this.sessionStore.updateOperation(userId, sessionId, operationId, {
|
||||
phaseLabel: '编译草稿卡',
|
||||
phaseDetail: '正在把世界底稿整理成可浏览的卡片摘要和详情结构。',
|
||||
progress: 98,
|
||||
});
|
||||
|
||||
const draftCards = this.draftCompiler.compileDraftCards(draftProfile);
|
||||
const assetCoverage = rebuildRoleAssetCoverage(draftProfile);
|
||||
const draftCards = this.draftCompiler.compileDraftCards(
|
||||
draftWithAssets.draftProfile,
|
||||
);
|
||||
const assetCoverage = draftWithAssets.assetCoverage;
|
||||
const nextStage = 'object_refining' as const;
|
||||
const nextSuggestedActions = buildSuggestedActions({
|
||||
stage: nextStage,
|
||||
isReady: true,
|
||||
draftProfile,
|
||||
draftProfile: draftWithAssets.draftProfile,
|
||||
draftCards,
|
||||
});
|
||||
|
||||
@@ -910,7 +949,8 @@ export class CustomWorldAgentOrchestrator {
|
||||
stage: nextStage,
|
||||
creatorIntent,
|
||||
anchorPack,
|
||||
draftProfile: draftProfile as unknown as Record<string, unknown>,
|
||||
draftProfile:
|
||||
draftWithAssets.draftProfile as unknown as Record<string, unknown>,
|
||||
draftCards,
|
||||
assetCoverage,
|
||||
pendingClarifications: [],
|
||||
@@ -925,22 +965,34 @@ export class CustomWorldAgentOrchestrator {
|
||||
sessionId,
|
||||
buildFoundationDraftAssistantMessage({
|
||||
relatedOperationId: operationId,
|
||||
draftProfile,
|
||||
draftProfile: draftWithAssets.draftProfile,
|
||||
warnings: draftWithAssets.warnings,
|
||||
}),
|
||||
);
|
||||
|
||||
await this.sessionStore.updateOperation(userId, sessionId, operationId, {
|
||||
status: 'completed',
|
||||
phaseLabel: '世界底稿已生成',
|
||||
phaseDetail: `第一版世界底稿和 ${draftCards.length} 张草稿卡已经整理完成。`,
|
||||
phaseDetail:
|
||||
draftWithAssets.warnings.length > 0
|
||||
? `第一版世界底稿和 ${draftCards.length} 张草稿卡已经整理完成,另有 ${draftWithAssets.warnings.length} 项资产补齐待后续处理。`
|
||||
: `第一版世界底稿和 ${draftCards.length} 张草稿卡已经整理完成。`,
|
||||
progress: 100,
|
||||
error: null,
|
||||
});
|
||||
} catch (error) {
|
||||
const currentOperation = await this.sessionStore.getOperation(
|
||||
userId,
|
||||
sessionId,
|
||||
operationId,
|
||||
);
|
||||
await this.sessionStore.updateOperation(userId, sessionId, operationId, {
|
||||
status: 'failed',
|
||||
phaseLabel: '底稿生成失败',
|
||||
phaseDetail: '这一轮没有成功把设定编成世界底稿。',
|
||||
phaseLabel:
|
||||
currentOperation?.phaseLabel?.trim() || '底稿生成失败',
|
||||
phaseDetail:
|
||||
currentOperation?.phaseDetail?.trim() ||
|
||||
'这一轮没有成功把设定编成世界底稿。',
|
||||
progress: 100,
|
||||
error:
|
||||
error instanceof Error ? error.message : 'draft foundation failed',
|
||||
|
||||
Reference in New Issue
Block a user