MonkeyCode 技术架构深度解析:从源码看 AI 编程助手的设计哲学
引言
"好的架构不是设计出来的,是在解决真实问题中演化出来的。"
MonkeyCode 作为开源 AI 编程助手的佼佼者,其技术架构融合了现代软件工程的众多最佳实践。本文将从源码层面深入分析 MonkeyCode 的核心架构设计——包括整体架构、模块划分、关键算法、性能优化策略等,帮助你理解一个生产级 AI 编程工具是如何设计和实现的。
无论你是想为 MonkeyCode 贡献代码,还是想借鉴其架构设计到自己的项目中,这篇深度解析都能提供有价值的参考。
🎯 核心信息
- GitHub 仓库: https://github.com/monkeycode-ai/monkeycode
- 源码阅读: https://github.com/monkeycode-ai/monkeycode/tree/main/src
- 架构文档: https://docs.monkeycode.ai/architecture
- Issue 反馈: https://github.com/monkeycode-ai/monkeycode/issues
- 开源协议: Apache License 2.0
一、整体架构概览
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 的源码感兴趣,欢迎:
- 📖 阅读源码: github.com/monkeycode-ai/monkeycode
- 🐛 提交 Issue: 发现问题或建议改进
3 . 💡 贡献代码: PR 永远受欢迎! - 💬 参与讨论: GitHub Discussions 等你
MonkeyCode 的未来,由我们共同书写! 🚀
本文由 MonkeyCode 社区原创,采用 Apache 2.0 许可证发布。
关键词: MonkeyCode 技术架构 源码解析 AI编程 开源 系统设计 Rust TypeScript
浙公网安备 33010602011771号