AI-IDE 项目架构详解

基于 Eclipse Theia 1.66.0 的企业级 AI 集成开发环境


📊 项目概览

基本信息

  • 项目类型: Lerna 管理的 monorepo
  • 版本: 1.66.0
  • 包总数: 76 个包 (22 个 AI 相关 + 54 个 Theia 核心)
  • 技术栈: TypeScript 5.4.5 + React 18.2.0 + Monaco Editor
  • 部署方式: 浏览器版 (Web) + Electron 桌面版
  • 基础框架: Eclipse Theia (云端和桌面 IDE 框架)

核心特性

  • ✅ 多 AI 提供商抽象 (OpenAI, Claude, Ollama, Gemini 等 8+ 提供商)
  • ✅ Agent 驱动的智能编程助手
  • ✅ 上下文感知的 Prompt 系统
  • ✅ 代码补全、编辑器增强、终端集成
  • ✅ MCP (Model Context Protocol) 支持
  • ✅ VS Code 扩展兼容

🏗️ 项目目录结构

根目录结构

  1. /home/kinbos/Desktop/AI-IDE/
  2. ├── packages/ # 75 个运行时包
  3. ├── ai-* # 22 个 AI 相关包
  4. ├── core/ # Theia 核心框架
  5. ├── terminal/ # 终端模拟
  6. ├── editor/ # 代码编辑
  7. ├── debug/ # 调试支持
  8. ├── git/ # Git 集成
  9. ├── filesystem/ # 文件系统
  10. ├── task/ # 任务管理
  11. └── [50+ 其他包] # 其他 IDE 功能
  12. ├── dev-packages/ # 14 个开发工具包
  13. ├── application-manager/ # 应用管理
  14. ├── application-package/ # 应用打包
  15. ├── cli/ # CLI 工具
  16. └── ...
  17. ├── examples/ # 示例应用
  18. ├── browser/ # 浏览器版 IDE
  19. ├── electron/ # Electron 桌面版
  20. ├── playwright/ # UI 自动化测试
  21. └── api-tests/ # API 测试
  22. ├── configs/ # 构建配置
  23. ├── scripts/ # 构建脚本
  24. ├── .notes/ # 开发笔记
  25. └── lerna.json # Monorepo 配置

AI 包生态系统 (22 个包)

核心基础设施 (4 个)

  1. packages/
  2. ├── ai-core/ # AI 核心抽象层
  3. ├── LanguageModel # 语言模型接口
  4. ├── Agent # Agent 系统
  5. ├── PromptService # Prompt 构建
  6. └── VariableService # 上下文变量
  7. ├── ai-chat/ # 聊天服务
  8. ├── ChatService # 聊天管理
  9. ├── AgentService # Agent 协调
  10. └── SessionStore # 会话存储
  11. ├── ai-chat-ui/ # 聊天界面 (React)
  12. ├── ChatWidget # 聊天组件
  13. ├── MessageRenderer # 消息渲染
  14. └── InputArea # 输入区域
  15. └── ai-terminal/ # AI 增强终端
  16. ├── TerminalAgent # 终端 Agent
  17. └── CommandHelper # 命令助手

AI 提供商集成 (8 个)

  1. packages/
  2. ├── ai-openai/ # OpenAI GPT 模型
  3. ├── ai-anthropic/ # Anthropic Claude
  4. ├── ai-ollama/ # 本地 Ollama 模型
  5. ├── ai-google/ # Google Gemini
  6. ├── ai-hugging-face/ # Hugging Face 模型
  7. ├── ai-llamafile/ # Llamafile 本地模型
  8. ├── ai-codex/ # OpenAI Codex
  9. └── ai-vercel-ai/ # Vercel AI SDK 集成

专业功能 (10 个)

  1. packages/
  2. ├── ai-code-completion/ # 内联代码补全
  3. ├── ai-editor/ # 编辑器 AI 助手
  4. ├── ai-ide/ # IDE 编排 Agent
  5. ├── ai-claude-code/ # Claude Code 集成 (Alpha)
  6. ├── ai-mcp/ # Model Context Protocol
  7. ├── ai-mcp-server/ # MCP 服务器实现
  8. ├── ai-mcp-ui/ # MCP 配置界面
  9. ├── ai-scanoss/ # 许可证/安全扫描
  10. ├── ai-history/ # 对话历史管理
  11. └── ai-core-ui/ # AI 配置界面

🎯 前后端分离架构

架构层级说明

Theia 采用严格的按运行环境分层的架构模式:

  1. packages/{package-name}/src/
  2. ├── browser/ # 🌐 前端层 - 浏览器环境
  3. ├── node/ # 🖥️ 后端层 - Node.js 环境
  4. ├── common/ # 🔗 共享层 - 前后端通用
  5. ├── electron-browser/ # ⚡ Electron 渲染进程 (可选)
  6. ├── electron-main/ # ⚡ Electron 主进程 (可选)
  7. ├── electron-common/ # ⚡ Electron 共享代码 (可选)
  8. ├── electron-node/ # ⚡ Electron Node 层 (可选)
  9. └── browser-only/ # 🌐 纯浏览器环境 (可选)

实际统计数据

从 76 个包中的分层分布:

层级 包数量 占比
browser/ 66 87%
common/ 54 71%
node/ 47 62%
electron-browser/ 10 13%
electron-main/ 3 4%

📁 各层级详解

1️⃣ browser/ - 前端层

运行环境: 浏览器/Electron 渲染进程 可用 API: DOM, Window, React, Monaco Editor, xterm.js

典型文件示例

  1. // packages/terminal/src/browser/terminal-widget-impl.ts
  2. import { Terminal } from 'xterm';
  3. @injectable()
  4. export class TerminalWidgetImpl extends BaseWidget {
  5. protected readonly xterm: Terminal;
  6. @inject(TerminalServer) // RPC 代理,实际在后端
  7. protected readonly terminalServer: TerminalServer;
  8. constructor() {
  9. super();
  10. // 可以使用浏览器 API
  11. this.xterm = new Terminal({
  12. cursorBlink: true,
  13. theme: this.getTheme()
  14. });
  15. // 监听用户输入
  16. this.xterm.onData(data => {
  17. // 通过 RPC 发送到后端
  18. this.terminalServer.write(this.terminalId, data);
  19. });
  20. }
  21. protected render(): React.ReactNode {
  22. return <div ref={this.attachXterm} />;
  23. }
  24. }

包含内容

  • ✅ React 组件 (.tsx 文件)
  • ✅ UI Widgets 和视图
  • ✅ 前端服务
  • ✅ 前端 DI 模块 (*-frontend-module.ts)
  • ✅ 前端贡献点 (*-frontend-contribution.ts)
  • ✅ CSS 样式文件

Terminal 包示例

  1. packages/terminal/src/browser/
  2. ├── terminal-widget-impl.ts # 终端 UI Widget
  3. ├── terminal-frontend-contribution.ts # 命令、菜单贡献
  4. ├── terminal-frontend-module.ts # DI 容器配置
  5. ├── terminal-theme-service.ts # 主题服务
  6. ├── terminal-profile-service.ts # 配置管理
  7. ├── search/
  8. ├── terminal-search-widget.tsx # React 搜索组件
  9. └── terminal-search-container.ts # 搜索容器
  10. └── style/
  11. ├── terminal.css # 终端样式
  12. └── terminal-search.css # 搜索样式

2️⃣ node/ - 后端层

运行环境: Node.js 进程 可用 API: Node.js API, fs, child_process, path, os 等

典型文件示例

  1. // packages/terminal/src/node/shell-terminal-server.ts
  2. import * as pty from 'node-pty';
  3. import * as fs from 'fs-extra';
  4. @injectable()
  5. export class ShellTerminalServer implements IShellTerminalServer {
  6. protected readonly processes = new Map<number, TerminalProcess>();
  7. async create(options: IShellTerminalServerOptions): Promise<number> {
  8. // 使用 Node.js API 创建伪终端
  9. const ptyProcess = pty.spawn(options.shell, options.args, {
  10. name: 'xterm-256color',
  11. cols: 80,
  12. rows: 30,
  13. cwd: options.cwd || process.cwd(),
  14. env: { ...process.env, ...options.env }
  15. });
  16. const id = ptyProcess.pid;
  17. this.processes.set(id, ptyProcess);
  18. // 监听输出并通过 RPC 发送到前端
  19. ptyProcess.onData(data => {
  20. this.emitOutput(id, data);
  21. });
  22. return id;
  23. }
  24. async write(id: number, data: string): Promise<void> {
  25. const process = this.processes.get(id);
  26. if (process) {
  27. process.write(data);
  28. }
  29. }
  30. protected async readShellConfig(): Promise<string[]> {
  31. // 可以访问文件系统
  32. const content = await fs.readFile('/etc/shells', 'utf-8');
  33. return content.split('\n').filter(line => !line.startsWith('#'));
  34. }
  35. }

包含内容

  • ✅ 后端服务实现
  • ✅ 文件系统操作
  • ✅ 进程管理
  • ✅ 后端 DI 模块 (*-backend-module.ts)
  • ✅ 后端贡献点 (*-backend-contribution.ts)
  • ✅ CLI 工具实现

Terminal 包示例

  1. packages/terminal/src/node/
  2. ├── shell-terminal-server.ts # RPC 服务实现
  3. ├── shell-process.ts # Shell 进程管理
  4. ├── terminal-server.ts # 基础终端服务
  5. ├── terminal-backend-contribution.ts # 后端启动逻辑
  6. ├── terminal-backend-module.ts # DI 容器配置
  7. ├── buffering-stream.ts # 流缓冲
  8. └── test/
  9. └── terminal-test-container.ts # 测试容器

3️⃣ common/ - 共享层

运行环境: 前端和后端都可以使用 可用 API: ⚠️ 仅 JavaScript 基础 API (不能用 DOM 或 Node.js 特定 API)

典型文件示例

  1. // packages/terminal/src/common/terminal-protocol.ts
  2. // 1. 定义 RPC 服务接口
  3. export interface IShellTerminalServer {
  4. create(options: IShellTerminalServerOptions): Promise<number>;
  5. write(id: number, data: string): Promise<void>;
  6. resize(id: number, cols: number, rows: number): Promise<void>;
  7. destroy(id: number): Promise<void>;
  8. }
  9. // 2. 定义数据传输对象 (DTO)
  10. export interface IShellTerminalServerOptions {
  11. shell: string;
  12. args: string[];
  13. cwd?: string;
  14. env?: { [key: string]: string | null };
  15. }
  16. // 3. 定义 DI 符号
  17. export const IShellTerminalServer = Symbol('IShellTerminalServer');
  18. // 4. 定义 RPC 路径
  19. export const shellTerminalPath = '/services/shell-terminal';
  20. // 5. 定义事件类型
  21. export interface TerminalOutputEvent {
  22. id: number;
  23. data: string;
  24. }
  25. export interface TerminalExitEvent {
  26. id: number;
  27. code: number;
  28. }

包含内容

  • ✅ TypeScript 接口定义
  • ✅ 数据传输对象 (DTOs)
  • ✅ RPC 协议定义
  • ✅ 共享工具函数 (纯 JS)
  • ✅ 偏好设置定义
  • ✅ 常量和枚举

Terminal 包示例

  1. packages/terminal/src/common/
  2. ├── terminal-protocol.ts # 基础终端协议
  3. ├── shell-terminal-protocol.ts # Shell 终端协议
  4. ├── terminal-preferences.ts # 偏好设置
  5. ├── terminal-watcher.ts # 监听器接口
  6. ├── shell-type.ts # Shell 类型定义
  7. └── base-terminal-protocol.ts # 基础协议

4️⃣ electron-browser/ - Electron 渲染进程

运行环境: Electron 渲染进程 (浏览器 + 部分 Node API) 可用 API: DOM + Electron Renderer API + require()

典型示例

  1. // packages/core/src/electron-browser/menu/electron-menu-renderer.ts
  2. import { remote } from 'electron';
  3. @injectable()
  4. export class ElectronContextMenuRenderer {
  5. show(items: MenuItem[], x: number, y: number): void {
  6. const menu = remote.Menu.buildFromTemplate(
  7. items.map(item => ({
  8. label: item.label,
  9. click: () => item.execute()
  10. }))
  11. );
  12. menu.popup({ x, y });
  13. }
  14. }

5️⃣ electron-main/ - Electron 主进程

运行环境: Electron 主进程 (完整 Node.js + Electron Main API) 可用 API: Node.js + Electron Main API

典型示例

  1. // packages/core/src/electron-main/electron-main-application.ts
  2. import { app, BrowserWindow } from 'electron';
  3. @injectable()
  4. export class ElectronMainApplication {
  5. async start(): Promise<void> {
  6. await app.whenReady();
  7. const mainWindow = new BrowserWindow({
  8. width: 1200,
  9. height: 800,
  10. webPreferences: {
  11. nodeIntegration: true,
  12. contextIsolation: false
  13. }
  14. });
  15. await mainWindow.loadFile('index.html');
  16. }
  17. }

6️⃣ electron-common/ - Electron 共享代码

运行环境: Electron 主进程和渲染进程共享

  1. packages/core/src/electron-common/
  2. ├── electron-api.ts # Electron API 定义
  3. ├── electron-token.ts # 安全令牌
  4. └── electron-window-preferences.ts # 窗口偏好

🔗 前后端通信机制

RPC (Remote Procedure Call) 架构

前端和后端通过 WebSocket 进行双向通信,使用代理模式调用远程方法。

完整示例:Terminal 通信流程

  1. // ========================================
  2. // 第 1 步:在 common/ 定义接口
  3. // ========================================
  4. // packages/terminal/src/common/terminal-protocol.ts
  5. export const IShellTerminalServer = Symbol('IShellTerminalServer');
  6. export interface IShellTerminalServer {
  7. $createTerminal(options: TerminalOptions): Promise<number>;
  8. $write(id: number, data: string): void;
  9. $resize(id: number, cols: number, rows: number): void;
  10. onOutput: Event<TerminalOutputEvent>;
  11. }
  12. export interface TerminalOptions {
  13. shell: string;
  14. args: string[];
  15. cwd?: string;
  16. }
  17. export interface TerminalOutputEvent {
  18. id: number;
  19. data: string;
  20. }
  21. // ========================================
  22. // 第 2 步:在 node/ 实现后端服务
  23. // ========================================
  24. // packages/terminal/src/node/shell-terminal-server.ts
  25. import * as pty from 'node-pty';
  26. @injectable()
  27. export class ShellTerminalServer implements IShellTerminalServer {
  28. protected readonly processes = new Map<number, pty.IPty>();
  29. protected readonly onOutputEmitter = new Emitter<TerminalOutputEvent>();
  30. readonly onOutput = this.onOutputEmitter.event;
  31. async $createTerminal(options: TerminalOptions): Promise<number> {
  32. // 在后端创建真实的终端进程
  33. const ptyProcess = pty.spawn(options.shell, options.args, {
  34. cwd: options.cwd || process.cwd(),
  35. env: process.env
  36. });
  37. const id = ptyProcess.pid;
  38. this.processes.set(id, ptyProcess);
  39. // 监听终端输出
  40. ptyProcess.onData(data => {
  41. this.onOutputEmitter.fire({ id, data });
  42. });
  43. return id;
  44. }
  45. $write(id: number, data: string): void {
  46. const process = this.processes.get(id);
  47. if (process) {
  48. process.write(data);
  49. }
  50. }
  51. $resize(id: number, cols: number, rows: number): void {
  52. const process = this.processes.get(id);
  53. if (process) {
  54. process.resize(cols, rows);
  55. }
  56. }
  57. }
  58. // ========================================
  59. // 第 3 步:在 browser/ 通过代理调用
  60. // ========================================
  61. // packages/terminal/src/browser/terminal-widget-impl.ts
  62. import { Terminal } from 'xterm';
  63. @injectable()
  64. export class TerminalWidgetImpl extends BaseWidget {
  65. protected xterm: Terminal;
  66. protected terminalId: number;
  67. @inject(IShellTerminalServer)
  68. protected readonly server: IShellTerminalServer; // 自动注入 RPC 代理
  69. async initialize(): Promise<void> {
  70. // 创建 xterm.js 实例
  71. this.xterm = new Terminal();
  72. // 这个调用会通过 WebSocket 发送到后端
  73. this.terminalId = await this.server.$createTerminal({
  74. shell: '/bin/bash',
  75. args: [],
  76. cwd: '/home/user/project'
  77. });
  78. // 监听用户输入
  79. this.xterm.onData(data => {
  80. // 通过 RPC 发送到后端
  81. this.server.$write(this.terminalId, data);
  82. });
  83. // 监听后端输出
  84. this.server.onOutput(event => {
  85. if (event.id === this.terminalId) {
  86. this.xterm.write(event.data);
  87. }
  88. });
  89. // 窗口大小变化时通知后端
  90. this.xterm.onResize(({ cols, rows }) => {
  91. this.server.$resize(this.terminalId, cols, rows);
  92. });
  93. }
  94. }

