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

146 lines
5.2 KiB
TypeScript

import {
buildCreatorIntentFromEightAnchorContent,
buildAnchorPackFromEightAnchorContent,
} from '../eightAnchorCompatibilityService.js';
import { rebuildRoleAssetCoverage } from '../customWorldAgentRoleAssetStateService.js';
import type { CustomWorldAgentActionExecutor } from './types.js';
import type { CustomWorldAgentFoundationDraftService } from '../customWorldAgentFoundationDraftService.js';
import type { CustomWorldAgentAutoAssetService } from '../customWorldAgentAutoAssetService.js';
import type { CustomWorldAgentSnapshotBuilder } from '../customWorldAgentSnapshotBuilder.js';
import type { CustomWorldAgentSessionStore } from '../customWorldAgentSessionStore.js';
import { buildFoundationDraftAssistantMessage } from './helpers.js';
import {
buildCheckpointSnapshot,
createOperationUpdater,
getRequiredSession,
} from './executorShared.js';
export function createDraftFoundationExecutor(params: {
sessionStore: CustomWorldAgentSessionStore;
foundationDraftService: CustomWorldAgentFoundationDraftService;
autoAssetService: CustomWorldAgentAutoAssetService | null;
snapshotBuilder: CustomWorldAgentSnapshotBuilder;
}): CustomWorldAgentActionExecutor<'draft_foundation'> {
return async ({ userId, sessionId, operationId }) => {
const updateOperation = createOperationUpdater({
sessionStore: params.sessionStore,
userId,
sessionId,
operationId,
});
try {
await updateOperation({
status: 'running',
phaseLabel: '整理世界骨架',
phaseDetail: '正在校验已确认锚点,并准备第一版世界框架生成链路。',
progress: 12,
});
const latestSession = await getRequiredSession({
sessionStore: params.sessionStore,
userId,
sessionId,
});
if (latestSession.progressPercent < 100) {
throw new Error('session progressPercent is below 100');
}
const creatorIntent = buildCreatorIntentFromEightAnchorContent(
latestSession.anchorContent,
);
const anchorPack = buildAnchorPackFromEightAnchorContent(
latestSession.anchorContent,
latestSession.progressPercent,
);
const draftProfile = await params.foundationDraftService.generate({
creatorIntent,
anchorPack,
anchorContent: latestSession.anchorContent,
onProgress: async (progress) => {
await updateOperation({
status: 'running',
phaseLabel: progress.phaseLabel,
phaseDetail: progress.phaseDetail,
progress: progress.progress,
});
},
});
const draftWithAssets = params.autoAssetService
? await params.autoAssetService.populateDraftAssets({
draftProfile,
onProgress: async (progress) => {
await updateOperation({
status: 'running',
phaseLabel: progress.phaseLabel,
phaseDetail: progress.phaseDetail,
progress: progress.progress,
});
},
})
: {
draftProfile,
assetCoverage: rebuildRoleAssetCoverage(draftProfile),
warnings: [],
};
await updateOperation({
phaseLabel: '编译草稿卡',
phaseDetail: '正在把世界底稿整理成可浏览的卡片摘要和详情结构。',
progress: 98,
});
const nextState = params.snapshotBuilder.buildFoundationDraftState({
creatorIntent,
anchorPack,
draftProfile:
draftWithAssets.draftProfile as unknown as Record<string, unknown>,
assetCoverage: draftWithAssets.assetCoverage,
});
await params.sessionStore.replaceDerivedState(userId, sessionId, nextState);
await params.sessionStore.appendCheckpoint(userId, sessionId, {
label: '世界底稿 V1',
snapshot: buildCheckpointSnapshot(latestSession, nextState),
});
await params.sessionStore.appendMessage(
userId,
sessionId,
buildFoundationDraftAssistantMessage({
relatedOperationId: operationId,
draftProfile: draftWithAssets.draftProfile,
warnings: draftWithAssets.warnings,
}),
);
await updateOperation({
status: 'completed',
phaseLabel: '世界底稿已生成',
phaseDetail:
draftWithAssets.warnings.length > 0
? `第一版世界底稿和 ${(nextState.draftCards ?? []).length} 张草稿卡已经整理完成,另有 ${draftWithAssets.warnings.length} 项资产补齐待后续处理。`
: `第一版世界底稿和 ${(nextState.draftCards ?? []).length} 张草稿卡已经整理完成。`,
progress: 100,
error: null,
});
} catch (error) {
const currentOperation = await params.sessionStore.getOperation(
userId,
sessionId,
operationId,
);
await updateOperation({
status: 'failed',
phaseLabel: currentOperation?.phaseLabel?.trim() || '底稿生成失败',
phaseDetail:
currentOperation?.phaseDetail?.trim() ||
'这一轮没有成功把设定编成世界底稿。',
progress: 100,
error:
error instanceof Error ? error.message : 'draft foundation failed',
});
}
};
}