import { ArrowLeft, CheckCircle2, Puzzle } from 'lucide-react'; import { useEffect, useMemo, useState } from 'react'; import type { CreativeAgentInputPart, CreativeAgentSessionSnapshot, CreativeAgentSseEvent, } from '../../../packages/shared/src/contracts/creativeAgent'; import type { PuzzleCreativeTemplateProtocol, PuzzleCreativeTemplateSelection, } from '../../../packages/shared/src/contracts/puzzleCreativeTemplate'; import { CreativeAgentInputComposer } from './CreativeAgentInputComposer'; import { CreativeAgentProcessPanel } from './CreativeAgentProcessPanel'; import { CreativeAgentStageTimeline } from './CreativeAgentStageTimeline'; import { CreativeAgentTemplateConfirmPanel } from './CreativeAgentTemplateConfirmPanel'; import { buildCreativeAgentProcessItems, buildPuzzleTemplateSelectionFromProtocol, createCreativeAgentClientMessageId, CREATIVE_AGENT_STAGE_LABEL, } from './creativeAgentViewModel'; type CreativeAgentWorkspaceProps = { session: CreativeAgentSessionSnapshot | null; isBusy: boolean; isStreaming: boolean; error: string | null; eventLog: CreativeAgentSseEvent[]; onBack: () => void; onSubmitMessage: (payload: { clientMessageId: string; content: CreativeAgentInputPart[]; }) => void; onConfirmTemplate: (selection: PuzzleCreativeTemplateSelection) => void; onCancelTemplate?: () => void; onOpenTarget: () => void; }; type CreativeAgentTemplateCatalogPanelProps = { templates: PuzzleCreativeTemplateProtocol[]; isBusy: boolean; onSelect: (template: PuzzleCreativeTemplateProtocol) => void; }; function CreativeAgentTemplateCatalogPanel({ templates, isBusy, onSelect, }: CreativeAgentTemplateCatalogPanelProps) { if (templates.length === 0) { return null; } return (
{templates.map((template) => ( ))}
); } export function CreativeAgentWorkspace({ session, isBusy, isStreaming, error, eventLog, onBack, onSubmitMessage, onConfirmTemplate, onCancelTemplate, onOpenTarget, }: CreativeAgentWorkspaceProps) { const stage = session?.stage ?? 'idle'; const messages = session?.messages ?? []; const selection = session?.puzzleTemplateSelection ?? null; const templateCatalog = session?.puzzleTemplateCatalog ?? []; const targetBinding = session?.targetBinding ?? null; const [pendingSelection, setPendingSelection] = useState(null); useEffect(() => { // 中文注释:会话切换时清掉本地待确认模板,避免上一轮选择残留到新会话。 setPendingSelection(null); }, [session?.sessionId]); const processItems = useMemo( () => buildCreativeAgentProcessItems(eventLog, session), [eventLog, session], ); const visibleSelection = targetBinding ? null : (selection ?? pendingSelection); const shouldShowTemplateCatalog = !targetBinding && !selection && templateCatalog.length > 0 && stage === 'waiting_template_confirmation'; return (
{CREATIVE_AGENT_STAGE_LABEL[stage]}
智能创作
当前生成拼图草稿
{targetBinding ? (
拼图草稿已就绪
{targetBinding.targetStage === 'puzzle-result' ? '可以进入结果页继续编辑' : '可以进入拼图工作区继续处理'}
) : null} {messages.length > 0 ? (
{messages.map((message) => (
{message.text}
))}
) : (
发一句想法,或加一张参考图。
)} {shouldShowTemplateCatalog ? ( { setPendingSelection( buildPuzzleTemplateSelectionFromProtocol(template), ); }} /> ) : null} {session?.puzzleImageGenerationPlan ? (
关卡计划
{session.puzzleImageGenerationPlan.levels.map((level) => (
{level.levelName}
{level.pictureDescription}
))}
) : null} {error ? (
{error}
) : null}
{ const content: CreativeAgentInputPart[] = []; if (text) { content.push({ type: 'input_text', text, }); } if (image) { content.push({ type: 'input_image', imageUrl: image.imageUrl, thumbnailUrl: image.thumbnailUrl, assetId: null, }); } onSubmitMessage({ clientMessageId: createCreativeAgentClientMessageId(), content, }); }} />
{visibleSelection && visibleSelection.requiresUserConfirmation ? ( { setPendingSelection(null); onConfirmTemplate(nextSelection); }} onCancel={() => { setPendingSelection(null); onCancelTemplate?.(); }} /> ) : null}
); } export default CreativeAgentWorkspace;