import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react'; import { AssistantRuntimeProvider, ComposerPrimitive, ErrorPrimitive, MessagePrimitive, ThreadPrimitive, useMessage, useMessagePartText, useLocalRuntime, useThread, type ChatModelAdapter, type ThreadMessage, type ThreadMessageLike, } from '@assistant-ui/react'; import { StreamdownTextPrimitive } from '@assistant-ui/react-streamdown'; import { cjk } from '@streamdown/cjk'; import { code } from '@streamdown/code'; import { math } from '@streamdown/math'; import { mermaid } from '@streamdown/mermaid'; import type { GatewayApiKey, GatewayTask, PlatformModel } from '@easyai-ai-gateway/contracts'; import { Bot, ChevronDown, FileText, Image as ImageIcon, LoaderCircle, MessageSquarePlus, Music2, Paperclip, Send, Sparkles, Video, X } from 'lucide-react'; import { Badge, Button, Select, Textarea } from '../components/ui'; import { GatewayApiError, createImageEditTask, createImageGenerationTask, createVideoGenerationTask, pollTaskUntilSettled, streamChatCompletionText, taskIsPending, uploadFileToStorage } from '../api'; import type { PlaygroundMode } from '../types'; import { defaultMediaGenerationSettings, deriveMediaModelCapabilities, gatewayTaskErrorText, mediaRequestPayload, MediaSettingsPopover, MediaTaskBoard, normalizeMediaSettingsForCapabilities, type MediaGenerationRun, type MediaGenerationSettings, type MediaModelCapabilities, } from './playground-media'; type VideoCreateMode = 'text_to_video' | 'first_last_frame' | 'omni_reference'; const MEDIA_RUNS_STORAGE_KEY = 'easyai:playground:media-runs:v1'; const MEDIA_RUNS_STORAGE_LIMIT = 50; const CHAT_MESSAGES_STORAGE_KEY = 'easyai:playground:chat-messages:v1'; const CHAT_MESSAGES_STORAGE_LIMIT = 100; interface StoredChatMessage { content: string; createdAt: string; id: string; role: 'assistant' | 'user'; } interface ModelOption { count: number; label: string; models: PlatformModel[]; provider: string; value: string; } type PlaygroundUploadKind = 'audio' | 'file' | 'image' | 'video'; interface PlaygroundUpload { contentType: string; id: string; kind: PlaygroundUploadKind; name: string; raw: Record; size: number; url: string; } const modeOptions: Array<{ description: string; icon: ReactNode; label: string; value: PlaygroundMode }> = [ { value: 'chat', label: '大模型对话', description: '对话、推理、结构化输出', icon: }, { value: 'image', label: '图像生成', description: '文生图、图像编辑参数预览', icon: }, { value: 'video', label: '视频生成', description: '图生视频、文生视频任务测试', icon: