Skip to content

Commit 29589d2

Browse files
committed
feat: 为动画页面添加可折叠的介绍组件
为多个动画页面添加可折叠的介绍组件,包括子代理系统、工具调度状态机、核心交互循环等。这些组件提供相关概念、设计原理和源码位置的说明,帮助用户理解动画展示的功能。 组件包含标题、核心概念、触发场景、关键设计和相关机制等内容,支持展开/折叠功能。同时移除了原有的注释说明,改用更结构化的介绍组件展示信息。
1 parent 664aa5f commit 29589d2

9 files changed

Lines changed: 815 additions & 17 deletions

src/pages/Animation.tsx

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,90 @@
11
import { useState, useEffect } from 'react';
22
import { JsonBlock } from '../components/JsonBlock';
33

4+
// 介绍内容组件
5+
function Introduction({ isExpanded, onToggle }: { isExpanded: boolean; onToggle: () => void }) {
6+
return (
7+
<div className="mb-6 bg-[var(--bg-elevated)] rounded-lg overflow-hidden border border-[var(--border-subtle)]">
8+
<button
9+
onClick={onToggle}
10+
className="w-full px-4 py-3 flex items-center justify-between text-left hover:bg-[var(--bg-panel)] transition-colors"
11+
>
12+
<span className="text-lg font-semibold text-[var(--text-primary)]">📖 什么是核心交互循环?</span>
13+
<span className={`transform transition-transform text-[var(--text-muted)] ${isExpanded ? 'rotate-180' : ''}`}></span>
14+
</button>
15+
16+
{isExpanded && (
17+
<div className="px-4 pb-4 space-y-4 text-sm">
18+
{/* 核心概念 */}
19+
<div>
20+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">🎯 核心概念</h3>
21+
<p className="text-[var(--text-secondary)]">
22+
<strong>核心交互循环</strong>是 Qwen CLI 的心跳。当用户发送消息后,CLI 会与 AI 进行多轮交互,
23+
直到 AI 完成任务或需要用户输入。这个循环包括:消息发送 → AI 思考 → 工具调用 → 用户审批 → 执行 → 继续对话。
24+
</p>
25+
</div>
26+
27+
{/* 为什么需要 */}
28+
<div>
29+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">❓ 为什么需要理解这个循环?</h3>
30+
<ul className="text-[var(--text-secondary)] space-y-1 list-disc list-inside">
31+
<li><strong>掌控全局</strong>:理解 CLI 每一步在做什么,不再黑箱操作</li>
32+
<li><strong>排查问题</strong>:当 CLI 卡住或行为异常时,知道从哪里入手</li>
33+
<li><strong>安全意识</strong>:理解工具审批机制,知道何时 CLI 会询问你</li>
34+
<li><strong>性能优化</strong>:理解 Continuation 机制,知道多轮对话的开销</li>
35+
</ul>
36+
</div>
37+
38+
{/* 关键参与者 */}
39+
<div>
40+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">👥 关键参与者</h3>
41+
<div className="grid grid-cols-2 gap-2 text-xs">
42+
<div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]">
43+
<div className="text-[var(--terminal-green)]">👤 用户</div>
44+
<div className="text-[var(--text-muted)]">发起请求、审批工具、接收结果</div>
45+
</div>
46+
<div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]">
47+
<div className="text-[var(--cyber-blue)]">🖥️ CLI</div>
48+
<div className="text-[var(--text-muted)]">协调各方、执行工具、管理状态</div>
49+
</div>
50+
<div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]">
51+
<div className="text-[var(--purple)]">☁️ AI API</div>
52+
<div className="text-[var(--text-muted)]">理解意图、生成回复、调用工具</div>
53+
</div>
54+
<div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]">
55+
<div className="text-[var(--amber)]">🔧 工具</div>
56+
<div className="text-[var(--text-muted)]">读写文件、执行命令、搜索代码</div>
57+
</div>
58+
</div>
59+
</div>
60+
61+
{/* 源码位置 */}
62+
<div>
63+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">📁 核心源码</h3>
64+
<div className="bg-[var(--bg-void)] p-2 rounded font-mono text-xs border border-[var(--border-subtle)]">
65+
<div className="text-[var(--text-muted)]">// 主循环入口</div>
66+
<div>packages/core/src/core/geminiChat.ts</div>
67+
<div className="text-[var(--text-muted)] mt-1">// 工具调度</div>
68+
<div>packages/core/src/tools/toolScheduler.ts</div>
69+
</div>
70+
</div>
71+
72+
{/* 相关机制 */}
73+
<div>
74+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">🔗 相关机制</h3>
75+
<div className="flex flex-wrap gap-2">
76+
<span className="px-2 py-1 bg-[var(--cyber-blue)]/20 text-[var(--cyber-blue)] rounded text-xs">工具调度器</span>
77+
<span className="px-2 py-1 bg-[var(--purple)]/20 text-[var(--purple)] rounded text-xs">流式解析</span>
78+
<span className="px-2 py-1 bg-[var(--terminal-green)]/20 text-[var(--terminal-green)] rounded text-xs">权限审批</span>
79+
<span className="px-2 py-1 bg-[var(--amber)]/20 text-[var(--amber)] rounded text-xs">上下文管理</span>
80+
</div>
81+
</div>
82+
</div>
83+
)}
84+
</div>
85+
);
86+
}
87+
488
interface AnimStepProps {
589
visible: boolean;
690
from: string;
@@ -160,6 +244,7 @@ const stepDescriptions = [
160244
export function Animation() {
161245
const [step, setStep] = useState(0);
162246
const [isPlaying, setIsPlaying] = useState(false);
247+
const [isIntroExpanded, setIsIntroExpanded] = useState(true);
163248
const maxSteps = animSteps.length;
164249

165250
useEffect(() => {
@@ -212,6 +297,9 @@ export function Animation() {
212297
// 展示 innies-cli 的核心交互循环:用户输入 → AI 思考 → 工具审批 → 执行 → Continuation
213298
</p>
214299

300+
{/* 介绍部分 */}
301+
<Introduction isExpanded={isIntroExpanded} onToggle={() => setIsIntroExpanded(!isIntroExpanded)} />
302+
215303
{/* Controls */}
216304
<div className="flex gap-3 mb-6 flex-wrap">
217305
<button

src/pages/ContextCompressionAnimation.tsx

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,87 @@
11
import { useState, useEffect, useCallback, useMemo } from 'react';
22
import { JsonBlock } from '../components/JsonBlock';
33

4+
// 介绍内容组件
5+
function Introduction({ isExpanded, onToggle }: { isExpanded: boolean; onToggle: () => void }) {
6+
return (
7+
<div className="mb-6 bg-[var(--bg-elevated)] rounded-lg overflow-hidden border border-[var(--border-subtle)]">
8+
<button
9+
onClick={onToggle}
10+
className="w-full px-4 py-3 flex items-center justify-between text-left hover:bg-[var(--bg-panel)] transition-colors"
11+
>
12+
<span className="text-lg font-semibold text-[var(--text-primary)]">📖 什么是上下文压缩?</span>
13+
<span className={`transform transition-transform text-[var(--text-muted)] ${isExpanded ? 'rotate-180' : ''}`}></span>
14+
</button>
15+
16+
{isExpanded && (
17+
<div className="px-4 pb-4 space-y-4 text-sm">
18+
{/* 核心概念 */}
19+
<div>
20+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">🎯 核心概念</h3>
21+
<p className="text-[var(--text-secondary)]">
22+
<strong>上下文压缩</strong>是 CLI 保持长对话能力的关键机制。当对话历史超过 Token 限制时,
23+
系统会智能压缩旧消息,保留最重要的信息,让 AI 能够继续理解上下文。
24+
</p>
25+
</div>
26+
27+
{/* 为什么需要 */}
28+
<div>
29+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">❓ 为什么需要压缩?</h3>
30+
<ul className="text-[var(--text-secondary)] space-y-1 list-disc list-inside">
31+
<li><strong>Token 限制</strong>:每个 AI 模型都有最大上下文长度限制</li>
32+
<li><strong>成本控制</strong>:Token 越多,API 调用成本越高</li>
33+
<li><strong>响应速度</strong>:更少的 Token 意味着更快的响应</li>
34+
<li><strong>信息密度</strong>:压缩保留关键信息,丢弃冗余内容</li>
35+
</ul>
36+
</div>
37+
38+
{/* 压缩策略 */}
39+
<div>
40+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">📊 压缩策略</h3>
41+
<div className="grid grid-cols-2 gap-2 text-xs">
42+
<div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]">
43+
<div className="text-[var(--amber)]">阈值触发</div>
44+
<div className="text-[var(--text-muted)]">Token 超过限制时自动触发</div>
45+
</div>
46+
<div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]">
47+
<div className="text-[var(--cyber-blue)]">分割点选择</div>
48+
<div className="text-[var(--text-muted)]">寻找最佳压缩位置</div>
49+
</div>
50+
<div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]">
51+
<div className="text-[var(--purple)]">AI 摘要</div>
52+
<div className="text-[var(--text-muted)]">用 AI 生成历史摘要</div>
53+
</div>
54+
<div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]">
55+
<div className="text-[var(--terminal-green)]">重建上下文</div>
56+
<div className="text-[var(--text-muted)]">摘要 + 最近消息组成新上下文</div>
57+
</div>
58+
</div>
59+
</div>
60+
61+
{/* 源码位置 */}
62+
<div>
63+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">📁 源码位置</h3>
64+
<code className="text-xs bg-[var(--bg-void)] p-2 rounded block border border-[var(--border-subtle)]">
65+
packages/core/src/core/chatHistory.ts
66+
</code>
67+
</div>
68+
69+
{/* 相关机制 */}
70+
<div>
71+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">🔗 相关机制</h3>
72+
<div className="flex flex-wrap gap-2">
73+
<span className="px-2 py-1 bg-[var(--amber)]/20 text-[var(--amber)] rounded text-xs">Token 计数</span>
74+
<span className="px-2 py-1 bg-[var(--purple)]/20 text-[var(--purple)] rounded text-xs">消息格式</span>
75+
<span className="px-2 py-1 bg-[var(--cyber-blue)]/20 text-[var(--cyber-blue)] rounded text-xs">会话管理</span>
76+
<span className="px-2 py-1 bg-[var(--terminal-green)]/20 text-[var(--terminal-green)] rounded text-xs">记忆系统</span>
77+
</div>
78+
</div>
79+
</div>
80+
)}
81+
</div>
82+
);
83+
}
84+
485
// 消息类型
586
interface Message {
687
id: number;
@@ -295,6 +376,7 @@ export function ContextCompressionAnimation() {
295376
const [splitPoint, setSplitPoint] = useState<number | null>(null);
296377
const [isPlaying, setIsPlaying] = useState(false);
297378
const [currentStep, setCurrentStep] = useState(0);
379+
const [isIntroExpanded, setIsIntroExpanded] = useState(true);
298380

299381
const totalTokens = useMemo(
300382
() => messages.reduce((sum, m) => sum + m.tokens, 0),
@@ -414,10 +496,11 @@ export function ContextCompressionAnimation() {
414496

415497
<p className="text-sm text-[var(--text-muted)] font-mono mb-6">
416498
// 当 Token 使用量超过阈值时,自动压缩历史消息以释放空间
417-
<br />
418-
// 源码位置: packages/core/src/services/chatCompressionService.ts
419499
</p>
420500

501+
{/* 介绍部分 */}
502+
<Introduction isExpanded={isIntroExpanded} onToggle={() => setIsIntroExpanded(!isIntroExpanded)} />
503+
421504
{/* Controls */}
422505
<div className="flex gap-3 mb-6 flex-wrap">
423506
<button

src/pages/MCPDiscoveryAnimation.tsx

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,87 @@
11
import { useState, useEffect, useCallback } from 'react';
22
import { JsonBlock } from '../components/JsonBlock';
33

4+
// 介绍内容组件
5+
function Introduction({ isExpanded, onToggle }: { isExpanded: boolean; onToggle: () => void }) {
6+
return (
7+
<div className="mb-6 bg-[var(--bg-elevated)] rounded-lg overflow-hidden border border-[var(--border-subtle)]">
8+
<button
9+
onClick={onToggle}
10+
className="w-full px-4 py-3 flex items-center justify-between text-left hover:bg-[var(--bg-panel)] transition-colors"
11+
>
12+
<span className="text-lg font-semibold text-[var(--text-primary)]">📖 什么是 MCP 服务发现?</span>
13+
<span className={`transform transition-transform text-[var(--text-muted)] ${isExpanded ? 'rotate-180' : ''}`}></span>
14+
</button>
15+
16+
{isExpanded && (
17+
<div className="px-4 pb-4 space-y-4 text-sm">
18+
{/* 核心概念 */}
19+
<div>
20+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">🎯 核心概念</h3>
21+
<p className="text-[var(--text-secondary)]">
22+
<strong>MCP (Model Context Protocol)</strong> 是一种扩展 AI 能力的协议。通过 MCP 服务器,
23+
CLI 可以连接外部工具(如数据库、API、文件系统)。服务发现流程负责找到、连接并注册这些扩展服务。
24+
</p>
25+
</div>
26+
27+
{/* 为什么需要 */}
28+
<div>
29+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">❓ 为什么需要服务发现?</h3>
30+
<ul className="text-[var(--text-secondary)] space-y-1 list-disc list-inside">
31+
<li><strong>扩展能力</strong>:无需修改核心代码,插件式扩展功能</li>
32+
<li><strong>隔离错误</strong>:一个服务失败不影响其他服务</li>
33+
<li><strong>并行启动</strong>:多个服务同时连接,加快启动速度</li>
34+
<li><strong>动态工具</strong>:每个服务提供的工具自动注册到 AI</li>
35+
</ul>
36+
</div>
37+
38+
{/* 发现阶段 */}
39+
<div>
40+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">📊 发现阶段</h3>
41+
<div className="grid grid-cols-2 gap-2 text-xs">
42+
<div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]">
43+
<div className="text-[var(--cyber-blue)]">1. 加载配置</div>
44+
<div className="text-[var(--text-muted)]">读取内置/用户/项目级配置</div>
45+
</div>
46+
<div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]">
47+
<div className="text-[var(--cyber-blue)]">2. 并行连接</div>
48+
<div className="text-[var(--text-muted)]">spawn 进程,建立 stdio 通道</div>
49+
</div>
50+
<div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]">
51+
<div className="text-[var(--amber)]">3. 能力协商</div>
52+
<div className="text-[var(--text-muted)]">交换版本和能力信息</div>
53+
</div>
54+
<div className="bg-[var(--bg-void)] p-2 rounded border border-[var(--border-subtle)]">
55+
<div className="text-[var(--terminal-green)]">4. 工具注册</div>
56+
<div className="text-[var(--text-muted)]">将工具列表合并到 AI 上下文</div>
57+
</div>
58+
</div>
59+
</div>
60+
61+
{/* 源码位置 */}
62+
<div>
63+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">📁 源码位置</h3>
64+
<code className="text-xs bg-[var(--bg-void)] p-2 rounded block border border-[var(--border-subtle)]">
65+
packages/core/src/tools/mcp-client-manager.ts
66+
</code>
67+
</div>
68+
69+
{/* 相关机制 */}
70+
<div>
71+
<h3 className="text-[var(--terminal-green)] font-semibold mb-2">🔗 相关机制</h3>
72+
<div className="flex flex-wrap gap-2">
73+
<span className="px-2 py-1 bg-[var(--cyber-blue)]/20 text-[var(--cyber-blue)] rounded text-xs">工具系统</span>
74+
<span className="px-2 py-1 bg-[var(--purple)]/20 text-[var(--purple)] rounded text-xs">扩展系统</span>
75+
<span className="px-2 py-1 bg-[var(--amber)]/20 text-[var(--amber)] rounded text-xs">配置管理</span>
76+
<span className="px-2 py-1 bg-[var(--terminal-green)]/20 text-[var(--terminal-green)] rounded text-xs">进程管理</span>
77+
</div>
78+
</div>
79+
</div>
80+
)}
81+
</div>
82+
);
83+
}
84+
485
// MCP Server 状态
586
type ServerStatus = 'pending' | 'connecting' | 'negotiating' | 'ready' | 'error';
687

@@ -300,6 +381,7 @@ export function MCPDiscoveryAnimation() {
300381
const [servers, setServers] = useState<MCPServer[]>(initialServers);
301382
const [activeServerId, setActiveServerId] = useState<string | null>(null);
302383
const [isPlaying, setIsPlaying] = useState(false);
384+
const [isIntroExpanded, setIsIntroExpanded] = useState(true);
303385

304386
// 模拟服务器状态更新
305387
const updateServersForPhase = useCallback((phase: number) => {
@@ -403,10 +485,11 @@ export function MCPDiscoveryAnimation() {
403485

404486
<p className="text-sm text-[var(--text-muted)] font-mono mb-6">
405487
// Model Context Protocol 服务器的并行发现与工具注册
406-
<br />
407-
// 源码位置: packages/core/src/tools/mcp-client-manager.ts
408488
</p>
409489

490+
{/* 介绍部分 */}
491+
<Introduction isExpanded={isIntroExpanded} onToggle={() => setIsIntroExpanded(!isIntroExpanded)} />
492+
410493
{/* Controls */}
411494
<div className="flex gap-3 mb-6 flex-wrap">
412495
<button

0 commit comments

Comments
 (0)