diff --git a/apps/web/src/components/layout/AppShell.tsx b/apps/web/src/components/layout/AppShell.tsx index 6a5585d..4c37ced 100644 --- a/apps/web/src/components/layout/AppShell.tsx +++ b/apps/web/src/components/layout/AppShell.tsx @@ -1,11 +1,12 @@ import type { ReactNode } from 'react'; -import { BookOpen, Boxes, Home, RefreshCw, ShieldCheck, UserCircle } from 'lucide-react'; +import { BookOpen, Boxes, Home, RefreshCw, ShieldCheck, Sparkles, UserCircle } from 'lucide-react'; import type { HealthResponse } from '../../api'; import type { LoadState, PageKey } from '../../types'; import { Button, Badge } from '../ui'; const navItems: Array<{ key: PageKey; label: string; icon: ReactNode }> = [ { key: 'home', label: '首页', icon: }, + { key: 'playground', label: '在线测试', icon: }, { key: 'models', label: '模型', icon: }, { key: 'workspace', label: '用户工作台', icon: }, { key: 'admin', label: '管理工作台', icon: }, @@ -24,7 +25,7 @@ export function AppShell(props: { onSignOut: () => void; }) { return ( -
+
AI
@@ -72,7 +73,7 @@ export function AppShell(props: {
-
+
{props.state === 'error' && 数据加载失败} {props.children}
diff --git a/apps/web/src/pages/PlaygroundPage.tsx b/apps/web/src/pages/PlaygroundPage.tsx new file mode 100644 index 0000000..1681d6e --- /dev/null +++ b/apps/web/src/pages/PlaygroundPage.tsx @@ -0,0 +1,713 @@ +import { useEffect, useMemo, useState, type ReactNode } from 'react'; +import { + AssistantRuntimeProvider, + ComposerPrimitive, + MessagePrimitive, + ThreadPrimitive, + useMessagePartText, + useLocalRuntime, + type ChatModelAdapter, + type ThreadMessage, +} 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, PlatformModel } from '@easyai-ai-gateway/contracts'; +import { Bot, ChevronDown, Image as ImageIcon, MessageSquarePlus, Paperclip, Send, Sparkles, Video } from 'lucide-react'; +import { Badge, Button, Select, Textarea } from '../components/ui'; +import { streamChatCompletionText } from '../api'; +import type { PlaygroundMode } from '../types'; + +type VideoCreateMode = 'text_to_video' | 'first_last_frame' | 'omni_reference'; + +interface ModelOption { + count: number; + label: string; + provider: string; + value: 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: