ChatBuddy 架构文档

July 25, 2026 · View on GitHub

最后更新:2026-07-25

本文档描述 ChatBuddy VS Code 扩展的整体架构、模块分层和数据流。


目录


概览

ChatBuddy 是一个 VS Code 侧边栏扩展,提供多助手 AI 聊天功能。架构遵循分层设计原则,核心层与 VS Code API 解耦,通过适配层(src/extension/)进行桥接。

┌─────────────────────────────────────────────────────────────┐
│                      VS Code 宿主环境                         │
│  (WebviewView, WebViewPanel, Commands, globalStorage, Events)│
└──────────────────────────┬──────────────────────────────────┘

┌──────────────────────────▼──────────────────────────────────┐
│              扩展适配层 (src/extension/)                      │
│  - 命令注册(settingsCommands, sessionCommands 等)           │
│  - 共享上下文类型 (shared.ts)                                 │
└──────────────────────────┬──────────────────────────────────┘

┌──────────────────────────▼──────────────────────────────────┐
│              扩展入口 (src/extension.ts)                      │
│  - activate/deactivate 生命周期                              │
│  - 依赖注入图的构建与组装                                     │
│  - SidebarViewProvider / PanelController 的实例化           │
└──────────────────────────┬──────────────────────────────────┘

┌──────────────────────────▼──────────────────────────────────┐
│              业务核心层 (src/chatbuddy/)                      │
│  - 状态管理 (stateRepository)                               │
│  - 聊天控制器 (chatController)                              │
│  - 提供商客户端 (providerClient)                            │
│  - MCP 运行时 (mcpRuntime)                                  │
│  - WebView 渲染 (webview*)                                  │
│  - 设置中心 (settingsCenter*)                               │
└─────────────────────────────────────────────────────────────┘

模块分层

1. 扩展入口层 (src/extension.ts)

activate() 函数是扩展的启动入口,负责:

  1. 全局异常兜底:注册 unhandledRejection 处理器,静默忽略 VS Code 生命周期中的良性错误
  2. 依赖注入:按顺序创建 Repository → ProviderClient → McpRuntime → ChatController
  3. 视图构建:创建侧边栏 WebviewView Provider(assistantsView,main/recycleBin 双模式)
  4. 面板控制器:初始化 SettingsCenterPanelController 和 AssistantEditorPanelController
  5. 命令注册:将所有命令注册到 VS Code 命令系统
  6. 订阅管理:通过 context.subscriptions 统一管理资源释放

关键类型:

  • ActivationSidebarViewProviders — 助手侧边栏 Webview View Provider(主视图 + 回收站模式)
  • PanelControllers — 设置中心和助手编辑器面板控制器

2. 命令层 (src/extension/)

命令按功能域拆分为多个模块,每个模块导出一个 register*Commands() 函数:

模块职责
settingsCommands.ts打开设置、模型配置、默认模型、MCP、关于页面
navigationCommands.ts打开助手聊天、"问 AI" 等导航命令
assistantTreeCommands.ts助手侧边栏的搜索、折叠、分组管理(转发到 Webview View)
assistantManagementCommands.ts助手的创建、编辑、删除、置顶、分组管理
sessionCommands.ts会话的创建、重命名、删除、导出、清空
localeMenuCommands.ts中英文菜单别名命令注册

所有命令共享一个 ExtensionContext 接口,通过解构获取依赖:

type ExtensionContext = {
  repository: ChatStateRepository;
  chatController: ChatController;
  settingsCenterPanelController: SettingsCenterPanelController;
  assistantEditorPanelController: AssistantEditorPanelController;
  sidebarViewProviders: ActivationSidebarViewProviders;
  refreshAll: () => void;
  getRuntimeLocale: () => string;
  getRuntimeStrings: () => Record<string, string>;
};

3. 业务核心层 (src/chatbuddy/)

3.1 状态管理

ChatStateRepository (stateRepository.ts)

单一状态源(Single Source of Truth),管理 PersistedStateLite