消息流程图

  1. ┌─────────────────────────────────────────────────────────────────┐
  2. 用户输入流程
  3. └─────────────────────────────────────────────────────────────────┘
  4. 用户按键 "ls -la"
  5. xterm.js onData 事件
  6. TerminalWidgetImpl.xterm.onData(data => ...)
  7. server.$write(terminalId, "ls -la") 调用 RPC 代理
  8. ━━━━━━━━━━━━━━ WebSocket 消息 ━━━━━━━━━━━━━━
  9. {
  10. method: "$write",
  11. args: [12345, "ls -la"]
  12. }
  13. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  14. ShellTerminalServer.$write(12345, "ls -la")
  15. ptyProcess.write("ls -la") node-pty
  16. OS Shell (/bin/bash) 执行命令
  17. ┌─────────────────────────────────────────────────────────────────┐
  18. 输出返回流程
  19. └─────────────────────────────────────────────────────────────────┘
  20. OS Shell 输出: "total 128\ndrwxr-xr-x ..."
  21. node-pty: ptyProcess.onData(data => ...)
  22. ShellTerminalServer: onOutputEmitter.fire({ id: 12345, data })
  23. ━━━━━━━━━━━━━━ WebSocket 事件 ━━━━━━━━━━━━━━
  24. {
  25. event: "onOutput",
  26. data: { id: 12345, data: "total 128\n..." }
  27. }
  28. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  29. TerminalWidgetImpl: server.onOutput(event => ...)
  30. if (event.id === this.terminalId)
  31. this.xterm.write(event.data)
  32. xterm.js 渲染输出到屏幕

🤖 AI 包架构深度解析

AI-Core 包结构

  1. packages/ai-core/src/
  2. ├── browser/ # 前端 AI 服务
  3. ├── frontend-language-model-registry.ts # 模型注册表
  4. ├── frontend-language-model-service.ts # 模型服务代理
  5. ├── frontend-variable-service.ts # 变量解析服务
  6. ├── frontend-prompt-customization-service.ts # Prompt 定制
  7. ├── ai-core-frontend-module.ts # DI 容器
  8. ├── file-variable-contribution.ts # 文件上下文变量
  9. ├── open-editors-variable-contribution.ts # 打开编辑器变量
  10. └── theia-variable-contribution.ts # Theia 环境变量
  11. ├── node/ # 后端 AI 服务
  12. ├── backend-language-model-registry.ts # 后端模型注册
  13. ├── language-model-frontend-delegate.ts # 前端委托
  14. ├── token-usage-service-impl.ts # Token 使用统计
  15. └── ai-core-backend-module.ts # DI 容器
  16. └── common/ # 共享 AI 协议
  17. ├── language-model.ts # 核心模型接口
  18. ├── agent.ts # Agent 接口定义
  19. ├── prompt-service.ts # Prompt 服务接口
  20. ├── variable-service.ts # 变量服务接口
  21. ├── language-model-service.ts # 模型服务接口
  22. ├── prompt-text.ts # Prompt 文本类型
  23. ├── protocol.ts # RPC 协议
  24. └── tool-invocation-registry.ts # 工具调用注册表

AI-Chat 包结构

  1. packages/ai-chat/src/
  2. ├── browser/ # 聊天前端
  3. ├── frontend-chat-service.ts # 聊天服务实现
  4. ├── chat-session-store-impl.ts # 会话存储
  5. ├── custom-agent-factory.ts # 自定义 Agent 工厂
  6. ├── file-chat-variable-contribution.ts # 文件变量贡献
  7. ├── image-context-variable-contribution.ts # 图片上下文
  8. ├── task-context-service.ts # 任务上下文服务
  9. ├── chat-tool-request-service.ts # 工具请求服务
  10. └── ai-chat-frontend-module.ts # DI 容器
  11. ├── common/ # 聊天协议
  12. ├── chat-model.ts # 聊天数据模型
  13. ├── chat-service.ts # 聊天服务接口
  14. ├── chat-agent-service.ts # Agent 服务接口
  15. ├── chat-agents.ts # Agent 定义
  16. ├── chat-request-parser.ts # 请求解析器
  17. ├── chat-model-serialization.ts # 序列化/反序列化
  18. ├── chat-session-store.ts # 会话存储接口
  19. ├── parsed-chat-request.ts # 解析后的请求
  20. └── context-variables.ts # 上下文变量定义
  21. └── node/ # 聊天后端
  22. └── ai-chat-backend-module.ts # DI 容器

