nkds

导航

 

MonkeyCode 技术架构深度解析:从源码看 AI 编程助手的设计哲学

引言

"好的架构不是设计出来的,是在解决真实问题中演化出来的。"

MonkeyCode 作为开源 AI 编程助手的佼佼者,其技术架构融合了现代软件工程的众多最佳实践。本文将从源码层面深入分析 MonkeyCode 的核心架构设计——包括整体架构、模块划分、关键算法、性能优化策略等,帮助你理解一个生产级 AI 编程工具是如何设计和实现的。

无论你是想为 MonkeyCode 贡献代码,还是想借鉴其架构设计到自己的项目中,这篇深度解析都能提供有价值的参考。

🎯 核心信息


一、整体架构概览

1.1 系统架构图

┌─────────────────────────────────────────────────────────────────────┐
│                    MonkeyCode 核心架构                                │
│                                                                     │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                    Client Layer (客户端层)                    │   │
│  │  ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐    │   │
│  │  │ VSCode    │ │ JetBrains │ │ Vim/Neovim│ │ Web IDE   │    │   │
│  │  │ Extension │ │ Plugin    │ │ Plugin    │ │ Interface │    │   │
│  │  └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘    │   │
│  └────────┼────────────┼────────────┼────────────┼───────────┘   │
│           │            │            │            │                │
│           └────────────┴────────────┴────────────┘                │
│                              │                                     │
│  ┌───────────────────────────▼───────────────────────────────┐   │
│  │                  SDK Layer (SDK 层)                        │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐ │   │
│  │  │ Language    │  │ Editor      │  │ Protocol            │ │   │
│  │  │ Server SDK  │  │ Integration │  │ (JSON-RPC/gRPC)     │ │   │
│  │  └──────┬──────┘  └──────┬──────┘  └──────────┬──────────┘ │   │
│  └─────────┼────────────────┼────────────────────┼────────────┘   │
│            │                │                    │                 │
│  ┌─────────▼────────────────▼────────────────────▼────────────┐   │
│  │               Core Layer (核心层)                           │   │
│  │                                                            │   │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐  │   │
│  │  │ Context  │  │ Prompt   │  │ Model    │  │ Output   │  │   │
│  │  │ Engine  │  │ Builder  │  │ Router   │  │ Post-Proc│  │   │
│  │  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘  │   │
│  │       └──────────────┼────────────┼────────────┘          │   │
│  │                      ▼            ▼                       │   │
│  │              ┌──────────────────────────┐                │   │
│  │              │    Completion Pipeline   │                │   │
│  │              │  (请求编排与执行引擎)     │                │   │
│  │              └────────────┬─────────────┘                │   │
│  └───────────────────────────┼──────────────────────────────┘   │
│                              │                                   │
│  ┌───────────────────────────▼──────────────────────────────┐   │
│  │               Infrastructure Layer (基础设施层)             │   │
│  │                                                            │   │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐  │   │
│  │  │ Cache    │  │ Queue    │  │ Metrics  │  │ Config   │  │   │
│  │  │ (Redis)  │  │ (NATS)   │  │(Prometheus)│  │ Center   │  │   │
│  │  └──────────┘  └──────────┘  └──────────┘  └──────────┘  │   │
│  └───────────────────────────────────────────────────────────┘   │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

1.2 技术栈一览

层级 技术选型 说明
客户端 TypeScript + VSCode API / IntelliJ Platform API 跨 IDE 统一体验
通信协议 JSON-RPC 2.0 + WebSocket 低延迟双向通信
核心引擎 Rust(高性能模块)+ TypeScript(业务逻辑) 性能与开发效率的平衡
模型路由 自研 Model Router 多模型智能调度
缓存层 Redis Cluster 多级缓存策略
消息队列 NATS JetStream 异步任务处理
可观测性 Prometheus + OpenTelemetry 全链路追踪
配置中心 etcd + 本地配置文件 动态配置热更新

1.3 核心目录结构

