Files
Genarrative/server-node/src/services/customWorldAgentActionExecutors/generateLandmarksExecutor.ts
2026-04-21 18:27:46 +08:00

111 lines
4.0 KiB
TypeScript

import { getWorldFoundationCardId } from '../customWorldAgentDraftCompiler.js';
import type { CustomWorldAgentActionExecutor } from './types.js';
import type { CustomWorldAgentEntityGenerationService } from '../customWorldAgentEntityGenerationService.js';
import type { CustomWorldAgentChangeSummaryService } from '../customWorldAgentChangeSummaryService.js';
import type { CustomWorldAgentSnapshotBuilder } from '../customWorldAgentSnapshotBuilder.js';
import type { CustomWorldAgentSessionStore } from '../customWorldAgentSessionStore.js';
import { buildActionResultMessage } from './helpers.js';
import {
buildCheckpointSnapshot,
createOperationUpdater,
getRequiredSession,
} from './executorShared.js';
export function createGenerateLandmarksExecutor(params: {
sessionStore: CustomWorldAgentSessionStore;
entityGenerationService: CustomWorldAgentEntityGenerationService;
changeSummaryService: CustomWorldAgentChangeSummaryService;
snapshotBuilder: CustomWorldAgentSnapshotBuilder;
}): CustomWorldAgentActionExecutor<'generate_landmarks'> {
return async ({ userId, sessionId, operationId, payload }) => {
const updateOperation = createOperationUpdater({
sessionStore: params.sessionStore,
userId,
sessionId,
operationId,
});
try {
await updateOperation({
status: 'running',
phaseLabel: '生成新地点',
phaseDetail: '正在围绕当前世界底稿补出新地点。',
progress: 32,
});
const latestSession = await getRequiredSession({
sessionStore: params.sessionStore,
userId,
sessionId,
});
const generationResult =
await params.entityGenerationService.generateAdditionalLandmarks({
creatorIntent: latestSession.creatorIntent,
anchorPack: latestSession.anchorPack,
draftProfile: (latestSession.draftProfile ?? {}) as Record<
string,
unknown
>,
count: payload.count,
promptText: payload.promptText,
anchorCardIds:
payload.anchorCardIds && payload.anchorCardIds.length > 0
? payload.anchorCardIds
: latestSession.focusCardId
? [latestSession.focusCardId]
: [getWorldFoundationCardId()],
});
await updateOperation({
phaseLabel: '插入新地点卡',
phaseDetail: '正在把新地点插回草稿并刷新卡片列表。',
progress: 74,
});
const focusCardId = generationResult.generatedLandmarks[0]?.id ?? null;
const nextState = params.snapshotBuilder.buildRefiningState({
previousStage: latestSession.stage,
draftProfile: generationResult.draftProfile,
focusCardId,
});
await params.sessionStore.replaceDerivedState(userId, sessionId, nextState);
await params.sessionStore.appendCheckpoint(userId, sessionId, {
label: `新增地点 ${generationResult.generatedLandmarks.length}`,
snapshot: buildCheckpointSnapshot(latestSession, nextState),
});
await params.sessionStore.appendMessage(
userId,
sessionId,
buildActionResultMessage({
relatedOperationId: operationId,
text: params.changeSummaryService.buildSummary({
action: 'generate_landmarks',
names: generationResult.generatedLandmarks.map(
(entry) => entry.name,
),
draftProfile: generationResult.draftProfile,
}),
}),
);
await updateOperation({
status: 'completed',
phaseLabel: '新地点已加入草稿',
phaseDetail: `已补出 ${generationResult.generatedLandmarks.length} 个新地点。`,
progress: 100,
error: null,
});
} catch (error) {
await updateOperation({
status: 'failed',
phaseLabel: '地点生成失败',
phaseDetail: '这一轮没有成功补出新地点。',
progress: 100,
error:
error instanceof Error ? error.message : 'generate landmarks failed',
});
}
};
}