AI-Chat-UI 包结构

  1. packages/ai-chat-ui/src/browser/
  2. ├── chat-view-widget.tsx # 主聊天视图
  3. ├── chat-input-widget.tsx # 输入组件
  4. ├── chat-tree-view-widget.tsx # 会话树视图
  5. ├── chat-response-renderer/ # 消息渲染器
  6. ├── chat-response-renderer.tsx # 主渲染器
  7. ├── markdown-chat-response-renderer.tsx # Markdown 渲染
  8. ├── code-chat-response-renderer.tsx # 代码块渲染
  9. └── error-chat-response-renderer.tsx # 错误渲染
  10. ├── chat-response-content/ # 内容组件
  11. ├── command-chat-response-content.tsx # 命令响应
  12. ├── tool-call-chat-response-content.tsx # 工具调用
  13. └── delegation-response-content.tsx # 委托响应
  14. └── style/ # 样式
  15. └── chat.css

AI 消息流程

  1. ┌──────────────────────────────────────────────────────────────┐
  2. 用户发送消息流程
  3. └──────────────────────────────────────────────────────────────┘
  4. 用户输入: "帮我重构这个函数"
  5. ChatInputWidget (browser)
  6. ChatService.sendMessage(message)
  7. ChatRequestParser.parse(message)
  8. ├─> 提取 @文件引用
  9. ├─> 提取 /命令
  10. └─> 提取 #上下文
  11. AgentService.selectAgent(request)
  12. PromptService.buildPrompt(agent, request)
  13. ├─> 解析变量: ${file}, ${selection}, ${workspace}
  14. ├─> VariableService.resolve(variables)
  15. ├─> FileVariableContribution 读取文件内容
  16. ├─> EditorVariableContribution 获取选中内容
  17. └─> WorkspaceVariableContribution 获取项目信息
  18. └─> 构建最终 Prompt
  19. LanguageModelService.request(prompt, options)
  20. ├─> 路由到对应的提供商 (OpenAI/Claude/...)
  21. └─> 流式返回响应
  22. ChatResponseRenderer 渲染消息
  23. ├─> Markdown 内容
  24. ├─> 代码块
  25. ├─> 工具调用结果
  26. └─> 错误信息

📐 依赖规则和最佳实践

✅ 允许的依赖方向

  1. browser/ ──┐
  2. ├──> common/ (前端和后端都可以依赖 common)
  3. node/ ──┘
  4. electron-browser/ ──> browser/ ──> common/
  5. electron-main/ ──> node/ ──> common/
  6. electron-node/ ──> node/ ──> common/

❌ 禁止的依赖方向

  1. common/ ──✗──> browser/ # common 不能依赖前端
  2. common/ ──✗──> node/ # common 不能依赖后端
  3. browser/ ──✗──> node/ # 前端不能直接依赖后端
  4. node/ ──✗──> browser/ # 后端不能直接依赖前端

📝 架构最佳实践

1. 接口优先原则

  1. // ✅ 正确:在 common/ 定义接口
  2. // packages/my-package/src/common/my-service.ts
  3. export const MyService = Symbol('MyService');
  4. export interface MyService {
  5. doSomething(param: string): Promise<Result>;
  6. }
  7. // 在 node/ 实现
  8. // packages/my-package/src/node/my-service-impl.ts
  9. @injectable()
  10. export class MyServiceImpl implements MyService {
  11. async doSomething(param: string): Promise<Result> {
  12. // 后端实现
  13. }
  14. }
  15. // 在 browser/ 通过代理调用
  16. // packages/my-package/src/browser/my-widget.ts
  17. @injectable()
  18. export class MyWidget {
  19. @inject(MyService)
  20. protected readonly service: MyService; // RPC 代理
  21. }

2. DTO (Data Transfer Object) 模式

  1. // ✅ 正确:跨层传输的数据对象必须可序列化
  2. // packages/my-package/src/common/my-protocol.ts
  3. export interface MyDataDTO {
  4. id: string;
  5. name: string;
  6. timestamp: number;
  7. metadata: Record<string, unknown>;
  8. }
  9. // ❌ 错误:不能包含函数或类实例
  10. export interface BadDTO {
  11. id: string;
  12. process: ChildProcess; // ✗ Node.js 特定对象
  13. onClick: () => void; // ✗ 函数不能序列化
  14. date: Date; // ✗ 使用 number (timestamp) 代替
  15. }

3. RPC 服务命名规范

  1. // packages/my-package/src/common/my-protocol.ts
  2. // 1. 定义 Symbol
  3. export const MyRpcService = Symbol('MyRpcService');
  4. // 2. 定义接口,RPC 方法使用 $ 前缀
  5. export interface MyRpcService {
  6. $create(options: CreateOptions): Promise<number>;
  7. $update(id: number, data: UpdateData): Promise<void>;
  8. $delete(id: number): Promise<void>;
  9. onDataChange: Event<DataChangeEvent>;
  10. }
  11. // 3. 定义服务路径
  12. export const myRpcServicePath = '/services/my-rpc';