monkeycode/
├── src/
│   ├── core/                    # 核心引擎
│   │   ├── context/            # 上下文管理引擎
│   │   │   ├── engine.ts       # 主上下文引擎
│   │   │   ├── indexer.ts      # 代码索引器
│   │   │   ├── trimmer.ts      # 智能裁剪器
│   │   │   └── cache.ts        # 上下文缓存
│   │   ├── prompt/             # Prompt 构建系统
│   │   │   ├── builder.ts      # Prompt 构建器
│   │   │   ├── templates/      # Prompt 模板库
│   │   │   └── optimizer.ts    # Prompt 优化器
│   │   ├── model/              # 模型路由与管理
│   │   │   ├── router.ts       # 智能路由器
│   │   │   ├── provider.ts     # 模型提供者抽象
│   │   │   └── fallback.ts     # 降级策略
│   │   ├── completion/         # 补全流水线
│   │   │   ├── pipeline.ts     # 流水线编排
│   │   │   ├── processor.ts    # 处理器链
│   │   │   └── ranker.ts       # 结果排序
│   │   └── output/             # 输出后处理
│   │       ├── filter.ts       # 安全过滤
│   │       ├── formatter.ts    # 格式化
│   │       └── dedup.ts        # 去重
│   ├── server/                 # 服务端
│   │   ├── api/                # REST API
│   │   ├── rpc/                # RPC 服务
│   │   ├── auth/               # 认证授权
│   │   └── middleware/          # 中间件
│   ├── client/                 # 客户端 SDK
│   │   ├── vscode/             # VSCode 插件
│   │   ├── jetbrains/          # JetBrains 插件
│   │   ├── vim/                # Vim/Neovim 插件
│   │   └── web/                # Web SDK
│   └── shared/                 # 共享代码
│       ├── types/              # 类型定义
│       ├── utils/              # 工具函数
│       └── constants/          # 常量定义
├── crates/                     # Rust 高性能模块
│   ├── context-indexer/        # 上下文索引(Rust)
│   ├── prompt-tokenizer/       # Prompt 分词器(Rust)
│   └── output-filter/          # 输出过滤器(Rust)
├── tests/                      # 测试
│   ├── unit/                   # 单元测试
│   ├── integration/            # 集成测试
│   └── e2e/                    # 端到端测试
└── docs/                       # 文档

二、核心模块深度解析

2.1 上下文管理引擎(Context Engine)

上下文管理是 AI 编程助手最核心的能力之一——如何从海量代码中提取最相关的信息,并在 Token 预算内构建最优的 Prompt

// src/core/context/engine.ts —— 上下文引擎核心实现

/**
 * MonkeyCode 上下文引擎
 * 
 * 设计理念:
 * 1. 相关性优先:只发送与当前补全位置最相关的代码
 * 2. Token 预算感知:严格控制上下文大小,避免浪费和截断
 * 3. 缓存友好:相似请求复用已计算的上下文
 * 4. 渐进式加载:先返回基础结果,再异步补充增强上下文
 */

import { LRUCache } from 'lru-cache';
import { CodeIndexer } from './indexer';
import { ContextTrimmer } from './trimmer';

export class ContextEngine {
  private indexer: CodeIndexer;
  private trimmer: ContextTrimmer;
  
  // 多级缓存:L1 内存缓存 → L2 Redis 缓存 → L3 重新计算
  private l1Cache: LRUCache<string, ResolvedContext>;
  private l2Cache: RedisCache;

  constructor(config: ContextEngineConfig) {
    this.indexer = new CodeIndexer(config.indexer);
    this.trimmer = new ContextTrimmer(config.trimmer);
    
    // L1 缓存:1000 条,5 分钟 TTL
    this.l1Cache = new LRUCache<string, ResolvedContext>({
      max: 1000,
      ttl: 1000 * 60 * 5,
    });
  }

  /**
   * 解析补全请求的上下文
   * 
   * 这是整个补全流程的入口之一,
   * 负责将用户的代码片段转换为模型可理解的丰富上下文。
   */
  async resolve(request: CompletionRequest): Promise<ResolvedContext> {
    const cacheKey = this.buildCacheKey(request);

    // 1. 尝试 L1 缓存
    const l1Hit = this.l1Cache.get(cacheKey);
    if (l1Hit) return l1Hit;

    // 2. 尝试 L2 缓存
    const l2Hit = await this.l2Cache.get(cacheKey);
    if (l2Hit) {
      this.l1Cache.set(cacheKey, l2Hit);
      return l2Hit;
    }

    // 3. 计算新上下文
    const context = await this.computeContext(request);
    
    // 写入缓存
    this.l1Cache.set(cacheKey, context);
    await this.l2Cache.set(cacheKey, context, { ttl: 300 });

    return context;
  }

