import { RotateCcw } from 'lucide-react'; import type { VisualNovelHistoryEntry, VisualNovelRunSnapshot, VisualNovelRuntimeStep, } from '../../../packages/shared/src/contracts/visualNovel'; type VisualNovelHistoryPanelProps = { run: VisualNovelRunSnapshot; allowRegeneration?: boolean; isBusy?: boolean; onRegenerateHistoryEntry?: (entryId: string) => void; }; function renderStepText(step: VisualNovelRuntimeStep) { if (step.type === 'narration') { return step.text; } if (step.type === 'dialogue') { return `${step.characterName}: ${step.text}`; } if (step.type === 'transition') { return step.text ?? ''; } if (step.type === 'choice') { return step.choices.map((choice) => choice.text).join(' / '); } return ''; } function VisualNovelHistoryEntryCard({ entry, allowRegeneration, isBusy, onRegenerateHistoryEntry, }: { entry: VisualNovelHistoryEntry; allowRegeneration: boolean; isBusy: boolean; onRegenerateHistoryEntry?: (entryId: string) => void; }) { const visibleStepTexts = entry.steps.map(renderStepText).filter(Boolean); const canRegenerate = allowRegeneration && entry.source === 'assistant' && onRegenerateHistoryEntry; return (
#{entry.turnIndex} {entry.source === 'player' ? '玩家' : '故事'}
{entry.actionText ? (

{entry.actionText}

) : null} {visibleStepTexts.map((text, index) => (

{text}

))} {canRegenerate ? ( ) : null}
); } export function VisualNovelHistoryPanel({ run, allowRegeneration = false, isBusy = false, onRegenerateHistoryEntry, }: VisualNovelHistoryPanelProps) { return (
{run.history.length > 0 ? ( run.history.map((entry) => ( )) ) : (
暂无历史
)}
); } export default VisualNovelHistoryPanel;