Context Mode (上下文模式) 的核心架构是一个三层流水线:MCP 服务器层接收和路由 ctx_* 工具调用;多语言执行引擎在严格限制的沙盒中运行用户代码,防止资源耗尽;FTS5 知识库负责将原始数据索引并提供多级回退的精准搜索。整个系统的设计目标是将大块原始数据拦截在 AI 的上下文窗口之外,仅将极小的索引入口或执行结果送入模型,从而实现高达 98% 的上下文节省。

Context Mode 架构深度剖析:MCP 服务器、沙箱执行引擎与 FTS5 知识库的工作原理

理解 Context Mode 如何将巨大的原始数据(如代码库、日志、文档)转化为微小的上下文入口,关键在于剖析其三层协作的架构:MCP 服务器层、沙箱执行引擎和 FTS5 知识库。下图概述了其工作流,后续章节将逐层深入代码实现。

graph TD
    A[AI 编码助手/平台<br>Claude Code, Cursor...] --> B[MCP 服务器层<br>server.ts];
    B -- ctx_execute, ctx_batch_execute --> C[沙箱执行引擎<br>executor.ts];
    B -- ctx_fetch_and_index, ctx_index --> D[FTS5 知识库<br>store.ts];
    B -- ctx_search --> D;
    C -- 执行结果 --> B;
    D -- 搜索结果 --> B;
    B -- 工具调用/结果 --> A;

第一层:MCP 服务器层 — 工具注册与路由中枢

MCP (模型上下文协议) 服务器是 Context Mode 与各 AI 平台交互的入口。在 server.ts 中,它定义并注册了一系列 ctx_* 工具,构成了系统的对外接口。

启动时,服务器会检测当前运行环境并确定项目目录,这是后续所有路径解析的基础。

// src/server.ts
const executor = new PolyglotExecutor({
  runtimes,
  projectRoot: () => getProjectDir(),
});

随后,它会向 MCP 协议层注册工具。核心是 11 个以 ctx_ 开头的工具,例如 ctx_executectx_searchctx_fetch_and_index 等。注册过程通过 server.registerTool 完成,并用一个 wrapToolHandler 函数包装,用于捕获工具执行中的错误和进行统计追踪。

// src/server.ts (简化示例)
server.registerTool('ctx_execute', {
  // ... 工具描述和参数定义 ...
}, async (args) => {
  // 工具的具体逻辑
  return executor.execute(args);
});

为了确保在所有 15 个支持的平台(如 Claude Code、Gemini CLI、Cursor)上行为一致,服务器层还负责解析项目路径 (getProjectDir())、管理会话状态 (SessionDB) 和处理平台特定的适配器逻辑。当接收到工具调用时,它将请求路由到正确的处理器(执行引擎或知识库)。

第二层:沙箱执行引擎 — 多语言管道与严格的流量控制

当 AI 决定“用代码思考”并调用 ctx_executectx_batch_execute 时,请求会到达 executor.ts 中定义的 PolyglotExecutor。这个引擎的核心职责是在隔离的沙盒中安全地执行多语言代码,并严格限制输出量

多语言支持与命令构建

引擎支持 11 种语言(JavaScript、Python、Shell 等)。执行前,它会在一个临时目录中创建脚本文件,并根据语言和运行时信息构建最终的执行命令。

// src/runtime.ts
export function buildCommand(runtimes, language, filePath): string[] {
  switch (language) {
    case 'python':
      return [runtimes.python, filePath];
    case 'shell':
      // 平台特定的 shell 命令处理
      return [runtimes.shell, filePath];
    // ... 其他语言
  }
}

硬上限流量控制

最关键的防护机制是 hardCapBytes。执行引擎在 #spawn 方法中实时监控子进程 stdoutstderr 的总字节数。一旦累计超过阈值(默认 100MB,由构造函数中的 this.#hardCapBytes 定义),就会立即终止进程树,防止如 yescat /dev/urandom 这样的命令耗尽内存或填满磁盘。

// src/executor.ts (核心逻辑)
let totalBytes = 0;
proc.stdout!.on('data', (chunk: Buffer) => {
  totalBytes += chunk.length;
  if (totalBytes <= this.#hardCapBytes) {
    stdoutChunks.push(chunk);
  } else if (!capExceeded) {
    capExceeded = true;
    killTree(proc); // 立即终止进程树
  }
});

执行结果(或截断后的部分结果)会返回给 MCP 服务器层,再由服务器返回给 AI。这个设计确保了即使用户或 AI 执行了危险的代码,系统资源也受到保护。

第三层:FTS5 知识库 — 三层搜索降级与精准检索

Context Mode 的知识存储和检索核心是 store.ts 中的 ContentStore。它使用 SQLite 的 FTS5 扩展实现全文搜索,并内置了一套优雅的三级搜索降级策略,以平衡搜索的精确度和召回率。