  /**
   * 核心上下文计算逻辑
   */
  private async computeContext(request: CompletionRequest): Promise<ResolvedContext> {
    const { code, cursorPosition, filePath, language } = request;

    // Step 1: 基础上下文提取(光标附近的代码)
    const nearbyContext = this.extractNearbyCode(code, cursorPosition);
    
    // Step 2: 语义索引查询(基于 AST 的相关符号查找)
    const indexedSymbols = await this.indexer.queryRelatedSymbols({
      filePath,
      position: cursorPosition,
      language,
    });

    // Step 3: 导入依赖解析
    const imports = this.parseImports(code, language);
    const dependencyContext = await this.resolveDependencies(imports, filePath);

    // Step 4: 项目级配置和约定
    const projectConfig = await this.loadProjectConfig(filePath);

    // Step 5: 组装原始上下文
    const rawContext: RawContext = {
      nearby: nearbyContext,
      symbols: indexedSymbols,
      dependencies: dependencyContext,
      config: projectConfig,
      metadata: {
        language,
        filePath,
        cursorLine: this.getLineNumber(code, cursorPosition),
        timestamp: Date.now(),
      },
    };

    // Step 6: 智能裁剪(Token 预算约束下的最优子集)
    const trimmed = await this.trimmer.trim(rawContext, {
      maxTokens: request.maxContextTokens || 8000,
      priorityWeights: {
        nearbyCode: 0.4,      // 光标附近代码权重最高
        relatedSymbols: 0.3,   // 相关符号次之
        dependencies: 0.2,     // 依赖信息再次之
        projectConfig: 0.1,    // 项目配置最低
      },
    });

    return trimmed;
  }

  /**
   * 提取光标附近的代码
   * 
   * 策略:
   * - 向上取 N 行到最近的函数/类边界
   * - 向下取 M 行到下一个函数/类边界
   * - 包含完整的当前函数/类定义
   */
  private extractNearbyCode(code: string, position: number): NearbyCode {
    const lines = code.split('\n');
    const cursorLine = this.getLineNumber(code, position);
    
    // 使用 AST 解析找到函数/类边界(如果可用)
    // 否则使用启发式规则
    const boundaries = this.findSemanticBoundaries(lines, cursorLine);
    
    return {
      before: lines.slice(boundaries.start, cursorLine).join('\n'),
      after: lines.slice(cursorLine, boundaries.end).join('\n'),
      currentLine: lines[cursorLine],
      range: { start: boundaries.start, end: boundaries.end },
    };
  }
}

2.2 Prompt 构建系统

// src/core/prompt/builder.ts —— Prompt 构建器

/**
 * MonkeyCode Prompt 构建系统
 * 
 * 设计原则:
 * 1. 结构化:每个 Prompt 都有明确的结构(System/User/Context)
 * 2. 可配置:通过模板支持不同场景的定制化
 * 3. 可优化:自动优化 Prompt 以提高输出质量
 * 4. 可追踪:记录每次 Prompt 的组成用于调试和分析
 */

export class PromptBuilder {
  private templateEngine: TemplateEngine;
  private tokenizer: Tokenizer;
  private optimizer: PromptOptimizer;

  /**
   * 构建补全请求的完整 Prompt
   */
  async buildCompletionPrompt(
    context: ResolvedContext,
    request: CompletionRequest,
    options?: BuildOptions
  ): Promise<BuiltPrompt> {
    const startTime = Date.now();

    // 1. 选择合适的模板
    const template = this.selectTemplate(request.language, request.taskType);

    // 2. 准备变量
    const variables = await this.prepareVariables(context, request);

    // 3. 渲染模板
    let rendered = await this.templateEngine.render(template, variables);

    // 4. Token 计数检查和裁剪
    const tokenCount = await this.tokenizer.count(rendered);
    if (tokenCount > request.maxPromptTokens) {
      rendered = await this.smartTruncate(rendered, request.maxPromptTokens);
    }

    // 5. Prompt 优化(可选)
    if (options?.optimize !== false) {
      rendered = await this.optimizer.optimize(rendered, {
        language: request.language,
        targetModel: request.model,
      });
    }

    // 6. 构建最终结构
    const builtPrompt: BuiltPrompt = {
      system: this.extractSection(rendered, 'system'),
      user: this.extractSection(rendered, 'user'),
      context: this.extractSection(rendered, 'context'),
      fullText: rendered,
      metadata: {
        tokenCount: await this.tokenizer.count(rendered),
        buildTimeMs: Date.now() - startTime,
        templateName: template.name,
        optimizationApplied: options?.optimize !== false,
      },
    };

    return builtPrompt;
  }

