import { useMemo, useState } from 'react'; import { BookOpen, Brain, CheckCircle2, Code2, HeartPulse, ImagePlus, Lock, MessageCircle, Mic, PackagePlus, Play, Send, Sparkles, Stars, Users, WandSparkles, } from 'lucide-react'; import { toast } from 'sonner'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Progress } from '@/components/ui/progress'; import { Textarea } from '@/components/ui/textarea'; import { cn } from '@/lib/utils'; type StageStatus = 'open' | 'locked'; type Stage = { id: number; name: string; action: string; status: StageStatus; Icon: typeof Brain; }; type Message = { role: 'partner' | 'kid'; text: string; }; const stages: Stage[] = [ { id: 1, name: '装大脑', action: '接入电子心脏,伙伴醒来', status: 'open', Icon: Brain }, { id: 2, name: '建记忆', action: '聊天形成记忆,伙伴认识你', status: 'open', Icon: MessageCircle }, { id: 3, name: '做创作', action: '一起做第一个 HTML 作品', status: 'open', Icon: Code2 }, { id: 4, name: '学技能', action: '解锁 Skill,点亮技能墙', status: 'locked', Icon: Stars }, { id: 5, name: '装工具', action: '添加 MCP 工具,伙伴拿到新装备', status: 'locked', Icon: PackagePlus }, { id: 6, name: '喂知识', action: '上传知识文件,书架出现新书', status: 'locked', Icon: BookOpen }, { id: 7, name: '遇伙伴', action: '发现其他专项伙伴,一起组队', status: 'locked', Icon: Users }, ]; const lockedCards = [ { title: '技能墙', desc: '完成更多创作后解锁。以后这里会亮起你的伙伴学会的技能。', Icon: Stars, }, { title: '工具栏', desc: '升级伙伴能力后解锁。以后可以给伙伴装上更多工具。', Icon: PackagePlus, }, { title: '知识书架', desc: '开始喂给伙伴知识后解锁。以后每本书都是伙伴的新知识。', Icon: BookOpen, }, { title: '伙伴广场', desc: '认识更多伙伴后解锁。以后可以找到画画、写作、编程伙伴。', Icon: Users, }, ]; const initialMessages: Message[] = [ { role: 'partner', text: '你好,我现在还是一团小泥巴。先帮我装上电子心脏吧。' }, { role: 'kid', text: '我想让你陪我做一个小游戏。' }, { role: 'partner', text: '收到。你想做给谁玩?希望它看起来像什么世界?' }, ]; const previewHtml = `

我的第一个伙伴作品

点击按钮,帮助小伙伴收集星星。

星星:0

`; function PixelPartner({ active }: { active: boolean }) { return (
{active ? '活过来啦' : '待激活'}
); } function StageRow({ stage, selected, onClick }: { stage: Stage; selected: boolean; onClick: () => void }) { const Icon = stage.Icon; return ( ); } export function KangarooPartner() { const [selectedStage, setSelectedStage] = useState(1); const [messages, setMessages] = useState(initialMessages); const [input, setInput] = useState(''); const selected = stages.find((stage) => stage.id === selectedStage) ?? stages[0]; const progress = useMemo(() => Math.round((stages.filter((stage) => stage.status === 'open').length / stages.length) * 100), []); const sendMessage = () => { const trimmed = input.trim(); if (!trimmed) return; setMessages((current) => [ ...current, { role: 'kid', text: trimmed }, { role: 'partner', text: '我记住啦。下一步我会帮你把想法整理成一张创作卡片。' }, ]); setInput(''); toast.success('记忆已更新', { description: '新增:孩子想做的作品想法', }); }; const showLocked = (title: string, desc: string) => { toast.info(title, { description: desc }); }; return (
袋鼠伙伴 · MVP 原型

养成一个会陪你创作的 AI 伙伴

成长路径

{progress}%
{stages.map((stage) => ( { setSelectedStage(stage.id); if (stage.status === 'locked') { showLocked(stage.name, stage.action); } }} /> ))}

角色区

像素风
= 2} />

电子心脏展柜

申请后,把模型心脏拖给伙伴,它就能说话。

少量可用
{['千问伙伴心脏', 'Claude 灵感心脏', 'GPT 创作心脏'].map((model, index) => (

{model}

{index === 0 ? '已获批' : '申请后解锁'}

))}

对话区

当前阶段:{selected.name} · {selected.action}

{messages.map((message, index) => (
{message.text}
))}