4. 模块化 DI 配置

  1. // packages/my-package/src/browser/my-frontend-module.ts
  2. export default new ContainerModule(bind => {
  3. // 绑定前端服务
  4. bind(MyWidgetFactory).toSelf().inSingletonScope();
  5. bind(MyFrontendService).toSelf().inSingletonScope();
  6. // 绑定 Widget
  7. bind(MyWidget).toSelf();
  8. bind(WidgetFactory).toDynamicValue(ctx => ({
  9. id: MY_WIDGET_ID,
  10. createWidget: () => ctx.container.get(MyWidget)
  11. })).inSingletonScope();
  12. // 绑定贡献点
  13. bind(FrontendApplicationContribution).to(MyFrontendContribution);
  14. bind(CommandContribution).to(MyCommandContribution);
  15. });
  16. // packages/my-package/src/node/my-backend-module.ts
  17. export default new ContainerModule(bind => {
  18. // 绑定后端服务
  19. bind(MyRpcService).to(MyRpcServiceImpl).inSingletonScope();
  20. // 绑定后端贡献点
  21. bind(BackendApplicationContribution).to(MyBackendContribution);
  22. });

5. 测试分离

  1. packages/my-package/src/
  2. ├── browser/
  3. ├── my-service.ts
  4. └── my-service.spec.ts # 前端单元测试
  5. ├── node/
  6. ├── my-backend-service.ts
  7. ├── my-backend-service.spec.ts # 后端单元测试
  8. └── my-backend-service.slow-spec.ts # 集成测试 (慢)
  9. └── common/
  10. ├── my-protocol.ts
  11. └── my-protocol.spec.ts # 协议测试

🚀 开发命令速查

基础命令

  1. # 安装依赖
  2. npm install
  3. # 编译所有 TypeScript 包
  4. npm run compile
  5. # 构建浏览器应用
  6. npm run build:browser
  7. # 启动浏览器开发服务器 (http://localhost:3000)
  8. npm run start:browser
  9. # 启动 Electron 桌面应用
  10. npm run start:electron
  11. # 监听模式 (自动重新编译)
  12. npm run watch

测试命令

  1. # 运行所有测试
  2. npm run test
  3. # 运行特定包的测试
  4. npx lerna run test --scope @theia/terminal
  5. # 运行测试并监听变化
  6. npx lerna run test:watch --scope @theia/ai-chat

包管理命令

  1. # 编译特定包
  2. npx lerna run compile --scope @theia/ai-core
  3. # 监听特定包及其依赖
  4. npx lerna run watch --scope @theia/ai-chat --include-filtered-dependencies --parallel
  5. # 清理所有构建产物
  6. npx lerna run clean

代码质量

  1. # 运行 ESLint
  2. npm run lint
  3. # 自动修复 lint 问题
  4. npm run lint:fix
  5. # 生成 API 文档
  6. npm run docs

📚 关键技术栈

技术 版本 用途
Eclipse Theia 1.66.0 IDE 基础框架
TypeScript ~5.4.5 开发语言
React 18.2.0 UI 框架
Monaco Editor 1.96.302 代码编辑器
InversifyJS 6.1.3 依赖注入容器
Express.js 4.21.0 后端 HTTP 服务器
Socket.io 4.5.3 WebSocket 实时通信
xterm.js - 终端模拟器
node-pty - 伪终端 (PTY)
Lerna 7.1.1 Monorepo 管理
Webpack 5.x 应用打包

🎯 当前开发重点

根据最近的 Git 提交记录和 .notes/ 目录:

最近提交 (倒序)

  1. 聊天窗口需求分析 (2025-11-21)

    • 规划聊天界面与终端的集成
  2. 终端时序图 (2025-11-21)

    • 文档化终端数据流和架构
  3. 终端模块分析 (2025-11-21)

    • 深入分析终端前后端通信机制

开发目标:Chat-Terminal 桥接

需求描述: 创建一个聊天界面,在后台隐藏终端中运行基于 CLI 的 AI 工具 (如 Claude Code 或 OpenAI Codex),将终端输出解析为聊天消息并展示给用户。

