1
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-04-14 21:49:44 +08:00
parent fa435aa6a6
commit 6363267bca
13 changed files with 2743 additions and 237 deletions

View File

@@ -0,0 +1,210 @@
import type {
CustomWorldAgentOperationRecord,
CustomWorldAgentSessionSnapshot,
} from '../../packages/shared/src/contracts/customWorldAgent';
import type {
CustomWorldGenerationProgress,
CustomWorldGenerationStep,
} from '../../packages/shared/src/contracts/runtime';
import {
buildCustomWorldCreatorIntentDisplayText,
buildCustomWorldCreatorIntentGenerationText,
normalizeCustomWorldCreatorIntent,
} from './customWorldCreatorIntent';
const AGENT_DRAFT_FOUNDATION_STEP_DEFINITIONS = [
{
id: 'queue',
label: '接收生成请求',
detail: '正在锁定当前已确认的世界锚点与草稿范围。',
},
{
id: 'foundation',
label: '生成世界底稿',
detail: '正在根据世界核心、关系种子与冲突线编排第一版世界结构。',
},
{
id: 'cards',
label: '编译草稿卡',
detail: '正在整理世界卡、角色卡与地点卡的摘要和详情。',
},
{
id: 'workspace',
label: '准备精修工作区',
detail: '正在写回草稿数据,并切回可继续精修的工作区。',
},
] as const satisfies ReadonlyArray<{
id: string;
label: string;
detail: string;
}>;
function clampProgress(progress: number | null | undefined) {
if (typeof progress !== 'number' || Number.isNaN(progress)) {
return 0;
}
return Math.max(0, Math.min(100, Math.round(progress)));
}
function resolveAgentDraftFoundationStepIndex(
operation: CustomWorldAgentOperationRecord,
) {
const progress = clampProgress(operation.progress);
const phaseLabel = operation.phaseLabel.trim();
if (
operation.status === 'completed' ||
phaseLabel.includes('世界底稿已生成') ||
progress >= 90
) {
return 3;
}
if (phaseLabel.includes('编译草稿卡') || progress >= 60) {
return 2;
}
if (phaseLabel.includes('生成世界底稿') || progress >= 25) {
return 1;
}
return 0;
}
function buildAgentDraftFoundationSteps(
operation: CustomWorldAgentOperationRecord,
activeStepIndex: number,
) {
return AGENT_DRAFT_FOUNDATION_STEP_DEFINITIONS.map((step, index) => {
const isCompleted =
operation.status === 'completed' || index < activeStepIndex;
const isActive = !isCompleted && index === activeStepIndex;
return {
id: step.id,
label: step.label,
detail: step.detail,
completed: isCompleted ? 1 : 0,
total: 1,
status: isCompleted
? 'completed'
: isActive
? 'active'
: 'pending',
} satisfies CustomWorldGenerationStep;
});
}
function resolveEstimatedRemainingMs(
progress: number,
startedAtMs: number | null,
nowMs: number,
status: CustomWorldAgentOperationRecord['status'],
) {
if (status === 'completed') {
return 0;
}
if (!startedAtMs || progress <= 0 || progress >= 100) {
return null;
}
const elapsedMs = Math.max(0, nowMs - startedAtMs);
const progressFraction = progress / 100;
return Math.max(
0,
Math.round(elapsedMs / progressFraction - elapsedMs),
);
}
export function isDraftFoundationOperation(
operation: CustomWorldAgentOperationRecord | null | undefined,
): operation is CustomWorldAgentOperationRecord {
return Boolean(operation && operation.type === 'draft_foundation');
}
export function isDraftFoundationOperationRunning(
operation: CustomWorldAgentOperationRecord | null | undefined,
) {
return (
isDraftFoundationOperation(operation) &&
(operation.status === 'queued' || operation.status === 'running')
);
}
export function buildAgentDraftFoundationGenerationProgress(
operation: CustomWorldAgentOperationRecord | null | undefined,
startedAtMs: number | null,
nowMs = Date.now(),
): CustomWorldGenerationProgress | null {
if (!isDraftFoundationOperation(operation)) {
return null;
}
const overallProgress = clampProgress(operation.progress);
const activeStepIndex = resolveAgentDraftFoundationStepIndex(operation);
const elapsedMs = startedAtMs ? Math.max(0, nowMs - startedAtMs) : 0;
const estimatedRemainingMs = resolveEstimatedRemainingMs(
overallProgress,
startedAtMs,
nowMs,
operation.status,
);
const activeStep =
AGENT_DRAFT_FOUNDATION_STEP_DEFINITIONS[activeStepIndex] ??
AGENT_DRAFT_FOUNDATION_STEP_DEFINITIONS[0];
return {
phaseId: activeStep.id,
phaseLabel: operation.phaseLabel || activeStep.label,
phaseDetail: operation.phaseDetail || activeStep.detail,
batchLabel: activeStep.label,
overallProgress,
completedWeight: overallProgress,
totalWeight: 100,
elapsedMs,
estimatedRemainingMs,
activeStepIndex,
steps: buildAgentDraftFoundationSteps(operation, activeStepIndex),
};
}
export function buildAgentDraftFoundationSettingText(
session: CustomWorldAgentSessionSnapshot | null | undefined,
) {
if (!session) {
return '';
}
const creatorIntent = normalizeCustomWorldCreatorIntent(
session.creatorIntent,
'freeform',
);
if (creatorIntent) {
const displayText =
buildCustomWorldCreatorIntentDisplayText(creatorIntent).trim();
const generationText =
buildCustomWorldCreatorIntentGenerationText(creatorIntent).trim();
if (displayText) {
return displayText;
}
if (generationText) {
return generationText;
}
if (creatorIntent.rawSettingText.trim()) {
return creatorIntent.rawSettingText.trim();
}
}
const latestUserMessage = [...session.messages]
.reverse()
.find((message) => message.role === 'user' && message.text.trim());
return latestUserMessage?.text.trim() ?? '正在整理当前共创设定。';
}