Context

Context 模块包含 9 个 React Context Provider,覆盖模态框状态(modalContext)、通知系统(notifications)、统计指标(stats)、FPS 监控(fpsMetrics)、语音状态(voice)、消息队列(QueuedMessageContext)、覆盖层(overlayContext)、提示覆盖层(promptOverlayContext)和邮箱通信(mailbox)。每个 Context 是一个独立的状态域,通过 React 的 Provider/Consumer 模式实现跨组件的状态共享,避免 prop drilling。

职责与设计理念

职责说明

9 个 React Context Provider,管理 UI 层的全局状态分发

设计理念

上下文即边界——每个 Context 划定一个状态域的边界,组件只订阅自己关心的状态切片。9 个 Context 而非 1 个巨型 Store,是对"最小知识原则"的践行。

架构决策

为什么用 9 个独立 Context 而不是一个全局 Store(如 Redux)?

每个状态域一个 Context,拒绝全局 Store

终端 UI 的渲染性能极其敏感(目标 60fps)。全局 Store 的任何状态变更都会触发所有订阅者重渲染。独立 Context 让 FPS 监控的更新不会触发模态框的重渲染,实现精确的渲染隔离。

⚖️ 9 层 Provider 嵌套增加了组件树深度,但 React 的 Context 传播是 O(1) 的,不影响性能。

文件清单

文件名 用途
modalContext.tsx 模态框上下文,管理模态框尺寸、滚动引用和嵌套检测
stats.tsx 统计指标上下文,提供 counter/gauge/timer/set 四种指标原语
notifications.tsx 通知系统上下文,管理全局通知的推送与消费
voice.tsx 语音状态上下文,管理语音输入的激活与录音状态
fpsMetrics.tsx FPS 监控上下文,追踪终端渲染帧率
mailbox.tsx 邮箱通信上下文,跨组件的异步消息传递
overlayContext.tsx 覆盖层上下文,管理全屏覆盖层的显示状态
QueuedMessageContext.tsx 消息队列上下文,管理待发送消息的排队与消费

使用场景

AI 响应生成中

stats Context 实时更新 Token 计数和耗时,StatusLine 组件订阅并展示

工具执行需要授权

notifications Context 推送授权请求通知,TrustDialog 组件消费并渲染

语音输入激活

voice Context 切换录音状态,PromptInput 和 StatusLine 同步响应

依赖关系

  • Ink — 深度定制的终端渲染引擎,基于 Yoga 布局 + React Reconciler 实现终端 UI

关键代码片段

统计指标 Provider

function createStatsStore(): StatsStore {
  return {
    increment(name, value = 1) { /* 计数器递增 */ },
    set(name, value) { /* 仪表盘设值 */ },
    observe(name, value) { /* 直方图观测 */ },
    add(name, value) { /* 集合添加 */ },
    getAll() { /* 返回所有指标快照 */ },
  }
}

// 消费端 Hooks
function useCounter(name) { /* 返回 [value, increment] */ }
function useGauge(name) { /* 返回 [value, set] */ }
function useTimer(name) { /* 返回 { start, stop, elapsed } */ }

四种指标原语(counter/gauge/timer/set)覆盖所有运行时度量需求

邮箱通信模式

// 跨组件异步通信:生产者投递,消费者订阅
const MailboxContext = createContext<Mailbox>(null!)

interface Mailbox {
  send(channel: string, message: unknown): void
  subscribe(channel: string, handler: (msg: unknown) => void): () => void
}

// 使用场景:PromptInput 通知 Messages 刷新
mailbox.send('transcript:refresh', { reason: 'new-message' })

发布-订阅模式解耦组件通信,避免 prop 回调链的层层传递

技术笔记

performance

FPS 监控的采样策略

fpsMetrics Context 每 16ms 采样一次渲染帧率,使用滑动窗口平均值避免瞬时抖动。低于 30fps 时触发性能警告。