技术方案:

  1. ┌─────────────────────────────────────────────────────────────┐
  2. Chat-Terminal 桥接架构
  3. └─────────────────────────────────────────────────────────────┘
  4. 用户输入 (ChatInputWidget)
  5. ChatTerminalService.sendMessage(message)
  6. 创建隐藏终端 (TerminalService)
  7. 发送命令到终端: `claude-code "${message}"`
  8. 监听终端输出 (onOutput 事件)
  9. 解析 JSON 输出
  10. {
  11. "type": "message",
  12. "content": "AI 回复内容",
  13. "thinking": "思考过程"
  14. }
  15. 转换为 ChatMessage 对象
  16. ChatResponseRenderer 渲染

关键组件 (待实现):

  1. // packages/ai-terminal/src/browser/chat-terminal-widget.tsx
  2. @injectable()
  3. export class ChatTerminalWidget extends ReactWidget {
  4. @inject(ChatTerminalService)
  5. protected readonly chatTerminalService: ChatTerminalService;
  6. protected render(): React.ReactNode {
  7. return (
  8. <div className="chat-terminal-container">
  9. <MessageList messages={this.messages} />
  10. <ChatInput onSend={this.handleSend} />
  11. </div>
  12. );
  13. }
  14. protected handleSend = async (message: string) => {
  15. await this.chatTerminalService.sendMessage(message);
  16. };
  17. }
  18. // packages/ai-terminal/src/browser/chat-terminal-service.ts
  19. @injectable()
  20. export class ChatTerminalService {
  21. @inject(TerminalService)
  22. protected readonly terminalService: TerminalService;
  23. protected hiddenTerminal?: TerminalWidget;
  24. async sendMessage(message: string): Promise<void> {
  25. if (!this.hiddenTerminal) {
  26. this.hiddenTerminal = await this.createHiddenTerminal();
  27. }
  28. // 发送命令到隐藏终端
  29. await this.hiddenTerminal.sendText(
  30. `claude-code "${this.escapeMessage(message)}"\n`
  31. );
  32. }
  33. protected async createHiddenTerminal(): Promise<TerminalWidget> {
  34. const terminal = await this.terminalService.newTerminal({
  35. shell: '/bin/bash',
  36. cwd: this.workspaceRoot
  37. });
  38. // 监听输出并解析
  39. terminal.onOutput(data => {
  40. this.parseAndDispatch(data);
  41. });
  42. return terminal;
  43. }
  44. protected parseAndDispatch(data: string): void {
  45. try {
  46. const json = JSON.parse(data);
  47. if (json.type === 'message') {
  48. this.onMessageReceived.fire(json.content);
  49. }
  50. } catch (e) {
  51. // 非 JSON 输出,作为普通文本处理
  52. }
  53. }
  54. }

📖 学习路径建议

初级 - 理解基础架构

  1. ✅ 阅读本文档,理解整体架构
  2. ✅ 阅读 CLAUDE.mddoc/coding-guidelines.md
  3. ✅ 探索 packages/core/src/ 目录结构
  4. ✅ 运行浏览器应用: npm run start:browser
  5. ✅ 在浏览器调试工具中探索 DI 容器

中级 - 深入特定模块

  1. 选择一个模块深入学习 (推荐从 Terminal 开始)
  2. 阅读该模块的 common/ 接口定义
  3. 调试 browser/ 前端代码
  4. 调试 node/ 后端代码
  5. 跟踪 RPC 调用流程

高级 - 开发新功能

  1. 设计新功能的架构
  2. 定义 common/ 接口和 DTO
  3. 实现 node/ 后端服务
  4. 实现 browser/ 前端 UI
  5. 编写测试 (*.spec.ts)
  6. 集成到应用 (贡献点、命令、菜单等)

🔗 相关资源

官方文档

项目文档

  • /CLAUDE.md - Claude Code 使用指南
  • /doc/coding-guidelines.md - 编码规范
  • /doc/Testing.md - 测试指南
  • /doc/Plugin-API.md - 插件 API 文档

社区


🏁 总结

AI-IDE 是一个基于 Eclipse Theia 的企业级 AI 集成开发环境,采用严格的前后端分离架构

  • browser/ - 前端 UI 层 (React + Monaco + xterm.js)
  • node/ - 后端服务层 (Node.js + 文件系统 + 进程管理)
  • common/ - 共享协议层 (接口 + DTO + 常量)
  • electron-* - Electron 平台特定代码

通过 RPC over WebSocket 实现前后端通信,使用 InversifyJS 进行依赖注入,支持 VS Code 扩展,集成 8+ AI 提供商

当前开发重点是 Chat-Terminal 桥接功能,将 CLI 工具集成到聊天界面中。