  /**
   * 模板选择策略
   * 
   * 根据语言、任务类型、用户偏好选择最合适的 Prompt 模板
   */
  private selectTemplate(language: string, taskType: TaskType): PromptTemplate {
    // 优先级:用户自定义 > 语言特定 > 通用默认
    const customTemplate = this.templateEngine.findCustomTemplate(language, taskType);
    if (customTemplate) return customTemplate;

    const langTemplate = this.templateEngine.findLanguageTemplate(language);
    if (langTemplate) return langTemplate;

    return this.templateEngine.getDefaultTemplate(taskType);
  }
}

Prompt 模板示例

<!-- templates/completion/typescript.md -->

{{#system}}
You are an expert {{language}} programmer with deep knowledge of best practices,
design patterns, and common libraries. Your task is to provide accurate and helpful
code completions that follow the established coding style.

Rules:
- Complete the code at the cursor position
- Follow the existing code style (indentation, naming conventions, etc.)
- Prefer modern {{language}} features when appropriate
- Add comments for non-obvious logic
- Do not add unnecessary imports or dependencies
{{/system}}

{{#context}}
## Project Context
- Language: {{language}}
- File Path: {{filePath}}
- Related Symbols:
{{#each symbols}}
  - {{name}} ({{kind}}) defined at {{location}}: {{signature}}
{{/each}}

## Dependencies
{{#each dependencies}}
- {{name}} (version {{version}})
{{/each}}

## Code Conventions
{{projectConfig.conventions}}

## Nearby Code
```{{language}}
{{nearbyCode.before}}{{cursorMarker}}{{nearbyCode.after}}

{{/context}}

{{#user}}
Complete the code at the cursor position (marked by ).
Provide only the completion text, no explanations.

Requirements:
{{#if requirements}}
{{requirements}}
{{/if}}


### 2.3 模型路由器(Model Router)

```typescript
// src/core/model/router.ts —— 智能模型路由

/**
 * MonkeyCode 模型路由器
 * 
 * 核心能力:
 * 1. 根据任务特征选择最优模型
 * 2. 支持多 Provider 自动切换
 * 3. 智能降级和熔断机制
 * 4. 成本优化的模型调度
 */

export class ModelRouter {
  private providers: Map<string, ModelProvider>;
  private circuitBreakers: Map<string, CircuitBreaker>;
  private costTracker: CostTracker;

  /**
   * 为给定请求选择最佳模型
   */
  async route(request: RoutedRequest): Promise<ModelRoutingResult> {
    const candidates = this.getCandidateModels(request);
    
    // 1. 过滤不可用的模型(熔断中的、超限额的)
    const available = candidates.filter(c => this.isAvailable(c));
    
    if (available.length === 0) {
      // 所有模型都不可用,触发紧急降级
      return this.emergencyFallback(request);
    }

    // 2. 评分排序
    const scored = available.map(candidate => ({
      candidate,
      score: this.scoreCandidate(candidate, request),
    })).sort((a, b) => b.score - a.score);

    // 3. 选择最优模型
    const selected = scored[0].candidate;

    return {
      provider: selected.provider,
      model: selected.model,
      reason: selected.reason,
      estimatedCost: this.costTracker.estimate(selected.model, request),
      expectedLatency: selected.avgLatency,
    };
  }

  /**
   * 模型评分函数
   * 
   * 综合考虑多个维度:
   * - 任务匹配度(不同模型擅长不同类型的任务)
   * - 延迟要求(简单补全需要快速响应)
   * - 成本约束(在质量满足的前提下选择更便宜的)
   * - 可用性(当前健康状态和历史成功率)
   */
  private scoreCandidate(candidate: CandidateModel, request: RoutedRequest): number {
    let score = 0;

    // 任务匹配度(权重 40%)
    score += this.taskMatchScore(candidate, request) * 0.40;

    // 延迟适配(权重 30%)— 简单任务更看重速度
    const latencyWeight = request.isSimple ? 0.30 : 0.15;
    score += this.latencyScore(candidate, request.maxLatency) * latencyWeight;

    // 成本效率(权重 20%)
    score += this.costEfficiencyScore(candidate) * 0.20;

    // 可靠性(权重 10%)
    score += this.reliabilityScore(candidate) * 0.10;

    return score;
  }

  /**
   * 熔断器模式实现
   * 
   * 当某个模型的错误率超过阈值时,
   * 自动"断开"该模型一段时间,
   * 避免持续失败影响用户体验。
   */
  private isAvailable(candidate: CandidateModel): boolean {
    const breaker = this.circuitBreakers.get(candidate.id);
    if (!breaker) return true; // 无熔断器视为可用
    
    return breaker.allowRequest();
  }

  /**
   * 降级策略链
   * 
   * 当主模型不可用时的降级顺序:
   * 1. 同 Provider 的备用模型
   * 2. 其他 Provider 的等效模型
   * 3. 本地模型(如果有)
   * 4. 缓存结果(如果有历史相似请求)
   * 5. 返回空结果(最后手段)
   */
  private async emergencyFallback(request: RoutedRequest): Promise<ModelRoutingResult> {
    const fallbackChain = [
      () => this.trySameProviderFallback(request),
      () => this.tryCrossProviderFallback(request),
      () => this.tryLocalModel(request),
      () => this.tryCachedResult(request),
      () => this.emptyResult(),
    ];

    for (const fallback of fallbackChain) {
      try {
        const result = await fallback();
        if (result) return result;
      } catch (e) {
        continue; // 尝试下一个降级方案
      }
    }

    throw new Error('All fallback strategies exhausted');
  }
}

2.4 补全流水线(Completion Pipeline)

// src/core/completion/pipeline.ts —— 补全流水线编排

/**
 * MonkeyCode 补全流水线
 * 
 * 采用责任链模式(Chain of Responsibility),
 * 将补全过程分解为一系列可组合、可替换的处理阶段:
 * 
 * Request → Validate → ResolveContext → BuildPrompt → 
 * CallModel → PostProcess → Rank → Filter → Response
 */

export class CompletionPipeline {
  private stages: PipelineStage[];

  constructor(config: PipelineConfig) {
    this.stages = [
      new ValidationStage(),       // 参数验证
      new ContextResolutionStage(), // 上下文解析
      new PromptBuildingStage(),    // Prompt 构建
      new ModelCallStage(),         // 模型调用
      new PostProcessingStage(),    // 后处理
      new RankingStage(),           // 结果排序
      new FilteringStage(),         // 安全过滤
    ];
  }

  /**
   * 执行补全请求
   */
  async execute(request: CompletionRequest): Promise<CompletionResponse> {
    const context: PipelineContext = {
      request,
      metadata: {
        requestId: generateId(),
        startTime: Date.now(),
        stageTimings: {},
      },
    };

    try {
      // 依次执行各个阶段
      for (const stage of this.stages) {
        const stageStart = Date.now();
        
        context = await stage.execute(context);
        
        context.metadata.stageTimings[stage.name] = Date.now() - stageStart;

        // 如果某阶段返回了终止信号,提前结束
        if (context.shouldTerminate) break;
      }

      // 构建最终响应
      return this.buildResponse(context);

    } catch (error) {
      // 错误处理和优雅降级
      return this.handleError(error, context);
    }
  }

  /**
   * 并行优化:某些阶段可以并行执行
   * 
   * 例如:上下文解析可以和 Prompt 模板预加载并行
   */
  async executeOptimized(request: CompletionRequest): Promise<CompletionResponse> {
    // 阶段 1-2 可以并行
    const [validationResult, preloadedTemplates] = await Promise.all([
      new ValidationStage().execute({ request }),
      this.preloadTemplates(request),
    ]);

    // ... 后续处理
  }
}

三、性能优化策略

3.1 多级缓存体系

┌─────────────────────────────────────────────────────────────────┐
│                   MonkeyCode 多级缓存架构                         │
│                                                                 │
│  请求到达                                                       │
│     │                                                          │
│     ▼                                                          │
│  ┌─────────┐   命中率 ~40%    命中率 ~35%                       │
│  │ L1 缓存  │ ─────────────► │ L2 缓存  │                      │
│  │ (内存)   │                │ (Redis) │                       │
│  │ TTL: 5min│                │ TTL:30min│                      │
│  └─────────┘                └─────────┘                        │
│                                      │                          │
│                              未命中 │                          │
│                                      ▼                          │
│                               ┌──────────┐                     │
│                               │ L3 计算   │ ← 实际计算上下文    │
│                               │ (CPU/GPU) │                    │
│                               └──────────┘                     │
│                                                                 │
│  缓存 Key 设计:                                                 │
│  hash(file_path + cursor_position + file_hash + language +       │
│       surrounding_code_fingerprint + config_version)             │
│                                                                 │
│  缓存失效策略:                                                   │
│  - 文件内容变更(通过文件 hash 检测)                             │
│  - 配置变更                                                     │
│  - 模型版本升级                                                 │
│  - 手动刷新                                                     │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

3.2 关键性能指标

指标 目标值 优化手段
P50 延迟 < 200ms L1 缓存 + 本地小模型
P99 延迟 < 1000ms 异步预计算 + 流式返回
吞吐量 1000 QPS 连接池 + 批量处理
缓存命中率 > 70% 智能缓存 Key + 预取
错误率 < 0.1% 熔断 + 降级 + 重试
Token 利用率 > 85% 智能裁剪 + 压缩

3.3 Rust 高性能模块

// crates/context-indexer/src/lib.rs —— Rust 实现的高性能上下文索引器

//! MonkeyCode 上下文索引器
//! 
//! 使用 Rust 实现,通过 FFI 被 TypeScript 调用
//! 性能比纯 TypeScript 实现提升 10-50 倍

use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use tree_sitter::{Parser, Language, Node};

/// 代码索引器,基于 Tree-sitter 进行 AST 分析
pub struct CodeIndexer {
    parsers: HashMap<String, Parser>,
    index: Arc<RwLock<SymbolIndex>>,
}

/// 符号索引用于快速查找相关定义
#[derive(Clone)]
pub struct SymbolIndex {
    /// 文件 -> 符号列表
    files: HashMap<String, Vec<Symbol>>,
    /// 符号名 -> 定义位置(跨文件)
    symbol_map: HashMap<String, Vec<SymbolLocation>>,
}

#[derive(Clone, Debug)]
pub struct Symbol {
    pub name: String,
    pub kind: SymbolKind,  // Function, Class, Variable, etc.
    pub range: Range,
    pub signature: Option<String>,
    pub doc_comment: Option<String>,
}

impl CodeIndexer {
    /// 创建新的索引器实例
    pub fn new() -> Self {
        let mut parsers = HashMap::new();
        
        // 初始化各语言的 Tree-sitter parser
        parsers.insert("typescript".to_string(), 
            Parser::new(tree_sitter_typescript::LANGUAGE_TYPESCRIPT).unwrap());
        parsers.insert("python".to_string(), 
            Parser::new(tree_sitter_python::LANGUAGE_PYTHON).unwrap());
        parsers.insert("rust".to_string(), 
            Parser::new(tree_sitter_rust::LANGUAGE_RUST).unwrap());
        // ... 更多语言
        
        Self {
            parsers,
            index: Arc::new(RwLock::new(SymbolIndex::new())),
        }
    }

    /// 索引文件内容
    pub fn index_file(&self, path: &str, content: &str, language: &str) -> Result<Vec<Symbol>> {
        let parser = self.parsers.get(language)
            .ok_or_else(|| Error::UnsupportedLanguage(language.to_string()))?;
        
        let tree = parser.parse(content, None)
            .ok_or(Error::ParseFailed)?;
        
        let symbols = self.extract_symbols(&tree.root_node(), content)?;
        
        // 更新索引
        let mut index = self.index.write().unwrap();
        index.files.insert(path.to_string(), symbols.clone());
        for sym in &symbols {
            index.symbol_map.entry(sym.name.clone())
                .or_insert_with(Vec::new)
                .push(SymbolLocation {
                    file: path.to_string(),
                    range: sym.range,
                });
        }
        
        Ok(symbols)
    }

    /// 查询与给定位置相关的所有符号
    pub fn query_related_symbols(
        &self, 
        file: &str, 
        line: usize, 
        column: usize,
        radius: usize,
    ) -> Result<Vec<RelatedSymbol>> {
        let index = self.index.read().unwrap();
        
        // 1. 找到当前位置所在的符号
        let current_symbol = index.files.get(file)
            .and_then(|symbols| {
                symbols.iter().find(|s| s.range.contains(line, column))
            });
        
        let mut related = Vec::new();
        
        if let Some(sym) = current_symbol {
            // 2. 查找同名符号(重载、覆写等)
            if let Some(locations) = index.symbol_map.get(&sym.name) {
                for loc in locations {
                    if loc.file != file || !loc.range.contains(line, column) {
                        related.push(RelatedSymbol {
                            name: sym.name.clone(),
                            location: loc.clone(),
                            relation: RelationType::SameName,
                        });
                    }
                }
            }
            
            // 3. 查找同一作用域内的其他符号
            if let Some(symbols) = index.files.get(file) {
                for other in symbols {
                    if other.range.is_within_radius(sym.range, radius) && other.name != sym.name {
                        related.push(RelatedSymbol {
                            name: other.name.clone(),
                            location: SymbolLocation {
                                file: file.to_string(),
                                range: other.range,
                            },
                            relation: RelationType::NearbyScope,
                        });
                    }
                }
            }
        }
        
        Ok(related)
    }
}

四、安全架构

4.1 多层安全防护

┌─────────────────────────────────────────────────────────────────┐
│                   MonkeyCode 安全架构                             │
│                                                                 │
│  Layer 1: 输入过滤                                              │
│  ├─ 敏感信息检测(API Key、密码、Token)                         │
│  ├─ 恶意代码检测(混淆代码、反序列化攻击)                        │
│  └─ 输入大小限制                                                │
│                                                                 │
│  Layer 2: 处理安全                                              │
│  ├─ 沙箱执行环境                                                │
│  ├─ Prompt 注入防护                                             │
│  └─ 输出内容审计                                                │
│                                                                 │
│  Layer 3: 数据安全                                              │
│  ├─ 传输加密(TLS 1.3)                                         │
│  ├─ 存储加密(AES-256)                                          │
│  ├─ 访问控制(RBAC)                                            │
│  └─ 审计日志                                                    │
│                                                                 │
│  Layer 4: 合规保障                                              │
│  ├─ GDPR 合规(数据本地化选项)                                  │
│  ├─ SOC 2 Type II 认证                                          │
│  └─ 代码来源追溯                                               │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

4.2 敏感信息检测器

// src/core/output/filter.ts —— 安全过滤器

/**
 * 敏感信息检测与过滤
 * 
 * 使用多层检测策略:
 * 1. 正则表达式匹配(快速初筛)
 * 2. 语义分析(减少误报)
 * 3. 机器学习分类(高精度识别)
 */

export class SecurityFilter {
  private patterns: SecurityPattern[];
  private mlClassifier: MLClassifier | null;

  async filter(output: string, context: FilterContext): Promise<FilterResult> {
    const findings: SecurityFinding[] = [];
    let filteredOutput = output;

    // 第一遍:正则快速扫描
    const regexFindings = this.regexScan(output);
    findings.push(...regexFindings);

    // 第二遍:语义确认(降低误报)
    const confirmedFindings = await this.semanticConfirm(regexFindings, context);
    
    // 第三遍:ML 分类(可选,最高精度)
    if (this.mlClassifier) {
      const mlFindings = await this.mlClassify(filteredOutput, confirmedFindings);
      findings.push(...mlFindings);
    }

    // 应用脱敏处理
    for (const finding of findings.filter(f => f.confidence > 0.9)) {
      filteredOutput = this.redact(filteredOutput, finding);
    }

    return {
      safeOutput: filteredOutput,
      findings,
      hasHighRisk: findings.some(f => f.severity === 'critical'),
    };
  }

  /**
   * 内置安全模式库
   */
  private static readonly PATTERNS: SecurityPattern[] = [
    {
      id: 'api-key',
      name: 'API Key',
      regex: /(?:api[_\-]?key|apikey)\s*[:=]\s*["']([\w\-]{20,})["']/gi,
      severity: 'critical',
      category: 'credential',
    },
    {
      id: 'private-key',
      name: 'Private Key',
      regex: /-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |DSA )?PRIVATE KEY-----/gi,
      severity: 'critical',
      category: 'credential',
    },
    {
      id: 'password',
      name: 'Password in Code',
      regex: /(?:password|passwd|pwd)\s*[:=]\s*["'][^"']{6,}["']/gi,
      severity: 'high',
      category: 'credential',
    },
    {
      id: 'connection-string',
      name: 'Database Connection String',
      regex: /(?:mongodb|mysql|postgres|redis):\/\/[^\s]+/gi,
      severity: 'high',
      category: 'infrastructure',
    },
    {
      id: 'ip-address',
      name: 'Internal IP Address',
      regex: /\b(?:(?:10|172\.(?:1[6-9]|2\d|3[01])|192\.168)\.\d+\.\d+)\b/g,
      severity: 'medium',
      category: 'network',
    },
    // ... 更多模式
  ];
}

五、可观测性设计

5.1 全链路追踪

// src/shared/tracing.ts —— OpenTelemetry 集成

/**
 * MonkeyCode 全链路追踪
 * 
 * 每个补全请求都会生成唯一的 Trace ID,
 * 贯穿整个处理流程,便于问题定位和性能分析。
 */

import { trace, context, SpanStatusCode } from '@opentelemetry/api';
import { tracer } from './tracer-init';

export function traceCompletion<T>(
  operation: string,
  fn: (span: Span) => Promise<T>
): Promise<T> {
  const span = tracer.startSpan(`monkeycode.${operation}`, {
    attributes: {
      'monkeycode.version': PACKAGE_VERSION,
    },
  });

  return context.with(trace.setSpan(context.active(), span), async () => {
    try {
      const result = await fn(span);
      span.setStatus({ code: SpanStatusCode.OK });
      return result;
    } catch (error) {
      span.setStatus({
        code: SpanStatusCode.ERROR,
        message: error.message,
      });
      span.recordException(error);
      throw error;
    } finally {
      span.end();
    }
  });
}

// 使用示例
const result = await traceCompletion('completion.full_pipeline', async (span) => {
  span.setAttribute('request.language', request.language);
  span.setAttribute('request.file_type', getFileType(request.filePath));
  
  // 子操作会自动继承父 Span 的 Trace Context
  const context = await traceCompletion('context.resolve', async (ctxSpan) => {
    ctxSpan.setAttribute('context.strategy', 'hybrid');
    return contextEngine.resolve(request);
  })(span);
  
  // ...
});

5.2 关键 Metrics 定义

Metric 名称 类型 描述 告警阈值
completion_requests_total Counter 补全请求总数 -
completion_latency_ms Histogram 补全延迟分布 P99 > 2000ms
cache_hit_rate Gauge 缓存命中率 < 50%
token_usage_total Counter Token 消耗总量 -
error_total Counter 错误总数 > 1%
model_switch_count Counter 模型切换次数 -
security_findings_total Counter 安全发现数 Critical > 0

六、设计哲学总结

6.1 核心设计原则

原则 体现 示例
用户体验第一 响应速度优先 多级缓存 + 流式返回
渐进增强 从简单到复杂 先返回基础结果,再增强
可扩展性 插件化架构 Provider/Stage 可插拔
可观测性 全链路追踪 OpenTelemetry 集成
安全内置 默认安全 多层安全防护
开放透明 开源优先 Apache 2.0 协议

6.2 架构演进路线

v1.0 (2024 Q3)  MVP 版本
  └─ 基础补全功能 + 单模型支持

v2.0 (2024 Q4)  多模型支持
  └─ 模型路由 + 多 Provider + 基础缓存

v3.0 (2025 Q1)  企业级能力
  └─ 私有部署 + RBAC + 审计日志

v4.0 (2025 Q3)  智能化升级  ← 当前版本
  └─ 智能上下文 + Prompt 优化 + Rust 加速

v5.0 (2026 Q1 规划)  Agent 能力
  └─ 多步骤任务自主完成 + 工具调用

结语

"优秀的源码是最好的文档。"

MonkeyCode 的架构设计体现了团队对性能、可靠性、安全性、开发者体验的不懈追求。每一个模块的设计决策背后,都是对真实用户需求的深刻理解和对工程最佳实践的尊重。

如果你对 MonkeyCode 的源码感兴趣,欢迎:

  1. 📖 阅读源码: github.com/monkeycode-ai/monkeycode
  2. 🐛 提交 Issue: 发现问题或建议改进
    3 . 💡 贡献代码: PR 永远受欢迎!
  3. 💬 参与讨论: GitHub Discussions 等你

MonkeyCode 的未来,由我们共同书写! 🚀


本文由 MonkeyCode 社区原创,采用 Apache 2.0 许可证发布。

关键词: MonkeyCode 技术架构 源码解析 AI编程 开源 系统设计 Rust TypeScript

posted on 2026-06-25 12:47  MonkeyCode  阅读(25)  评论(0)    收藏  举报