创作数据流程收束
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
import type { AppContext } from '../context.js';
|
||||
import {
|
||||
type CustomWorldGenerationProgress,
|
||||
generateCustomWorldProfileFromOrchestrator,
|
||||
type GenerateCustomWorldProfileInput,
|
||||
} from '../modules/ai/customWorldOrchestrator.js';
|
||||
import type { CustomWorldSession } from './customWorldSessionStore.js';
|
||||
|
||||
export async function generateCustomWorldProfile(
|
||||
context: AppContext,
|
||||
session: CustomWorldSession,
|
||||
options: {
|
||||
onProgress?: (progress: CustomWorldGenerationProgress) => void;
|
||||
signal?: AbortSignal;
|
||||
} = {},
|
||||
) {
|
||||
const input = {
|
||||
settingText: session.settingText,
|
||||
creatorIntent: session.creatorIntent,
|
||||
generationMode: session.generationMode,
|
||||
} satisfies GenerateCustomWorldProfileInput;
|
||||
|
||||
const profile = await generateCustomWorldProfileFromOrchestrator(
|
||||
context.llmClient,
|
||||
input,
|
||||
{
|
||||
onProgress: options.onProgress,
|
||||
signal: options.signal,
|
||||
},
|
||||
);
|
||||
|
||||
return JSON.parse(JSON.stringify(profile)) as Record<string, unknown>;
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
import crypto from 'node:crypto';
|
||||
|
||||
import type { JsonObject } from '../../../packages/shared/src/contracts/common.js';
|
||||
import type {
|
||||
CustomWorldGenerationMode,
|
||||
CustomWorldQuestion,
|
||||
CustomWorldSessionRecord,
|
||||
CustomWorldSessionStatus,
|
||||
} from '../../../packages/shared/src/contracts/runtime.js';
|
||||
import type { RuntimeRepositoryPort } from '../repositories/runtimeRepository.js';
|
||||
|
||||
export type CustomWorldSession = {
|
||||
sessionId: string;
|
||||
status: CustomWorldSessionStatus;
|
||||
settingText: string;
|
||||
creatorIntent: JsonObject | null;
|
||||
generationMode: CustomWorldGenerationMode;
|
||||
questions: CustomWorldQuestion[];
|
||||
result?: JsonObject;
|
||||
lastError?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
function cloneSession(session: CustomWorldSession) {
|
||||
return JSON.parse(JSON.stringify(session)) as CustomWorldSession;
|
||||
}
|
||||
|
||||
function toSessionRecord(session: CustomWorldSession): CustomWorldSessionRecord {
|
||||
return {
|
||||
sessionId: session.sessionId,
|
||||
status: session.status,
|
||||
settingText: session.settingText,
|
||||
creatorIntent: session.creatorIntent,
|
||||
generationMode: session.generationMode,
|
||||
questions: session.questions,
|
||||
result: session.result,
|
||||
lastError: session.lastError,
|
||||
createdAt: session.createdAt,
|
||||
updatedAt: session.updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
function toSession(record: CustomWorldSessionRecord) {
|
||||
return cloneSession({
|
||||
sessionId: record.sessionId,
|
||||
status: record.status,
|
||||
settingText: record.settingText,
|
||||
creatorIntent: record.creatorIntent ?? null,
|
||||
generationMode: record.generationMode,
|
||||
questions: record.questions,
|
||||
result: record.result,
|
||||
lastError: record.lastError,
|
||||
createdAt: record.createdAt,
|
||||
updatedAt: record.updatedAt,
|
||||
});
|
||||
}
|
||||
|
||||
function hasPendingQuestion(questions: CustomWorldQuestion[]) {
|
||||
return questions.some((question) => !question.answer?.trim());
|
||||
}
|
||||
|
||||
function buildClarificationQuestions(
|
||||
settingText: string,
|
||||
creatorIntent: JsonObject | null,
|
||||
) {
|
||||
const questions: CustomWorldQuestion[] = [];
|
||||
const worldHook =
|
||||
typeof creatorIntent?.worldHook === 'string' ? creatorIntent.worldHook.trim() : '';
|
||||
const playerPremise =
|
||||
typeof creatorIntent?.playerPremise === 'string' ? creatorIntent.playerPremise.trim() : '';
|
||||
const openingSituation =
|
||||
typeof creatorIntent?.openingSituation === 'string'
|
||||
? creatorIntent.openingSituation.trim()
|
||||
: '';
|
||||
const coreConflicts = Array.isArray(creatorIntent?.coreConflicts)
|
||||
? creatorIntent.coreConflicts
|
||||
: [];
|
||||
|
||||
if (!worldHook && settingText.trim().length < 24) {
|
||||
questions.push({
|
||||
id: 'world_hook',
|
||||
label: '世界核心',
|
||||
question: '请用一句话补充这个世界最核心的命题或独特卖点。',
|
||||
});
|
||||
}
|
||||
if (!playerPremise) {
|
||||
questions.push({
|
||||
id: 'player_premise',
|
||||
label: '玩家身份',
|
||||
question: '玩家在这个世界里是什么身份、立场或来历?',
|
||||
});
|
||||
}
|
||||
if (!openingSituation) {
|
||||
questions.push({
|
||||
id: 'opening_situation',
|
||||
label: '开局处境',
|
||||
question: '故事开局时,玩家正处于什么局面?',
|
||||
});
|
||||
}
|
||||
if (coreConflicts.length === 0) {
|
||||
questions.push({
|
||||
id: 'core_conflict',
|
||||
label: '核心冲突',
|
||||
question: '这个世界当前最核心的冲突、危机或悬念是什么?',
|
||||
});
|
||||
}
|
||||
|
||||
return questions;
|
||||
}
|
||||
|
||||
export class CustomWorldSessionStore {
|
||||
constructor(
|
||||
private readonly runtimeRepository: RuntimeRepositoryPort,
|
||||
) {}
|
||||
|
||||
async create(
|
||||
userId: string,
|
||||
settingText: string,
|
||||
creatorIntent: JsonObject | null,
|
||||
generationMode: CustomWorldGenerationMode,
|
||||
) {
|
||||
const sessionId = `custom-world-session-${crypto.randomBytes(16).toString('hex')}`;
|
||||
const now = new Date().toISOString();
|
||||
const session: CustomWorldSession = {
|
||||
sessionId,
|
||||
status: 'ready_to_generate',
|
||||
settingText,
|
||||
creatorIntent,
|
||||
generationMode,
|
||||
questions: buildClarificationQuestions(settingText, creatorIntent),
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
if (hasPendingQuestion(session.questions)) {
|
||||
session.status = 'clarifying';
|
||||
}
|
||||
|
||||
await this.runtimeRepository.upsertCustomWorldSession(
|
||||
userId,
|
||||
sessionId,
|
||||
toSessionRecord(session),
|
||||
);
|
||||
return cloneSession(session);
|
||||
}
|
||||
|
||||
async list(userId: string) {
|
||||
const sessions = await this.runtimeRepository.listCustomWorldSessions(userId);
|
||||
return sessions.map((session) => toSession(session));
|
||||
}
|
||||
|
||||
async get(userId: string, sessionId: string) {
|
||||
const session = await this.runtimeRepository.getCustomWorldSession(
|
||||
userId,
|
||||
sessionId,
|
||||
);
|
||||
return session ? toSession(session) : null;
|
||||
}
|
||||
|
||||
async answer(
|
||||
userId: string,
|
||||
sessionId: string,
|
||||
questionId: string,
|
||||
answer: string,
|
||||
) {
|
||||
const session = await this.get(userId, sessionId);
|
||||
if (!session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const question = session.questions.find((item) => item.id === questionId);
|
||||
if (!question) {
|
||||
return null;
|
||||
}
|
||||
|
||||
question.answer = answer;
|
||||
session.status = hasPendingQuestion(session.questions)
|
||||
? 'clarifying'
|
||||
: 'ready_to_generate';
|
||||
session.updatedAt = new Date().toISOString();
|
||||
await this.runtimeRepository.upsertCustomWorldSession(
|
||||
userId,
|
||||
sessionId,
|
||||
toSessionRecord(session),
|
||||
);
|
||||
return cloneSession(session);
|
||||
}
|
||||
|
||||
async updateStatus(
|
||||
userId: string,
|
||||
sessionId: string,
|
||||
status: CustomWorldSessionStatus,
|
||||
lastError = '',
|
||||
) {
|
||||
const session = await this.get(userId, sessionId);
|
||||
if (!session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
session.status = status;
|
||||
session.lastError = lastError || undefined;
|
||||
session.updatedAt = new Date().toISOString();
|
||||
await this.runtimeRepository.upsertCustomWorldSession(
|
||||
userId,
|
||||
sessionId,
|
||||
toSessionRecord(session),
|
||||
);
|
||||
return cloneSession(session);
|
||||
}
|
||||
|
||||
async setResult(userId: string, sessionId: string, result: JsonObject) {
|
||||
const session = await this.get(userId, sessionId);
|
||||
if (!session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
session.status = 'completed';
|
||||
session.lastError = undefined;
|
||||
session.result = JSON.parse(JSON.stringify(result)) as JsonObject;
|
||||
session.updatedAt = new Date().toISOString();
|
||||
await this.runtimeRepository.upsertCustomWorldSession(
|
||||
userId,
|
||||
sessionId,
|
||||
toSessionRecord(session),
|
||||
);
|
||||
return cloneSession(session);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user