数据索引

当调用 ctx_fetch_and_index 索引一个网页,或 ctx_index 索引文件时,原始文本会被解析并分块(如按 Markdown 标题),然后同时存入两个 FTS5 虚拟表:一个使用 porter 词干分析器(用于精确匹配),一个使用 trigram 分词器(用于模糊匹配)。

-- src/store.ts (Schema)
CREATE VIRTUAL TABLE IF NOT EXISTS chunks USING fts5(
  title, content, ...,
  tokenize='porter unicode61' -- 用于精确搜索
);
CREATE VIRTUAL TABLE IF NOT EXISTS chunks_trigram USING fts5(
  title, content, ...,
  tokenize='trigram' -- 用于模糊搜索
);

三级搜索降级 (searchWithFallback)

当 AI 调用 ctx_search 时,ContentStore 会按以下顺序尝试,直到获得足够数量的结果:

  1. 第一级:Porter 词干搜索 (search) 使用最精确的搜索,基于词干匹配和 BM25 排名算法。这是默认的首选策略。

  2. 第二级:Trigram 模糊搜索 (searchTrigram) 如果 Porter 搜索没有结果,则降级到 Trigram 搜索。它允许拼写错误和部分匹配,适合搜索代码标识符或专业术语。

  3. 第三级:Fuzzy Levenshtein 纠错 (fuzzyCorrect) 如果前两级都失败,系统会尝试从 vocabulary 表中寻找与查询词“编辑距离”最近的词,然后用纠正后的词重新进行搜索。这进一步提高了对用户输入错误的容忍度。

// src/store.ts (逻辑示意)
searchWithFallback(query, limit) {
  let results = this.search(query, limit); // 第一级
  if (results.length === 0) {
    results = this.searchTrigram(query, limit); // 第二级
  }
  if (results.length === 0) {
    const correctedQuery = this.fuzzyCorrect(query);
    if (correctedQuery !== query) {
      results = this.search(correctedQuery, limit); // 用纠正后的词重试第一级
    }
  }
  return results;
}

这个分层设计使得无论是精确的 API 文档查询,还是模糊的错误信息搜索,都能得到合理的结果,从而在长时间会话中可靠地恢复上下文。

安全与策略层:执行前的最后防线

在代码到达执行引擎或文件被索引之前,security.ts 中的策略引擎会进行拦截。它通过读取项目中的 .claude/settings.json 等配置文件来执行命令拒绝策略文件路径评估

  • 命令拒绝:对于 ctx_execute 中的 Shell 命令,evaluateCommandDenyOnly 函数会将其拆分成链式命令(如 &&||;| 连接的命令),然后逐一检查是否匹配拒绝列表中的模式。
  • 路径评估:对于 ctx_indexRead 操作,evaluateFilePath 会检查文件路径是否匹配拒绝 glob。它会将相对路径、绝对路径甚至符号链接解析后的规范路径都与规则进行比对,防止通过 ../ 遍历或符号链接绕过安全限制。
// src/security.ts
export function evaluateFilePath(filePath, denyGlobs, caseInsensitive, projectRoot) {
  // 1. 检查原始输入路径
  // 2. 如果提供 projectRoot,检查解析后的绝对路径
  // 3. 尝试 realpathSync 检查符号链接解析后的真实路径
  // 任一匹配拒绝 glob 则返回 denied: true
}

这确保了即使 AI 试图执行危险操作或访问敏感文件,也会被系统策略阻止。关于安全机制的更多细节,可以参考Context Mode 的安全防线

FAQ

Q: Context Mode 声称能节省 98% 的上下文,这个数字是如何验证的? A: 这个数据基于对典型 AI 编码会话的监控统计。MCP 服务器中的 sessionStats 对象会记录通过 ctx_fetch_and_index 索引而未送入上下文的字节数(bytesIndexed)、在沙盒中执行而未输出的字节数(bytesSandboxed)以及因缓存命中而节省的字节数。将这些“被拦截”的字节数与实际送入上下文窗口的工具返回字节数(bytesReturned)进行比较,可以计算出节省比例。ctx_stats 工具可以查看当前会话的实时统计数据。

Q: 如果沙盒执行失败或超时,AI 会收到什么信息? A: 执行引擎会捕获所有错误,并返回结构化的结果。对于超时,结果中的 timedOut 字段会设为 true。如果输出量被 hardCapBytes 硬上限截断,stderr 中会附加明确的提示信息,如 [output capped at 100MB — process killed]。退出码 exitCode 也会反映失败状态。AI 会收到这些清晰的错误信息,从而可以调整其策略或代码,而不是收到无意义的原始数据流。