PersistedStateLite
├── groups: AssistantGroup[]       ← 分组(默认、自定义、回收站)
├── assistants: AssistantProfile[] ← 助手列表
├── selectedAssistantId?: string   ← 当前选中的助手
├── selectedSessionIdByAssistant   ← 每个助手当前选中的会话
├── sessionPanelCollapsed: boolean ← 会话面板折叠状态
├── collapsedGroupIds: string[]    ← 折叠的分组 ID
└── settings: ChatBuddySettings    ← 全局设置

Repository 内部通过服务拆分管理不同领域:

  • AssistantStateService — 助手 CRUD、分组管理、软删除/恢复
  • SessionStateService — 会话 CRUD、消息操作
  • StatePersistenceService — 状态持久化(读写 Compass 存储)

状态读取带版本缓存getState() 在版本未变化时返回缓存副本,避免重复深拷贝。

3.2 聊天控制器

ChatController (chatController.ts)

核心协调器,聚合 3 个子服务:

子服务文件职责
ChatGenerationServicechatControllerGenerationService.ts消息发送、流式响应、标题生成
ChatPanelManagerchatControllerPanelManager.tsWebView 面板生命周期管理
ToolCallOrchestratorchatControllerToolOrchestrator.tsMCP/函数工具调用编排

ChatController 本身不处理业务细节,只负责:

  • WebView 消息路由(routeChatControllerWebviewMessage
  • 状态载荷构建(chatControllerPayload.ts
  • 面板状态同步(setActivePanelChangeCallback

辅助模块

模块文件职责
MCP 操作代理chatControllerMcpOperations.tsMCP 资源/Prompt 操作的复用逻辑
状态缓存chatControllerStateCache.ts生成期 sessions 缓存(TTL 30s)

超时机制ChatGenerationServiceToolCallOrchestrator 在发起 AI 请求时设置全局超时(默认无限制,timeoutMs=0,用户可在设置中心配置)。超时仅在首次响应等待阶段生效——首个流式 token 到达后清除全局超时计时器,后续由 consumeSseResponsereadWithTimeout 检测连接中断。超时触发时先 setAbortReason('timeout')abort(),确保错误处理读到正确的中止原因。当 timeoutMs 为 0 时,跳过超时计时器创建,请求不会因超时中断。

3.3 提供商客户端

OpenAICompatibleClient (providerClient.ts)

统一的 OpenAI 兼容 API 客户端,支持:

提供商API 类型特点
OpenAIchat_completions / responses原生支持
Geminichat_completions / gemini代理适配 + 原生 API
OpenRouterchat_completions统一路由
Ollamachat_completions本地模型,自动模型列表获取
自定义chat_completions任意兼容端点

子模块

模块文件职责
类型定义providerClientTypes.tsProvider 相关类型定义
请求构建器providerClientRequestBuilders.ts将内部配置转换为不同 API 的请求体
响应解析器providerClientParsers.ts处理流式和非流式响应
模型获取器providerClientModelFetchers.ts从 Provider 获取可用模型列表
媒体处理providerClientMedia.ts图片/文件等多媒体处理
HTTP 错误providerClientErrors.tsHttpError/ensureSuccess/toErrorMessage 共享定义(消除循环依赖)

3.4 MCP 运行时

McpRuntime (mcpRuntime.ts)

MCP (Model Context Protocol) 客户端运行时,负责:

  • 服务器连接管理(stdio / SSE / streamableHttp 三种传输)
  • 工具发现与调用
  • 资源读取与 Prompt 获取
  • 连接清理(pruneConnections

辅助模块

模块文件职责
MCP 类型mcpTypes.tsMCP 相关类型定义
MCP 工具函数mcpUtils.tsMCP 操作的工具函数

MCP 模块是 ESM-only,通过动态 import() 在运行时加载。


数据流

用户发送消息的完整数据流

用户输入


┌──────────────┐     WebView message     ┌──────────────┐
│  Chat WebView │ ──(sendMessage)────────>│ ChatController│
└──────────────┘                          └──────┬───────┘

    ┌────────────────────────────────────────────┤
    │                                            ▼
    │                              ┌─────────────────────────┐
    │                              │   ChatGenerationService  │
    │                              │  - resolveProviderConfig │
    │                              │  - buildProviderMessages │
    │                              │  - startStream / complete│
    │                              └──────┬──────────────────┘
    │                                     │
    │         stream chunks               │
    │    <───────────────────────────────┤
    │                                     │
    │                              ┌──────▼──────┐
    │                              │ ProviderClient│
    │                              │  (fetch API)  │
    │                              └──────┬──────┘
    │                                     │
    ▼                                     ▼
┌──────────────────────────────────────────────────────┐
│              ChatStateRepository                      │
│  - appendMessage()                                    │
│  - updateLastAssistantMessage() (streaming)           │
│  - SessionStateService                                │
└──────────────────┬───────────────────────────────────┘


┌──────────────────────────────────────────────────────┐
│              StatePersistenceService                  │
│  - persist() → CompassSessionStore.persist()          │
│  - persistSecrets() → CompassSettingsStore.persist()  │
└──────────────────┬───────────────────────────────────┘


┌──────────────────────────────────────────────────────┐
│              Compass Storage (文件系统)               │
│  - sessions/index.compass.json                        │
│  - sessions/{assistantId}/{sessionId}.jsonl          │
└──────────────────────────────────────────────────────┘


                   │ 状态变更触发

            ┌─────────────┐
             │ refreshAll() │ → 侧边栏 Webview View 刷新 + WebView state 推送
            └─────────────┘

持久化可靠性机制

StatePersistenceService 内置多项可靠性保障:

机制说明
persistDirty 标志persistScheduled 去重期间累积变更,完成后自动重触发,防止更新丢失
失败重试executeWithRetry(3 次递增退避);settingsStore.persist() 写失败时抛出(保留 dirty),ChatStorage.flush() 将失败传播给调用方,保证重试路径真正生效
API keys 独立写入结构化文件与 API keys 文件分别 try-catch,互不影响
竞态保护recentlyDeletedProviderIds / recentlyDeletedMcpServerIds 防止 WebView 竞态重建(已覆盖单元测试)
跨进程文件锁withFileLock(O_EXCL 锁文件 + stale 检测)在 enqueuePersist 串行化多 IDE 窗口的并发写入,避免全量重写互相覆盖
全量快照恢复createPrePersistSnapshot 备份全部 6 个结构化文件(每 key 独立快照、各保留 3 代),崩溃恢复时优先从快照还原 providers/mcp 等完整数据,而非默认空值

WebView 状态同步流

ChatController

    ├───> buildChatStatePayload() ──> ChatStatePayload
    │                                    │
    │                                    ├── groups, assistants, sessions
    │                                    ├── selectedAssistant, selectedSession
    │                                    ├── modelOptions, mcpServers
    │                                    └── locale, strings, streaming, isGenerating

    ├───> panel.webview.postMessage({ type: 'state', payload })

    └───> 流式过程中定时推送(throttled)

核心模块详解

侧边栏视图体系

AssistantsSidebarViewProvider (sidebarViewAssistants.ts)

唯一的侧边栏 Webview View Provider(注册于 chatbuddy.assistantsView),通过运行时模式切换服务于两种视图:

  • 主视图模式 (main) — 显示活跃助手(默认分组 + 自定义分组),支持搜索、分组折叠
  • 回收站模式 (recycle) — 显示已删除的助手,支持恢复/彻底删除

通过 webview 内自定义菜单替代原 view/item/context 右键菜单,渲染分组与助手列表,交互通过 postMessage 与 Extension Host 通信。

会话管理不占用独立侧边栏视图,已迁移至聊天 WebView 内的浮出面板(webviewChatJs/sessionPanel.ts);设置中心是独立的 WebviewPanel,同样不经过侧边栏。

设置中心

SettingsCenterPanelController (settingsCenterPanel.ts)

设置面板控制器,管理一个 WebViewPanel,内部通过 iframe 或单页应用方式渲染多个设置页面:

页面对应 JS 模块功能
模型配置settingsCenterJs/modelConfig.tsProvider CRUD、模型获取
默认模型settingsCenterJs/defaultModels.ts默认助手模型、标题总结模型
MCPsettingsCenterJs/mcp.tsMCP 服务器管理
通用设置settingsCenterJs/general.ts快捷键、语言、超时等
公告settingsCenterJs/notice.ts更新日志渲染
关于settingsCenterJs/about.ts版本信息

设置中心与 Extension Host 通过 postMessage 双向通信。

助手编辑器

AssistantEditorPanelController (assistantEditorPanel.ts)

助手创建/编辑面板,提供表单编辑助手的所有属性:系统提示词、问候语、模型选择、温度等。


WebView 渲染体系

ChatBuddy 使用 VS Code WebView API 渲染聊天界面。HTML 通过代码组装生成(无外部 HTML 文件)。

渲染流水线

getChatWebviewHtml()
    ├── getNonce() + buildCsp()           ← CSP 安全策略
    ├── getCodiconStyleText()             ← VS Code 图标字体
    ├── getChatPanelCss()                 ← 聊天面板样式
    ├── getChatBodyHtml()                 ← HTML body 结构
    └── getChatScript()                   ← JS 逻辑
            ├── webviewChatScript.ts      ← 主脚本:状态管理、消息路由
            ├── webviewChatScriptEvents.ts ← 事件处理:点击、滚动、粘贴
            ├── webviewChatScriptMarkdown.ts ← Markdown 渲染:代码高亮、KaTeX、Mermaid
            └── webviewChatScriptUi.ts    ← UI 交互:输入框、工具栏、模态框

依赖的外部库

用途加载方式
KaTeX数学公式渲染node_modules 内联加载
Mermaid流程图/时序图node_modules 内联加载
CodiconVS Code 图标字体内联 CSS

侧边栏 Webview 渲染体系

侧边栏 view(assistantsView,main/recycleBin 双模式)同样使用 WebviewViewProvider 渲染,与聊天面板和设置中心共用 CSP / postMessage / codicon 模式,但走独立的轻量协议。

  • 抽象基类BaseSidebarViewProvider<TState, TMessage>sidebarViewBase.ts)封装 ready 握手、全量状态推送、显式清空搜索与资源释放。
  • 共享基建sidebarViewStyles.ts(VS Code CSS 变量)、sidebarViewHtml.ts(HTML 骨架)、sidebarViewSorters.ts(排序逻辑)、sidebarViewTypes.ts(消息联合类型)。
  • 前端 JSsidebarViewJs/ 下按职责拆分(index / assistants / shared / treeList / contextMenu / searchBox)。
  • 具体 ProvidersidebarViewAssistants.ts(同时服务助手主视图与回收站模式)。

侧边栏右键菜单不再使用原生 view/item/context,改为 Webview 内自定义右键菜单,命令通过 {type:'invokeCommand', command, args} 消息回传 Host,Host 端命令 handler 统一改为 id-based 签名。

详细的通信消息格式见 WEBVIEW_PROTOCOL.md 的「侧边栏 Webview 通信协议」章节。


存储体系

详见 STORAGE.md


依赖关系

模块依赖方向

extension.ts (顶层组装)
    ├── extension/*.ts (命令层)
    └── chatbuddy/*.ts (业务核心)
        ├── compassStorage/ (存储)
        ├── i18n/ (国际化)
        ├── settingsCenterJs/ (设置面板前端)
        └── utils/ (工具函数)

核心禁止循环依赖

  • ChatStateRepository 不依赖 ChatController
  • ChatController 依赖 ChatStateRepository(单向)
  • ProviderClient 不依赖任何上层模块
  • McpRuntime 不依赖任何上层模块
  • CompassStorage 不依赖任何上层模块

引入新 Provider 的步骤

  1. types.tsProviderKind 中添加新类型
  2. providerClientRequestBuilders.ts 中添加请求体构造逻辑
  3. providerClientParsers.ts 中添加响应解析逻辑
  4. providerClientModelFetchers.ts 中添加模型列表获取逻辑(如支持)
  5. modelCapabilityRegistry.ts 中注册已知模型能力

相关文档