Doramagic 项目包 · 项目说明书

contextful 项目

生成时间:2026-05-16 04:01:04 UTC

项目概述

Contextful(也称 cxf 或 contextful)是一个本地代码索引与上下文检索系统,专为 AI 编程助手设计。该项目由 Inferensys 团队开发,旨在解决大型代码库中上下文信息过载的问题,帮助 AI Agent 在代码审查、重构、依赖分析等场景中高效获取精确的证据支撑[资料来源:README.md:1]()

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 核心设计理念

继续阅读本节完整说明和来源证据。

章节 整体架构图

继续阅读本节完整说明和来源证据。

章节 核心模块

继续阅读本节完整说明和来源证据。

项目简介

Contextful(也称 cxfcontextful)是一个本地代码索引与上下文检索系统,专为 AI 编程助手设计。该项目由 Inferensys 团队开发,旨在解决大型代码库中上下文信息过载的问题,帮助 AI Agent 在代码审查、重构、依赖分析等场景中高效获取精确的证据支撑资料来源:README.md:1

Contextful 的核心价值在于将传统的"暴力读取文件"模式转变为"证据驱动的紧凑上下文打包"模式。传统方式下,AI Agent 可能需要读取数十个文件才能理解一个问题,而 Contextful 能够根据查询意图返回一个经过排序、标注来源、符合 token 预算的紧凑证据包资料来源:README.md:1-5

核心设计理念

Contextful 遵循以下设计原则:

  1. 证据优先:每个返回的上下文都附带文件引用和行号,AI 可以直接溯源
  2. 意图感知:系统能够分类用户查询(如精确搜索、影响分析、架构追踪等)
  3. 预算可控:返回结果严格遵守 token 预算限制,避免信息过载
  4. 记忆持久化:支持将 AI 学习到的经验持久化存储,供后续会话复用

技术架构

整体架构图

graph TD
    subgraph 输入层
        Q[用户查询]
        W[工作区文件]
        M[记忆数据]
    end
    
    subgraph 处理层
        C[CLI命令解析]
        S[搜索引擎]
        G[图数据库]
        I[索引引擎]
    end
    
    subgraph MCP层
        MCP[MCP Server]
        TOOLS[7大工具集]
    end
    
    subgraph 输出层
        P[Evidence Pack]
        R[Context Report]
    end
    
    Q --> C
    W --> I
    I --> G
    C --> S
    S --> G
    M --> S
    C --> MCP
    MCP --> TOOLS
    TOOLS --> P
    TOOLS --> R
    S --> P
    G --> P

核心模块

模块名称文件路径职责说明
CLI 解析器src/cli.ts命令行参数解析与路由
搜索引擎src/search.ts全文检索、意图分类、结果排序
索引引擎src/extract.ts符号提取、依赖关系图构建
MCP 服务src/mcp-server.tsMCP 协议实现与工具暴露
报告生成src/report.ts上下文报告与证据包渲染

功能特性

CLI 命令行工具

Contextful 提供完整的命令行界面,支持以下操作资料来源:src/cli.ts:1-100

命令功能描述核心参数
cxf index建立或更新工作区索引--workspace, --watch
cxf daemon启动本地索引守护进程--workspace
cxf query创建证据包--workspace, --budget, --json
cxf search搜索上下文--workspace, --limit, --kind
cxf report生成上下文报告--workspace, --format
cxf memory add存储经验教训--claim, --evidence, --scope
cxf server启动 MCP 服务

MCP 工具集

Contextful 作为 MCP(Model Context Protocol)服务器,暴露了 7 个核心工具资料来源:src/mcp-server.ts:1-50

工具名称功能说明
context_pack返回排序、标注来源、符合预算的证据包
search_code强大的代码、文档、符号和记忆搜索
trace_path跨文件、符号、模块、配置的图遍历
impact_analysis逆向依赖分析与影响范围识别
why_changed结合 Git 历史的变更原因分析
recall_memory搜索持久化的经验教训
write_lesson写入带证据的经验教训

搜索意图分类

系统能够将用户查询自动分类为以下意图类型资料来源:src/search.ts:1-30

意图类型触发关键词典型使用场景
exact文件路径、符号名、正则表达式精确查找定义或文件
code函数、变量、参数、实现代码实现分析
memory记忆、经验、教训、会话经验检索
impact影响、依赖、影响范围变更影响分析
historical为什么、变更、历史、提交变更原因追溯
architectural架构、流程、路径、依赖系统架构分析
docs文档、指南、README、配置文档查找
vague通用查询模糊匹配

索引能力

系统支持多种编程语言的代码索引资料来源:src/extract.ts:1-80

语言支持类型提取内容
TypeScript/JavaScript函数、类、接口、类型函数声明、导出状态、签名
Python函数、类函数定义、类定义
Go函数、结构体、接口函数声明、包级导出
Rust函数、结构体、枚举、特征、impl函数、结构体、特征实现
Markdown标题层级标题结构
JSON配置键顶层键名
Goimport 路径包引用
Rustuse/mod 语句模块引用

工作流程

索引构建流程

graph LR
    A[文件扫描] --> B[语言检测]
    B --> C[符号提取]
    C --> D[依赖关系提取]
    D --> E[全文分块]
    E --> F[SQLite存储]
    
    F --> G[FTS全文索引]
    G --> H[图数据库索引]

证据包生成流程

graph TD
    Q[query查询] --> C{意图分类}
    C -->|code| F1[FTS全文搜索]
    C -->|impact| F2[图遍历分析]
    C -->|memory| F3[记忆库搜索]
    C -->|historical| F4[Git历史查询]
    
    F1 --> R[结果合并]
    F2 --> R
    F3 --> R
    F4 --> R
    
    R --> D[相关性评分]
    D --> S[Token预算分配]
    S --> P[Evidence Pack]
    
    P --> CITE[引用标注]
    P --> GRAPH[图路径连接]
    P --> CONF[置信度计算]
    
    CITE --> OUTPUT[最终输出]
    GRAPH --> OUTPUT
    CONF --> OUTPUT

依赖关系

核心依赖

依赖包版本用途
@modelcontextprotocol/sdk^1.29.0MCP 协议实现
better-sqlite3^12.10.0SQLite 数据库引擎
commander^14.0.3CLI 命令解析
fast-glob^3.3.3文件模式匹配
web-tree-sitter^0.20.8语法树解析
zod^4.4.3数据验证

开发依赖

依赖包版本用途
typescript^6.0.3类型检查与编译
vitest^4.1.6单元测试框架

环境要求

支持的 IDE

项目已针对以下 IDE 和编辑器进行测试资料来源:package.json:10-18

  • Windsurf
  • GitHub Copilot
  • VS Code
  • Cline
  • Roo Code
  • Continue
  • Zed

项目元数据

属性
项目名称contextful
CLI 别名cxf
MCP 名称io.github.Inferensys/contextful
许可证MIT
仓库地址git+https://github.com/Inferensys/contextful.git
官网https://inferensys.github.io/contextful/
问题追踪https://github.com/Inferensys/contextful/issues

使用示例

安装与索引

# 全局安装
npx @inferensys/contextful index --workspace .

# 持续监听文件变化
npx @inferensys/contextful index --workspace . --watch

查询上下文

# 基本查询
cxf query "where is user auth handled" --workspace . --budget 2000

# 输出 JSON 格式
cxf query "memory ledger implementation" --workspace . --json

MCP 服务模式

# 启动 MCP 服务器
npx @inferensys/contextful server

数据模型

证据包结构

classDiagram
    class EvidencePack {
        +string id
        +string query
        +string scope
        +SearchIntent intent
        +string summary
        +SearchHit[] citations
        +FileContext[] files
        +SymbolRecord[] symbols
        +GraphPath[] graphPaths
        +SearchHit[] memoryHits
        +number confidence
        +number tokenEstimate
        +number budget
        +string createdAt
    }
    
    class SearchHit {
        +string ref
        +string path
        +string title
        +string kind
        +string excerpt
        +number rank
    }
    
    class GraphPath {
        +string from
        +string to
        +string edgeType
        +string filePath
        +number line
    }
    
    EvidencePack --> SearchHit
    EvidencePack --> GraphPath

记忆条目结构

字段类型说明
idstring唯一标识符
claimstring经验主张
evidenceRefsstring[]证据引用列表
scopestring作用范围(repo/global)
confidencenumber置信度(0-1)
createdAtstring创建时间

报告功能

系统支持生成多格式的上下文报告资料来源:src/report.ts:1-60

格式说明
markdown默认格式,Markdown 渲染
json结构化 JSON 输出
html独立 HTML 页面,可直接在浏览器打开

报告包含内容

  • 索引状态:已索引文件数、符号数、块数
  • 统计摘要:Token 使用情况、节省比例估算
  • 警告信息:潜在问题提示(如未索引文件、依赖缺失)
  • Token 节省估算:相对于未使用系统的平均节省比例

来源:https://github.com/Inferensys/contextful / 项目说明书

系统架构

Contextful 是一个基于语义索引的上下文检索系统,旨在为 AI 代理提供精准、紧凑且有据可查的证据包。系统通过解析、索引代码仓库中的符号、导入关系和文档片段,使代理能够在执行任务时快速获取相关上下文,避免随机文件读取带来的效率低下问题。资料来源:[README.md]()

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 3.1 索引子系统 (Indexer)

继续阅读本节完整说明和来源证据。

章节 3.2 搜索与查询子系统 (Search)

继续阅读本节完整说明和来源证据。

章节 3.3 证据包系统 (Evidence Pack)

继续阅读本节完整说明和来源证据。

1. 概述

Contextful 是一个基于语义索引的上下文检索系统,旨在为 AI 代理提供精准、紧凑且有据可查的证据包。系统通过解析、索引代码仓库中的符号、导入关系和文档片段,使代理能够在执行任务时快速获取相关上下文,避免随机文件读取带来的效率低下问题。资料来源:README.md

2. 整体架构

Contextful 采用分层架构设计,主要包含以下层次:

层次职责核心模块
CLI 层用户交互接口src/cli.ts
MCP 服务层与 AI 代理的标准通信协议src/mcp-server.ts
搜索/查询层语义检索和证据包生成src/search.ts
索引层代码解析和数据库写入src/indexer.ts
提取层符号和依赖关系解析src/extract.ts
工具层通用工具函数src/util.ts
graph TD
    A[CLI 客户端] --> B[MCP Server]
    C[AI 代理] --> B
    B --> D[Search Module]
    D --> E[Index Layer]
    E --> F[SQLite Kernel DB]
    G[File System] --> E
    D --> G

资料来源:src/cli.ts:40-65src/search.ts:1-50

3. 核心组件详解

3.1 索引子系统 (Indexer)

索引子系统负责扫描工作区文件并将其内容转换为可检索的数据库记录。索引过程包括文件发现、语言检测、符号提取和依赖关系分析四个阶段。

graph LR
    A[文件扫描] --> B[语言检测]
    B --> C[符号提取]
    C --> D[依赖分析]
    D --> E[分块存储]

#### 索引流程

阶段功能关键函数
文件发现递归扫描目录,忽略隐藏文件和测试文件scanWorkspace()
语言检测根据扩展名识别 TypeScript/JavaScript、Python、Go、Rust 等语言detectLanguage()
符号提取解析函数、类、接口、类型定义extractSymbols()
依赖分析提取 import/require/use 语句extractEdges()
内容分块将文件内容切分为可管理的片段textChunks()

资料来源:src/extract.ts:1-50src/indexer.ts

#### 支持的编程语言

系统支持多种编程语言的符号提取和依赖分析:

语言符号类型依赖检测
TypeScript/JavaScriptfunction, class, interface, type, constimport fromrequire()
Pythonfunction, classfrom ... importimport
Gofunction, struct, interface字符串字面量导入
Rustfunction, struct, enum, trait, implusemod
Markdownheading无依赖
JSONconfig-key键值对配置

资料来源:src/extract.ts:10-45

搜索子系统是系统的核心大脑,负责理解用户查询意图并返回最相关的上下文片段。

graph TD
    A[用户查询] --> B{意图分类}
    B -->|code| C[代码搜索]
    B -->|symbol| D[符号搜索]
    B -->|impact| E[影响分析]
    B -->|historical| F[历史追溯]
    B -->|architectural| G[架构路径]
    B -->|docs| H[文档检索]
    C --> I[全文索引查询]
    D --> J[符号表查询]
    E --> K[依赖图遍历]
    F --> L[Git 历史读取]
    I --> M[BM25 排序]
    J --> M
    K --> M
    M --> N[证据包组装]

#### 意图分类器

查询意图自动分类为以下类型:

意图检测关键词搜索模式
codehow, implement, code, function全文搜索
symbolclass, interface, function name精确符号匹配
impactimpact, affected, depends, blast radius逆向依赖分析
historicalwhy, changed, commit, historyGit 历史 + 当前代码
architecturalarchitecture, flow, path, trace图遍历
docsresource, docs, documentation, guide文档优先
vague通用模糊查询扩展术语 + 全文搜索

资料来源:src/search.ts:1-20

3.3 证据包系统 (Evidence Pack)

证据包是系统返回给 AI 代理的核心数据结构,包含查询答案的所有支持证据。

graph TD
    A[createContextPack] --> B[searchContext]
    B --> C{选择命中}
    C -->|hits| D[topKByScore]
    C -->|graphPaths| E[loadGraphPaths]
    C -->|memoryHits| F[内存记忆]
    D --> G[组装证据包]
    E --> G
    F --> G
    G --> H[EvidencePack]
    H --> I[summary 摘要]
    H --> J[citations 引用]
    H --> K[symbols 符号]
    H --> L[graphPaths 路径]

#### 证据包数据结构

interface EvidencePack {
  id: string;                    // 唯一标识符
  query: string;                 // 原始查询
  scope: string;                 // 作用域 (repo|file|session)
  intent: SearchIntent;          // 识别的查询意图
  summary: string;               // 自然语言摘要
  citations: SearchHit[];         // 命中的上下文片段
  files: FileReference[];         // 相关文件列表
  symbols: SymbolRecord[];         // 匹配的符号
  graphPaths: GraphPath[];        // 图路径连接
  memoryHits: SearchHit[];        // 记忆系统命中
  confidence: number;            // 置信度 (0.1-0.92)
  tokenEstimate: number;         // 估算的 token 数量
  budget: number;                // token 预算上限
  createdAt: string;             // 创建时间戳
}

资料来源:src/search.ts:150-200src/types.ts

3.4 MCP 服务层

MCP (Model Context Protocol) 服务层提供了与 AI 代理通信的标准接口,使 Contextful 可作为工具被集成到任何兼容 MCP 的代理中。

graph LR
    A[AI Agent] -->|stdio| B[MCP Server]
    B -->|context_pack| C[createContextPack]
    B -->|search_code| D[searchContext]
    B -->|trace_path| E[traceGraph]
    B -->|impact_analysis| F[impactAnalysis]
    B -->|why_changed| G[whyChanged]
    B -->|recall_memory| H[recallMemory]
    B -->|write_lesson| I[writeLesson]

#### MCP 工具列表

工具名功能参数
context_pack生成带证据的上下文包query, budget, scope
search_code搜索代码、文档、符号、记忆query, mode, filters
trace_path图遍历追踪符号/模块依赖from, to, edge_types
impact_analysis分析符号/文件的逆向依赖symbol_or_file
why_changed追溯变更历史symbol_or_file
recall_memory搜索记忆系统query, scope
write_lesson写入学习记忆claim, evidence_refs

资料来源:src/mcp-server.tsREADME.md

3.5 CLI 命令行接口

CLI 模块提供了独立的命令行工具 cxf (contextful) 供开发者直接使用。

#### 命令概览

命令描述核心选项
index索引工作区文件--workspace, --watch
daemon启动本地索引守护进程--workspace
query创建证据包--workspace, --budget, --json
search搜索索引内容--workspace, --limit, --kind
report生成上下文报告--workspace, --format
memory add添加学习记忆--claim, --evidence, --confidence
server启动 MCP 服务

资料来源:src/cli.ts:1-80

#### 使用示例

# 索引当前目录
cxf index --workspace .

# 启动守护进程监听变更
cxf daemon --workspace .

# 查询上下文
cxf query "用户认证在哪里处理" --workspace . --budget 2000

# 生成报告
cxf report --workspace . --format markdown

4. 数据模型

4.1 内核数据库 (SQLite)

系统使用 SQLite 作为内核数据库,存储以下核心表结构:

表名用途核心字段
files已索引文件元数据path, language, hash, indexed_at
chunks文件分块内容file_id, path, title, text, kind
chunks_fts全文搜索索引BM25 排序的 FTS5 表
symbols代码符号表name, kind, file_path, line, signature
edges依赖关系图source_path, target_name, edge_type
memory学习记忆存储id, claim, evidence, confidence, scope
queries查询历史query, intent, timestamp

资料来源:src/indexer.tssrc/search.ts:50-100

4.2 符号提取数据模型

interface SymbolRecord {
  ref: string;          // 文件引用,如 "file:src/auth.ts:1-20"
  name: string;         // 符号名称
  kind: string;         // 类型:function, class, interface, struct, enum
  filePath: string;     // 文件路径
  line: number;         // 定义行号
  signature?: string;   // 函数签名摘要
  exported?: boolean;   // 是否导出
}

interface RawEdge {
  targetName: string;   // 目标名称
  targetType: string;   // 目标类型:module, config
  edgeType: string;     // 边类型:IMPORTS, CONFIGURES
  filePath: string;     // 源文件路径
  line: number;         // 行号
}

资料来源:src/extract.ts:1-30

5. 工作流程

5.1 索引完整流程

sequenceDiagram
    participant User
    participant CLI as CLI/Server
    participant Indexer
    participant Extractor
    participant DB as Kernel DB
    
    User->>CLI: cxf index --workspace .
    CLI->>Indexer: scanWorkspace(workspace)
    Indexer->>Indexer: 遍历所有文件
    loop 每个文件
        Indexer->>Extractor: extractSymbols(content, language)
        Extractor-->>Indexer: symbols[]
        Indexer->>Extractor: extractEdges(content, language)
        Extractor-->>Indexer: edges[]
        Indexer->>Extractor: textChunks(content)
        Extractor-->>Indexer: chunks[]
        Indexer->>DB: insert records
    end
    DB-->>CLI: indexing complete
    CLI-->>User: status report

5.2 查询证据包生成流程

sequenceDiagram
    participant Agent
    participant MCP as MCP Server
    participant Search
    participant DB as Kernel DB
    
    Agent->>MCP: context_pack("用户认证", budget=2000)
    MCP->>Search: createContextPack({query, budget})
    Search->>Search: classifyQuery(query) -> intent
    Search->>Search: searchContext({query, intent})
    Search->>DB: FTS query + BM25
    DB-->>Search: ranked hits
    Search->>Search: selectTopK(hits, budget)
    Search->>DB: loadSymbolsForPaths()
    Search->>DB: loadGraphPaths()
    Search-->>MCP: EvidencePack
    MCP-->>Agent: EvidencePack (JSON/Markdown)

6. 记忆系统

Contextful 内置了一个证据支持的学习记忆系统,允许 AI 代理保存从查询中获得的经验教训。

6.1 记忆数据结构

字段类型说明
idstring唯一标识符
claimstring经验断言/教训
evidenceSearchHit[]支持证据引用
confidencenumber置信度 (0-1)
scopestring作用域 (repo/file/session)
createdAtstring创建时间

6.2 记忆查询

记忆系统支持通过自然语言查询检索相关经验,与常规代码搜索并行执行,结果合并到证据包中。

资料来源:src/search.ts:200-250

7. 报告系统

报告模块提供工作区的整体上下文分析视图。

graph TD
    A[generateReport] --> B[getIndexStatus]
    A --> C[getQueryStats]
    A --> D[getStaleMemories]
    B --> E[renderReport]
    C --> E
    D --> E
    E -->|markdown| F[Markdown 格式]
    E -->|json| G[JSON 格式]
    E -->|html| H[HTML 格式]

7.1 报告内容

部分内容
状态概览文件数、符号数、索引状态
语言覆盖各编程语言的文件数量统计
热门查询最常使用的查询及意图分布
陈旧记忆需要更新的学习记忆
代理指导最佳实践建议
警告索引过程中的潜在问题

资料来源:src/report.ts:1-100

8. 扩展机制

8.1 自定义文件类型支持

系统通过 extract.ts 中的语言检测器支持扩展新的编程语言。需要实现:

  1. 符号提取:匹配函数/类/类型定义的正则表达式
  2. 依赖分析:匹配导入语句的模式
  3. 分块策略:适用于该语言内容的分块算法

8.2 MCP 工具扩展

MCP 服务层支持注册新的工具函数,遵循以下签名:

interface MCPTool {
  name: string;
  description: string;
  inputSchema: object;
  handler: (params: object) => Promise<object>;
}

9. 总结

Contextful 的系统架构围绕"精准上下文检索"这一核心目标设计,通过分层解耦实现了以下能力:

  • 多语言支持:支持 TypeScript/JavaScript、Python、Go、Rust 等主流语言的符号提取
  • 智能意图分类:自动识别查询意图并选择最优搜索策略
  • 图遍历能力:通过依赖图支持影响分析和架构追踪
  • 记忆持久化:证据支持的学习记忆系统
  • MCP 集成:标准化的 AI 代理通信协议

整个系统以 SQLite 为核心存储,通过 FTS5 全文索引和 BM25 排序算法实现高效检索,最终输出紧凑且有据可查的证据包。

资料来源:[src/cli.ts:40-65](),[src/search.ts:1-50]()

搜索系统

搜索系统是 Contextful 的核心功能模块,负责在已索引的工作区中执行多维度上下文检索。该系统通过整合全文搜索(FTS)、符号搜索、图关系遍历和记忆搜索等多种检索策略,为 AI 代理提供精确、相关且有据可查的代码上下文。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 搜索上下文管理器

继续阅读本节完整说明和来源证据。

章节 意图分类器

继续阅读本节完整说明和来源证据。

章节 全文搜索(FTS)

继续阅读本节完整说明和来源证据。

概述

搜索系统是 Contextful 的核心功能模块,负责在已索引的工作区中执行多维度上下文检索。该系统通过整合全文搜索(FTS)、符号搜索、图关系遍历和记忆搜索等多种检索策略,为 AI 代理提供精确、相关且有据可查的代码上下文。

搜索系统的主要设计目标是解决传统 RAG(检索增强生成)方法中常见的"随机文件读取"问题,通过意图分类、相关性排序和证据打包等机制,返回紧凑且经过验证的证据集,而非大量无关文件。资料来源:README.md

架构概览

graph TD
    A[用户查询] --> B[意图分类 classifyQuery]
    B --> C{查询类型}
    C -->|exact| D[精确搜索]
    C -->|symbol| E[符号搜索]
    C -->|memory| F[记忆搜索]
    C -->|impact| G[影响分析]
    C -->|historical| H[历史分析]
    C -->|architectural| I[架构分析]
    C -->|docs| J[文档搜索]
    C -->|vague| K[模糊搜索]
    
    D --> L[全文搜索引擎]
    E --> L
    F --> M[记忆数据库]
    G --> N[依赖图遍历]
    H --> O[Git历史]
    I --> N
    J --> L
    
    L --> P[结果合并去重]
    M --> P
    N --> P
    O --> P
    P --> Q[证据打包 createContextPack]
    Q --> R[EvidencePack]

核心组件

搜索上下文管理器

searchContext 是搜索系统的入口函数,负责协调整个搜索流程:

export async function searchContext(options: SearchOptions): Promise<{ intent: SearchIntent; hits: SearchHit[] }>

主要职责:

  1. 解析并验证工作区路径
  2. 确保索引已完成(调用 ensureIndexed
  3. 对查询进行意图分类
  4. 执行对应的搜索策略
  5. 合并和去重搜索结果

资料来源:src/search.ts:核心函数

意图分类器

意图分类器 classifyQuery 是搜索系统的智能路由层,根据查询内容将其映射到最适合的搜索策略。

function classifyQuery(q: string): SearchIntent

支持的意图类型:

意图类型触发关键词搜索策略
exact符号名(驼峰命名)、路径分隔符、井号精确匹配文件路径或符号
symbolfunction、method、class、interface、变量名符号定义检索
memorymemory、lesson、remember、learned、session记忆库检索
impactimpact、affected、depends、blast radius、uses影响分析和依赖追踪
historicalwhy、changed、commit、history、regressionGit 历史分析
architecturalarchitecture、flow、trace、connects、imports架构图遍历
docsdocs、documentation、guide、readme、how to文档检索
vague其他情况模糊全文搜索

资料来源:src/search.ts:意图分类逻辑

意图分类的实现细节:

function classifyQuery(q: string): SearchIntent {
  const lower = q.toLowerCase();
  if (/[`"'#.:/]/.test(q) || /\b[A-Z][A-Za-z0-9_]{2,}\b/.test(query)) return "exact";
  if (/\b(function|method|class|interface|enum|struct|impl)\b/.test(q)) return "symbol";
  if (/\b(memory|memories|remember|remembers|lesson|lessons|learned|session|sessions)\b/.test(q)) return "memory";
  if (/\b(impact|affected|depends on|dependents|blast radius|what uses|who calls)\b/.test(q)) return "impact";
  // ... 更多分类规则
}

搜索策略

全文搜索(FTS)

全文搜索引擎基于 SQLite 的 FTS5 扩展实现,支持 BM25 排序算法:

const rows = kernel.db
  .prepare("SELECT ref, path, title, text, bm25(chunks_fts) AS rank FROM chunks_fts WHERE chunks_fts MATCH ? LIMIT ?")
  .all(fts, limit * 10)

查询构建器 ftsQuery

负责将用户查询转换为 FTS5 兼容的查询语法:

  1. 移除停用词(stopwords)
  2. 展开相关术语(同义词扩展)
  3. 处理特殊字符和符号

停用词列表:

const STOPWORDS = new Set(["where", "what", "which", "when", "how", "are", "the", "for", "with", "and", "or", "to"]);

术语扩展 expandedTerms

根据查询语义自动添加相关术语:

语义主题扩展术语
tool/tools 相关server, tool, tools, callTool
MCP 相关mcp, server, stdio
memory 相关memory, memories, lesson, lessons, claim, ledger, evidence
impact 相关imports, tests, edges

资料来源:src/search.ts:FTS实现

符号搜索

符号搜索专门用于定位代码中的定义和声明,支持多种编程语言:

支持的符号类型:

语言符号类型
TypeScript/JavaScriptfunction, class, interface, type, const
Pythonfunction, class
Gofunction (大写导出), struct, interface
Rustfunction, struct, enum, trait, impl
Markdownheading

符号提取器 extractSymbols

function extractSymbols(relativePath: string, content: string, language: string): SymbolRecord[]

示例 - TypeScript 函数提取:

matchPush(line, /^\s*(export\s+)?(?:async\s+)?function\s+([A-Za-z_$][\w$]*)/, push, "function");

资料来源:src/extract.ts:符号提取

图关系搜索

图搜索基于提取的导入和依赖关系构建有向图,支持:

  • 依赖追踪:查找某个模块的导入关系
  • 影响分析:反向查找依赖当前目标的所有模块
  • 路径追踪:在两个符号/文件之间寻找连接路径

图数据结构:

interface RawEdge {
  targetName: string;
  targetType: "module" | "symbol" | "config";
  edgeType: "IMPORTS" | "TESTS" | "CONFIGURES";
  line: number;
}

导入关系提取:

语言导入语法
TypeScript/JavaScriptfrom "..." / require("...")
Pythonfrom ... import ... / import ...
Go"..."
Rustuse ...; / mod ...;
JSON"key": value

资料来源:src/extract.ts:边提取

记忆搜索

记忆系统允许 AI 代理存储和检索基于证据的经验教训:

memory
  .command("add")
  .requiredOption("--claim <text>", "Lesson claim.")
  .requiredOption("--evidence <ref...>", "Evidence ref(s)")
  .option("--scope <scope>", "Memory scope.", "repo")
  .option("--confidence <number>", "Confidence from 0 to 1.", parseFloat, 0.7)

记忆搜索触发条件:

当查询包含以下关键词时,系统自动启用记忆搜索:

  • memory, memories
  • remember, remembers
  • lesson, lessons
  • learned
  • session, sessions
  • ledger, evidence

资料来源:src/search.ts:记忆搜索触发

证据打包系统

createContextPack 函数将搜索结果整合为结构化的证据包:

export async function createContextPack(options: CreatePackOptions): Promise<EvidencePack>

证据包结构

interface EvidencePack {
  id: string;              // 唯一标识符
  query: string;           // 原始查询
  scope: string;           // 搜索范围
  intent: SearchIntent;    // 识别的意图类型
  summary: string;         // 结果摘要
  citations: SearchHit[];  // 引用列表
  files: FileContext[];    // 文件级上下文
  symbols: SymbolRecord[]; // 相关符号
  graphPaths: GraphPath[];// 图路径连接
  memoryHits: SearchHit[]; // 记忆命中
  confidence: number;      // 置信度 0.1-0.92
  tokenEstimate: number;   // 估算 token 数
  budget: number;          // 预算上限
  createdAt: string;      // 创建时间 (ISO)
}

置信度计算

function confidenceFor(hits: SearchHit[], graphPaths: GraphPath[], memoryHits: SearchHit[]): number {
  return clamp(0.25 + hits.length * 0.05 + graphPaths.length * 0.02 + memoryHits.length * 0.05, 0.1, 0.92);
}

置信度计算公式:

贡献来源权重
基础分0.25
每条命中+0.05
每条图路径+0.02
每条记忆命中+0.05
最小值0.1
最大值0.92

资料来源:src/search.ts:置信度计算

CLI 集成

搜索系统通过命令行提供完整的交互接口:

可用命令

# 搜索上下文
cxf search "<query>" --workspace <path> --limit 10 --kind all|code|docs|symbols|memory

# 创建证据包
cxf query "<query>" --workspace <path> --budget 2000 --json

# 追踪图路径
cxf trace --from <symbol> --to <target> --edge-types imports|tests

# 影响分析
cxf impact <symbol_or_file>

# 历史分析
cxf why --target <symbol_or_file>

查询选项

选项类型默认值说明
--workspacepathprocess.cwd()工作区路径
--limitnumber10最大命中数
--kindenumall搜索类型
--budgetnumber2000token 预算
--jsonbooleanfalseJSON 输出格式

资料来源:src/cli.ts:CLI命令定义

MCP 工具集成

Contextful 作为 MCP(Model Context Protocol)服务器运行,提供标准化的工具接口:

核心工具

工具名功能参数
context_pack创建证据包query, budget, scope
search_code多模式搜索query, mode, filters
trace_path图路径追踪from, to, edge_types
impact_analysis影响分析symbol_or_file
why_changed变更历史symbol_or_file
recall_memory记忆检索query, scope
write_lesson写入记忆claim, evidence_refs

MCP 服务器启动

npx @inferensys/contextful server

资料来源:README.md:MCP工具

搜索流程图

sequenceDiagram
    participant User as 用户
    participant CLI as CLI/MCP
    participant Search as 搜索系统
    participant FTS as FTS引擎
    participant Graph as 图数据库
    participant Memory as 记忆库
    participant Pack as 证据打包

    User->>CLI: query "where is auth handled"
    CLI->>Search: searchContext({query})
    Search->>Search: classifyQuery()
    Note over Search: intent = "architectural"
    
    Search->>FTS: executeQuery()
    Search->>Graph: loadGraphPaths()
    Search->>Memory: memoryHits()
    
    FTS-->>Search: hits[]
    Graph-->>Search: graphPaths[]
    Memory-->>Search: memoryHits[]
    
    Search->>Pack: createContextPack()
    Pack->>Pack: calculateConfidence()
    Pack->>Pack: estimateTokens()
    Pack-->>CLI: EvidencePack
    
    CLI-->>User: 格式化输出

数据模型

SearchHit

interface SearchHit {
  ref: string;       // 引用标识 (file:path:start-end)
  path: string;       // 文件路径
  title: string;      // 标题
  text: string;       // 匹配文本
  kind: "code" | "doc" | "symbol" | "memory";
  score: number;      // 相关性得分
  rank: number;       // BM25 排名
  line?: number;      // 行号
}

SymbolRecord

interface SymbolRecord {
  ref: string;
  name: string;
  kind: string;       // function, class, etc.
  filePath: string;
  line: number;
  signature: string;  // 函数签名/类型签名
  exported?: boolean;
}

GraphPath

interface GraphPath {
  from: string;
  to: string;
  edgeType: string;
  filePath: string;
  line: number;
}

资料来源:src/search.ts:数据结构定义

高级功能

影响分析

impactAnalysis 函数执行反向依赖分析:

export async function impactAnalysis(options: {
  workspace?: string;
  target: string;
  limit?: number;
}): Promise<{
  target: string;
  dependencies: GraphPath[];
  dependents: GraphPath[];
  likelyTests: GraphPath[];
}>

返回数据说明:

字段说明
dependencies目标直接依赖的模块
dependents依赖该目标的模块
likelyTests相关的测试文件

变更历史分析

whyChanged 函数结合搜索结果和 Git 历史:

export async function whyChanged(options: {
  workspace?: string;
  target: string;
  limit?: number
}): Promise<{
  target: string;
  currentEvidence: SearchHit[];
  commits: Array<{
    hash: string;
    subject: string;
    date?: string;
    files: string[];
  }>;
}>

资料来源:src/search.ts:高级搜索功能

索引状态查询

export async function getIndexStatus(options: { workspace?: string }): Promise<IndexStatus>

返回的索引状态信息:

字段类型说明
workspacestring工作区路径
statusstring索引状态
fileCountnumber文件总数
languageCountsRecord<string, number>各语言文件统计
warningsstring[]索引警告列表

搜索结果后处理

去重机制

function dedupeHits(hits: SearchHit[]): SearchHit[] {
  const seen = new Set<string>();
  return hits.filter((hit) => {
    if (seen.has(hit.ref)) return false;
    seen.add(hit.ref);
    return true;
  });
}

得分计算

搜索结果通过多层评分机制排序:

  1. BM25 基础分:FTS5 内置的 BM25 算法
  2. 意图匹配奖励:根据意图类型调整权重
  3. 语义扩展奖励:术语扩展匹配额外加分
function scoreFromRank(rank: number, intent: SearchIntent, query: string): number {
  const lower = query.toLowerCase();
  let bonus = 0;
  
  // 意图特定奖励
  if (intent === "symbol" && lower.includes("function")) bonus += 10;
  if (intent === "memory" && lower.includes("memory ledger")) bonus += 7;
  
  return 10 / (1 + Math.abs(rank)) + bonus;
}

资料来源:src/search.ts:得分计算

总结

搜索系统是 Contextful 实现智能上下文检索的核心引擎,通过以下机制为 AI 代理提供精确的代码上下文:

  1. 意图驱动的路由:自动识别查询意图并选择最优搜索策略
  2. 多模态检索:整合全文搜索、符号搜索、图搜索和记忆搜索
  3. 证据打包:将零散的搜索结果整合为结构化的证据包
  4. 智能排序:基于 BM25 和语义理解的结果排序
  5. 置信度评估:量化的结果可信度指标

该系统特别适用于大型代码库的场景,能够帮助 AI 代理快速定位相关代码片段,避免盲目探索,同时保留完整的引用溯源能力。

资料来源:[src/search.ts:核心函数](https://github.com/Inferensys/contextful/blob/main/src/search.ts)

上下文包系统

上下文包(Context Pack)是 Contextful 的核心功能模块,它将索引后的代码上下文、符号信息、图关系和记忆数据打包成紧凑的、带引用的、符合 token 预算的证据束,供 AI Agent 在执行任务时使用。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 设计目标

继续阅读本节完整说明和来源证据。

章节 核心数据类型

继续阅读本节完整说明和来源证据。

章节 上下文包创建流程

继续阅读本节完整说明和来源证据。

系统概述

设计目标

上下文包系统旨在解决 AI Agent 在大型代码库中检索上下文时的核心痛点:

问题上下文包解决方案
随机文件读取导致 token 浪费基于查询意图的精确检索
缺乏可信引用每个证据块都附带文件路径和行号
无法追踪代码关系集成图路径遍历结果
遗忘跨会话经验整合证据-backed 记忆数据

核心数据类型

上下文包的数据结构定义在 src/types.ts 中,主要包含以下组件:

interface EvidencePack {
  id: string;                    // 唯一标识符,格式: ctx_<hash>
  query: string;                 // 原始查询文本
  scope: string;                 // 作用域(如 "repo")
  intent: SearchIntent;           // 查询意图分类
  summary: string;               // 包内容的自然语言摘要
  citations: SearchHit[];        // 命中的证据列表
  files: FileContext[];          // 按文件分组的引用
  symbols: SymbolRecord[];       // 相关符号记录
  graphPaths: GraphPath[];       // 图关系路径
  memoryHits: SearchHit[];       // 记忆命中结果
  confidence: number;            // 置信度(0.1-0.92)
  tokenEstimate: number;         // 实际 token 估算值
  budget: number;                // 分配的 token 预算
  createdAt: string;             // 创建时间(ISO 格式)
}

资料来源:src/search.ts:180-195

工作流程

上下文包创建流程

graph TD
    A[接收查询请求] --> B[分类查询意图]
    B --> C{意图类型}
    C -->|code| D[执行代码搜索]
    C -->|docs| E[执行文档搜索]
    C -->|symbol| F[执行符号搜索]
    C -->|memory| G[搜索记忆数据]
    C -->|impact| H[执行影响分析]
    D --> I[检索图路径]
    E --> I
    F --> I
    G --> I
    H --> I
    I --> J[根据 token 预算排序选择证据]
    J --> K[生成置信度评分]
    K --> L[构建上下文包]
    L --> M[保存到数据库]
    M --> N[返回 EvidencePack]

证据选择与排序

上下文包使用分层策略选择证据:

  1. 意图匹配:根据查询意图优先返回相关类型的命中结果
  2. 相关性评分:使用 BM25 算法结合自定义调整因子
  3. Token 预算约束:按优先级遍历,直到达到预算上限
// token 预算选择逻辑
let tokenEstimate = 0;
const selected: SearchHit[] = [];

for (const hit of scored) {
  if (selected.some(s => s.ref === hit.ref)) continue;
  if (tokenEstimate + hit.tokenEstimate >= budget) break;
  selected.push(hit);
  tokenEstimate += hit.tokenEstimate;
}

资料来源:src/search.ts:160-175

意图分类系统

意图类型定义

意图类型触发关键词说明
symbol函数名、类名、常量符号定义和引用查找
code实现、逻辑、算法代码片段搜索
docs文档、README、如何文档内容检索
memory记忆、经验、教训证据-backed 记忆查询
impact影响、依赖、影响范围影响分析
historical为什么、变更、历史Git 历史追溯
architectural架构、流程、调用链架构分析
exact文件路径、行号、符号精确匹配
vague无明确意图模糊查询

意图分类实现

function classifyQuery(q: string): SearchIntent {
  if (/\b(function|class|method|const|interface|type|struct)\s+[A-Z]/.test(q)) return "symbol";
  if (/\b(where|find|search|locate|get|retrieve)\b/.test(q)) return "code";
  if (/\b(memory|remember|learned|lessons?|sessions?)\b/.test(q)) return "memory";
  if (/\b(impact|affected|depends on|dependents|blast radius|what uses|who calls)\b/.test(q)) return "impact";
  if (/\b(why|changed|commit|history|regression|introduced)\b/.test(q)) return "historical";
  if (/\b(architecture|flow|path|trace|connects|calls|imports|dependency)\b/.test(q)) return "architectural";
  if (/\b(resource|docs|documentation|guide|readme|how to|setup)\b/.test(q)) return "docs";
  if (/[`"'#.:/]/.test(q) || /\b[A-Z][A-Za-z0-9_]{2,}\b/.test(query)) return "exact";
  return "vague";
}

资料来源:src/search.ts:1-14

置信度评估

置信度计算公式

上下文包的置信度通过以下公式计算:

confidence = clamp(0.25 + hits.length × 0.05 + graphPaths.length × 0.02 + memoryHits.length × 0.05, 0.1, 0.92)
组成部分权重说明
基础分0.25最低置信度保证
命中数+0.05/个每个搜索命中增加置信度
图路径数+0.02/个每条图关系路径增加置信度
记忆命中数+0.05/个每个记忆命中增加置信度

置信度边界

置信度始终被限制在 [0.1, 0.92] 范围内,确保:

  • 最低 10% 置信度(无任何证据时)
  • 最高 92% 置信度(避免过度自信)
function confidenceFor(hits: SearchHit[], graphPaths: GraphPath[], memoryHits: SearchHit[]): number {
  return clamp(0.25 + hits.length * 0.05 + graphPaths.length * 0.02 + memoryHits.length * 0.05, 0.1, 0.92);
}

资料来源:src/search.ts:89-91

图关系集成

图路径类型

上下文包包含代码库中实体之间的图关系:

interface GraphPath {
  from: string;        // 源实体名称
  to: string;          // 目标实体名称
  edgeType: string;    // 边类型(IMPORTS、DEFINES、CONFIGURES 等)
  filePath: string;    // 关系所在文件
  line: number;        // 关系所在行号
}

边类型定义

边类型说明提取来源
IMPORTS模块导入关系TypeScript/Python/Go import 语句
DEFINES符号定义关系函数、类、接口声明
CONFIGURES配置关系package.json 依赖、配置文件键
TESTS测试关系测试文件与被测文件关联

图路径加载

function loadGraphPaths(db: Database, paths: string[], limit: number): GraphPath[] {
  const rows = db.prepare(`
    SELECT from_name, target_name, edge_type, file_path, line
    FROM edges
    WHERE file_path IN (${paths.map(() => "?").join(",")})
    LIMIT ?
  `).all(...paths, limit) as EdgeRow[];
  
  return rows.map(row => ({
    from: row.from_name,
    to: row.target_name,
    edgeType: row.edge_type,
    filePath: row.file_path,
    line: row.line
  }));
}

资料来源:src/search.ts:125-140

CLI 接口

查询命令

cxf query "<query>" --workspace <path> --budget <tokens> --json
参数类型默认值说明
query字符串必需要回答的查询文本
--workspace路径当前目录工作区路径
--budget整数2000近似的 token 预算
--json标志false输出 JSON 格式而非 Markdown

实现逻辑

program
  .command("query")
  .description("Create an evidence pack for a query.")
  .argument("<query>", "Query to answer from indexed context.")
  .option("--workspace <path>", "Workspace path.", process.cwd())
  .option("--budget <tokens>", "Approximate token budget.", parseInteger, 2000)
  .option("--json", "Print JSON instead of Markdown.")
  .action(async (query: string, options) => {
    const pack = await createContextPack({ 
      workspace: options.workspace, 
      query, 
      budget: options.budget 
    });
    process.stdout.write(
      options.json 
        ? `${JSON.stringify(pack, null, 2)}\n` 
        : renderEvidencePackMarkdown(pack)
    );
  });

资料来源:src/cli.ts:20-36

Markdown 渲染

渲染格式

Evidence Pack 的 Markdown 渲染输出格式:

# Context Pack ctx_xxx

Query: <原始查询>
Intent: <意图类型>
Confidence: <置信度百分比>
Token estimate: <实际token数>/<预算token数>

<摘要文本>

## Citations
- file:src/auth.ts:10-25 (User authentication handler)
  <证据摘要>

## Graph Paths
- auth.ts --IMPORTS--> utils.ts (src/auth.ts:3)

## Memory Hits
- <记忆引用>: <记忆内容>

渲染实现

export function renderEvidencePackMarkdown(pack: EvidencePack): string {
  const lines = [
    `# Context Pack ${pack.id}`,
    "",
    `Query: ${pack.query}`,
    `Intent: ${pack.intent}`,
    `Confidence: ${Math.round(pack.confidence * 100)}%`,
    `Token estimate: ${pack.tokenEstimate}/${pack.budget}`,
    "",
    pack.summary,
    "",
    "## Citations"
  ];
  
  for (const hit of pack.citations) {
    lines.push(`- ${hit.ref} (${hit.title})`);
    lines.push(`  ${hit.excerpt}`);
  }
  // ... 图路径和记忆命中渲染
  return lines.join("\n");
}

资料来源:src/report.ts:90-115

数据持久化

保存上下文包

创建后的上下文包会被保存到内核数据库:

function saveEvidencePack(
  db: Database, 
  pack: { id: string; query: string; tokenEstimate: number; json: string }
): void {
  db.prepare(`
    INSERT INTO evidence_packs (id, query, token_estimate, created_at, json)
    VALUES (?, ?, ?, ?, ?)
  `).run(pack.id, pack.query, pack.tokenEstimate, nowIso(), pack.json);
}

数据库表结构

表名用途
chunks_fts全文搜索索引
symbols符号索引
edges图关系边
memory证据-backed 记忆
evidence_packs已创建的上下文包历史

与 MCP 工具集成

核心 MCP 工具

上下文包系统通过以下 MCP 工具暴露给 AI Agent:

工具名称功能
context_pack创建上下文包(核心功能)
search_code代码、文档、符号、记忆搜索
trace_path图路径追踪
impact_analysis影响分析
why_changed变更历史追溯
recall_memory记忆召回

资料来源:README.md

工具调用示例

{
  "tool": "context_pack",
  "arguments": {
    "query": "用户认证逻辑在哪里",
    "budget": 2000,
    "scope": "repo"
  }
}

扩展词项机制

为提高搜索召回率,系统包含智能词项扩展:

function expandedTerms(query: string): string[] {
  const additions: string[] = [];
  const lower = query.toLowerCase();
  
  if (/\b(tool|tools|registered|register)\b/.test(lower)) 
    additions.push("server", "tool", "tools", "callTool");
  
  if (/\bmcp\b/.test(lower)) 
    additions.push("mcp", "server", "stdio");
  
  if (/\bmemory|memories|remember|remembers|lesson|lessons|learned\b/.test(lower)) 
    additions.push("memory", "memories", "lesson", "lessons", "claim", "ledger", "evidence");
  
  if (/\bimpact|depends|dependents|uses\b/.test(lower)) 
    additions.push("imports", "tests", "edges");
  
  return [...terms, ...additions];
}

资料来源:src/search.ts:50-68

总结

上下文包系统是 Contextful 的核心模块,它通过以下机制为 AI Agent 提供精准、可信的代码上下文:

  1. 智能意图分类 — 自动识别查询类型并选择最佳搜索策略
  2. Token 预算管理 — 确保返回内容在预算范围内
  3. 多源证据整合 — 合并代码片段、符号信息、图关系和记忆数据
  4. 置信度评估 — 提供可量化的结果可信度指标
  5. 持久化存储 — 记录查询历史以供分析和回溯

通过 MCP 工具接口,AI Agent 可以方便地调用 context_pack 获取高质量的代码上下文,显著提升代码理解和任务完成效率。

资料来源:[src/search.ts:180-195]()

内存分类账

内存分类账(Memory Ledger)是 Contextful 项目中的核心模块,用于存储和管理基于证据的经验教训。它允许 AI 代理在执行任务过程中积累可复用的知识,并通过引用具体的代码片段作为证据,确保记忆的可靠性和可追溯性。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 Lesson(经验教训)

继续阅读本节完整说明和来源证据。

章节 证据引用格式

继续阅读本节完整说明和来源证据。

章节 系统组件

继续阅读本节完整说明和来源证据。

设计目标

内存分类账解决了 AI 代码代理在长时间任务执行中面临的两个核心问题:

  1. 知识遗忘 - 代理无法记住跨会话的重要决策和经验
  2. 无据可查 - 记忆缺乏具体的代码引用,导致引用不准确

通过建立证据分类账,代理能够:

  • 持久化存储项目特定的学习成果
  • 通过引用索引快速检索相关记忆
  • 在执行任务前调用已有记忆,避免重复踩坑
  • 为每条记忆维护置信度,支持动态更新

资料来源:src/memory.ts:1-30

核心数据模型

Lesson(经验教训)

内存分类账中的基本存储单元是 Lesson 对象,其结构如下:

字段类型说明
idstring唯一标识符,格式为 les_{shortHash}
claimstring核心主张/结论,描述学到的经验
evidence_refsstring[]证据引用数组,每项格式为 file:{path}:{startLine}-{endLine}
scopestring作用范围,如 "repo"
confidencenumber置信度,范围 0.0-1.0
created_atstringISO 时间戳
supersedesstring[]被替代的记忆 ID 列表

资料来源:src/types.ts

证据引用格式

证据引用采用标准化格式,确保与代码索引系统无缝集成:

file:src/auth.ts:1-20
组成部分说明
file固定前缀,表示文件引用
src/auth.ts相对于工作区的文件路径
1-20代码行号范围

资料来源:src/memory.ts

架构设计

系统组件

graph TD
    subgraph "内存分类账核心"
        A[writeLesson] --> B[Lesson Store]
        C[recallMemory] --> B
        D[readEvidenceRefs] --> E[Chunk Loader]
        E --> F[代码片段内容]
    end
    
    subgraph "持久化层"
        B --> G[SQLite Database]
    end
    
    subgraph "接入层"
        H[CLI memory 命令]
        I[MCP Server Tools]
        J[Query Search]
    end
    
    H --> A
    I --> A
    I --> C
    J -.-> C

工作流程

sequenceDiagram
    participant Agent as AI 代理
    participant MCP as MCP Server
    participant Memory as 内存分类账
    participant DB as SQLite
    
    Agent->>MCP: write_lesson(claim, evidence_refs)
    MCP->>Memory: writeLesson(claim, evidenceRefs)
    Memory->>DB: 存储 Lesson 记录
    Memory-->>Agent: 返回 Lesson ID
    
    Agent->>MCP: recall_memory(query, scope)
    MCP->>Memory: recallMemory(query, scope)
    Memory->>DB: 全文检索匹配
    Memory->>DB: 加载证据引用
    Memory-->>Agent: 返回匹配的 Lesson 列表

MCP 工具接口

内存分类账通过 MCP(Model Context Protocol)提供服务端工具:

write_lesson

写入一条基于证据的经验教训。

参数类型必填说明
claimstring经验主张文本
evidence_refsstring[]证据引用数组
scopestring作用域,默认 "repo"
confidencenumber置信度,默认 0.7
supersedesstring被替代的记忆 ID

资料来源:src/mcp-server.ts:60-78

server.tool(
  "write_lesson",
  "Write an evidence-backed lesson to the memory ledger. Loose remember-this notes are rejected.",
  {
    claim: z.string(),
    evidence_refs: z.array(z.string()),
    scope: z.string().optional(),
    confidence: z.number().optional(),
    supersedes: z.string().optional()
  },
  async (params) =>
    jsonContent(
      await writeLesson({
        workspace: params.workspace,
        claim: params.claim,
        evidenceRefs: params.evidence_refs,
        scope: params.scope,
        confidence: params.confidence,
        supersedes: params.supersedes
      })
    )
);

recall_memory

检索匹配的经验教训。

参数类型必填说明
querystring检索查询字符串
scopestring作用域过滤
limitnumber返回结果上限

资料来源:src/mcp-server.ts:50-59

server.tool(
  "recall_memory",
  "Search the evidence-backed memory ledger for lessons that survived previous agent sessions.",
  {
    query: z.string(),
    scope: z.string().optional(),
    limit: z.number().optional()
  },
  async (params) => jsonContent(await recallMemory(params))
);

CLI 命令

通过命令行界面管理内存分类账:

cxf memory add --claim <text> --evidence <ref...> [--workspace <path>] [--scope <scope>] [--confidence <number>]

命令参数

参数说明
--claim <text>必填 经验主张内容
--evidence <ref...>必填 证据引用,至少一个
--workspace <path>工作区路径,默认为当前目录
--scope <scope>作用域,默认 "repo"
--confidence <number>置信度 0-1,默认 0.7

资料来源:src/cli.ts:70-90

使用示例

# 基础用法
cxf memory add --claim "用户认证在 src/auth.ts 中处理" --evidence "file:src/auth.ts:1-50"

# 指定作用域和置信度
cxf memory add \
  --claim "数据库连接池大小应设为 CPU 核心数的 2 倍" \
  --evidence "file:src/db.ts:10-30" \
  --evidence "file:config/default.json:5-10" \
  --scope "repo" \
  --confidence 0.85

# 替代旧记忆
cxf memory add \
  --claim "新的配置管理方式已迁移到 config/v2" \
  --evidence "file:config/v2/index.ts:1-100" \
  --supersedes "les_abc123"

存储实现

数据库架构

内存分类账使用 SQLite 存储,通过 better-sqlite3 实现同步操作:

erDiagram
    LESSONS {
        string id PK
        string claim
        string evidence_refs
        string scope
        float confidence
        string created_at
        string supersedes
    }
    
    LESSONS_FTS {
        string id PK
        string claim
    }

证据引用处理

证据引用通过专门的解析器处理,将字符串引用转换为具体的代码内容:

// 引用格式解析
const ref = "file:src/auth.ts:1-20";
const parsed = parseFileRef(ref);
// 返回 { path: "src/auth.ts", startLine: 1, endLine: 20 }

资料来源:src/search.ts:80-85

与搜索系统的集成

查询分类增强

内存分类账与搜索系统深度集成,当用户查询命中内存相关关键词时,系统会给予搜索加权:

if (/\bmemory|memories|remember|remembers|lesson|lessons|learned|session|sessions\b/.test(lower)) {
  additions.push("memory", "memories", "lesson", "lessons", "claim", "ledger", "evidence");
}

资料来源:src/search.ts:45-50

记忆匹配优先级

匹配条件优先级调整
命中 "memory ledger" 或 "evidence-backed memory"+7
包含 src/memory.ts 引用+5
包含 readme.md 引用+4
包含搜索模块内部函数-8 至 -16

置信度机制

置信度计算

每条记忆关联一个置信度分数,影响其在搜索结果中的排名:

置信度范围语义含义
0.8 - 1.0高可信,经过充分验证
0.5 - 0.8中可信,基于合理推断
0.2 - 0.5低可信,需要进一步验证
0.0 - 0.2实验性,仅供参考

置信度衰减

长时间未使用的记忆会逐渐降低置信度,系统通过 staleMemories 机制跟踪这类记忆:

// 在报告生成中检测陈旧记忆
lines.push("", "## Stale Memories");
if (report.staleMemories.length === 0) lines.push("- No stale memories.");
for (const memory of report.staleMemories) {
  lines.push(`- ${memory.id}: ${memory.claim}`);
}

资料来源:src/report.ts

使用场景

场景一:跨会话知识传递

graph LR
    A[Session 1: 发现问题] --> B[write_lesson]
    B --> C[存储到 Ledger]
    C --> D[Session 2: 遇到类似问题]
    D --> E[recall_memory]
    E --> F[获取历史经验]

场景二:代码变更影响评估

代理在修改共享模块前,通过内存分类账查找相关历史决策:

# 查询某模块的历史记忆
cxf query "为什么这里使用缓存" --workspace .
# 或通过 MCP
recall_memory(query="缓存策略决策", scope="repo")

场景三:证据驱动的决策

每条记忆必须包含证据引用,避免无依据的主观判断:

有效记忆无效记忆
"配置迁移到 config/v2,因为原有配置结构存在循环依赖问题""配置管理很重要"
证据:file:config/v1/base.ts:20-30无证据引用

最佳实践

撰写有效的经验主张

  1. 明确具体 - 包含具体的文件路径、函数名或配置项
  2. 包含证据 - 每条主张至少引用一个代码片段
  3. 合理置信度 - 根据验证程度设置合适的置信度
  4. 及时更新 - 发现新信息时替代旧记忆

证据引用规范

  • 使用精确的行号范围,避免整文件引用
  • 优先引用关键决策点而非辅助代码
  • 定期验证证据引用仍然有效

作用域策略

作用域适用场景
repo项目级通用经验
module:auth模块特定知识
feature:checkout功能特定决策

相关文档

资料来源:[src/memory.ts:1-30](https://github.com/Inferensys/contextful/blob/main/src/memory.ts)

数据存储与索引

Contextful 的数据存储与索引系统是整个工具的核心基础设施,负责将代码仓库转换为可高效查询的索引数据库。该系统基于 SQLite 构建,使用全文搜索(FTS)技术实现快速准确的语义检索,并为代码图谱、符号索引和证据包提供持久化存储。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 技术选型

继续阅读本节完整说明和来源证据。

章节 数据库结构概览

继续阅读本节完整说明和来源证据。

章节 符号提取(extractSymbols)

继续阅读本节完整说明和来源证据。

概述

Contextful 的数据存储与索引系统是整个工具的核心基础设施,负责将代码仓库转换为可高效查询的索引数据库。该系统基于 SQLite 构建,使用全文搜索(FTS)技术实现快速准确的语义检索,并为代码图谱、符号索引和证据包提供持久化存储。

索引系统的主要职责包括:

  • 解析多种编程语言的代码结构,提取符号(函数、类、接口等)
  • 分析代码依赖关系,构建模块间的导入/导出图谱
  • 将文件内容分块并建立全文索引
  • 管理证据包(Evidence Pack)和记忆(Memory)数据
  • 提供 CLI 命令和 MCP 接口供外部调用

资料来源:README.md:1-10

核心架构

技术选型

技术组件用途资料来源
SQLite + better-sqlite3关系型数据存储package.json
FTS5 全文索引文本搜索src/search.ts
Tree-sitter代码解析与 AST 提取package.json
Fast-glob文件模式匹配package.json

Contextful 选择 SQLite 作为存储引擎,主要考虑其轻量级、无需独立服务器进程的特性,非常适合本地开发环境和 CLI 工具场景。全文章索引使用 SQLite 的 FTS5 扩展实现,支持 BM25 排序算法和复杂的 MATCH 查询语法。

资料来源:package.json:20-35

数据库结构概览

graph TD
    A[文件系统] --> B[文件解析]
    B --> C[符号提取 extractSymbols]
    B --> D[边提取 extractEdges]
    B --> E[内容分块]
    C --> F[symbols 表]
    D --> G[edges 表]
    E --> H[chunks 表]
    H --> I[chunks_fts 全文索引]
    F --> J[MCP 查询接口]
    G --> J
    H --> J

数据提取模块

符号提取(extractSymbols)

extractSymbols 函数负责从源代码中提取各种编程结构,返回包含名称、种类、所在行号和签名的符号记录数组。该函数支持的语言及对应的提取模式如下:

资料来源:src/extract.ts:1-50

#### TypeScript / JavaScript 提取规则

语言元素正则模式符号种类
函数export async functionfunctionfunction
export classclass
接口export interfaceinterface
类型别名export typetype
常量箭头函数export const ... =>function
// 提取逻辑示例
matchPush(line, /^\s*(export\s+)?(?:async\s+)?function\s+([A-Za-z_$][\w$]*)/, push, "function");
matchPush(line, /^\s*(export\s+)?class\s+([A-Za-z_$][\w$]*)/, push, "class");

资料来源:src/extract.ts:10-18

#### Python 提取规则

Python 支持函数和类的提取,使用缩进敏感的解析方式:

const def = line.match(/^\s*(?:async\s+)?def\s+([A-Za-z_][\w]*)/);
if (def) push(def[1], "function");
const cls = line.match(/^\s*class\s+([A-Za-z_][\w]*)/);
if (cls) push(cls[1], "class");

#### Rust 提取规则

Rust 支持函数、结构体、枚举、Trait 和 impl 块的提取:

matchPush(line, /^\s*(pub\s+)?fn\s+([A-Za-z_][\w]*)/, push, "function");
matchPush(line, /^\s*(pub\s+)?struct\s+([A-Za-z_][\w]*)/, push, "struct");
matchPush(line, /^\s*(pub\s+)?enum\s+([A-Za-z_][\w]*)/, push, "enum");

资料来源:src/extract.ts:45-55

#### Markdown 标题提取

Markdown 文件会被提取为标题层级结构:

const heading = line.match(/^(#{1,6})\s+(.+)$/);
if (heading) push(heading[2].trim(), "heading");

边提取(extractEdges)

extractEdges 函数分析代码中的导入语句,构建模块间的依赖图谱。返回的边记录包含源文件名、行号和目标模块信息。

资料来源:src/extract.ts:60-90

#### 各语言导入解析规则

语言导入语法正则匹配
TypeScript/JS (ES Module)import ... from "..."from\s+"'["']
TypeScript/JS (CommonJS)require("...")require\("'["']
Pythonfrom ... importimport ...^\s*from\s+([\w.]+)\s+import
Goimport "...""([^"]+)"
Rustuse ...;mod ...;^\s*use\s+([^;]+);

#### package.json 依赖提取

当处理 package.json 文件时,系统会额外解析依赖配置:

for (const section of ["dependencies", "devDependencies", "peerDependencies", "scripts"]) {
  const values = parsed[section];
  if (!values || typeof values !== "object") continue;
  for (const key of Object.keys(values)) {
    edges.push({ targetName: `${section}:${key}`, targetType: "config", edgeType: "CONFIGURES", line: 1 });
  }
}

资料来源:src/extract.ts:100-115

内容分块策略

分块模式

Contextful 使用多层次的分块策略将文件内容转换为可管理的检索单元:

资料来源:src/extract.ts:140-180

分块类型生成方式适用场景
符号块 (symbol)以符号定义为边界,最多延伸60行精确查找函数/类定义
文件块 (file)80行窗口滑动分块文档和较大代码段
文档块 (doc)以 Markdown 标题分割文档检索

分块记录结构

interface ChunkRecord {
  ref: string;           // 引用标识符,格式: file:path:start-end
  filePath: string;      // 文件路径
  startLine: number;     // 起始行号
  endLine: number;       // 结束行号
  kind: "symbol" | "file" | "doc";  // 分块类型
  title: string;         // 显示标题
  text: string;          // 原始文本内容
  tokenEstimate: number; // token 数量估算
}

Markdown 特殊处理

Markdown 文件的分块逻辑与代码文件不同,会首先提取所有标题层级:

const headings: Array<{ title: string; line: number }> = [];
lines.forEach((line, index) => {
  const match = line.match(/^(#{1,6})\s+(.+)$/);
  if (match) headings.push({ title: match[2].trim(), line: index + 1 });
});

每个标题到下一个标题之间的内容构成一个独立的文档块,便于精确定位文档内容。

全文搜索实现

FTS 查询构建

Contextful 使用增强的 FTS 查询语法提升搜索效果:

资料来源:src/search.ts:20-60

function ftsQuery(query: string): string {
  // 1. 展开查询术语,添加同义词和关联词
  const expanded = expandedTerms(query);
  // 2. 组合为 FTS5 MATCH 表达式
  return expanded.map(t => `"${t}"*`).join(" OR ");
}

搜索意图分类

系统通过正则表达式匹配查询特征,自动识别用户意图:

意图类型检测关键词搜索策略
memorymemory, remember, lesson记忆库检索
impactimpact, affected, depends影响分析
historicalwhy, changed, commit历史追溯
architecturalarchitecture, flow, trace架构追踪
docsdocs, documentation, how to文档检索
exact代码符号、路径引用精确匹配
vague其他模糊查询宽松匹配

资料来源:src/search.ts:1-20

搜索结果排序

搜索结果使用 BM25 算法结合自定义权重进行排序:

function scoreFromRank(rank: number, query: string, path?: string): number {
  const lower = query.toLowerCase();
  const pathLower = path?.toLowerCase() || "";
  let bonus = 0;
  
  // 路径匹配奖励
  if (terms.some(t => pathLower.includes(t))) bonus += 5;
  
  // 特定文件奖励/惩罚
  if (pathLower.includes("memory")) bonus += 5;
  if (pathLower.includes("readme")) bonus += 4;
  
  return 10 / (1 + Math.abs(rank)) + bonus;
}

证据包(Evidence Pack)

创建流程

证据包是 Contextful 查询的最终输出,聚合了搜索结果、图谱路径和记忆数据:

graph TD
    A[用户查询] --> B[searchContext]
    B --> C{意图分类}
    C --> D[FTS 搜索]
    C --> E[记忆检索]
    D --> F[结果去重]
    E --> F
    F --> G[Token 预算分配]
    G --> H[图谱路径扩展]
    H --> I[生成 Evidence Pack]

证据包数据结构

interface EvidencePack {
  id: string;                    // 唯一标识符
  query: string;                 // 原始查询
  scope: string;                // 查询范围
  intent: SearchIntent;         // 识别的意图类型
  summary: string;              // 结果摘要
  citations: SearchHit[];       // 搜索命中结果
  files: Array<{                // 相关文件
    path: string;
    reason: string;
    refs: string[];
  }>;
  symbols: SymbolRecord[];       // 符号信息
  graphPaths: GraphPath[];      // 图谱路径
  memoryHits: SearchHit[];       // 记忆命中
  confidence: number;           // 置信度 (0.1-0.92)
  tokenEstimate: number;        // Token 估算
  budget: number;               // 预算上限
  createdAt: string;            // 创建时间
}

置信度计算

function confidenceFor(hits: SearchHit[], graphPaths: GraphPath[], memoryHits: SearchHit[]): number {
  return clamp(0.25 + hits.length * 0.05 + graphPaths.length * 0.02 + memoryHits.length * 0.05, 0.1, 0.92);
}

置信度基于命中数量、图谱连接数和记忆命中数计算,最低 0.1,最高 0.92。

CLI 命令接口

索引命令

cxf index --workspace <path> [--watch]

索引命令扫描工作区文件,调用符号提取和边提取模块,将结果存储到 SQLite 数据库。

查询命令

cxf query "<query>" --workspace <path> --budget 2000 --json

执行查询并返回格式化的证据包,支持 JSON 输出模式。

搜索命令

cxf search "<query>" --workspace <path> --limit 10 --kind all

支持按类型过滤:all|code|docs|symbols|memory

报告命令

cxf report --workspace <path> --format markdown|json|html

生成工作区的上下文报告,包含文件统计、符号分布和警告信息。

资料来源:src/cli.ts:1-50

工具函数库

文本处理

src/util.ts 提供了索引过程中常用的文本处理函数:

export function lineRange(text: string, startLine: number, endLine: number): string {
  const lines = text.split(/\r?\n/);
  return lines.slice(Math.max(0, startLine - 1), Math.min(lines.length, endLine)).join("\n");
}

export function clamp(value: number, min: number, max: number): number {
  return Math.max(min, Math.min(max, value));
}

lineRange 函数用于按行号范围提取文本片段,是分块策略的基础工具。clamp 函数确保数值在指定范围内,用于置信度计算。

二进制文件检测

export function isLikelyBinary(buffer: Buffer): boolean {
  const sample = buffer.subarray(0, Math.min(buffer.length, 4096));
  return sample.includes(0);
}

索引过程会跳过二进制文件以节省存储空间和提升检索效率。

资料来源:src/util.ts:1-30

MCP 服务器集成

Contextful 支持以 MCP(Model Context Protocol)服务器模式运行,提供标准化工具接口:

npx @inferensys/contextful server

核心工具列表

工具名称功能描述
context_pack生成带证据包的上下文响应
search_code代码、文档、符号和记忆搜索
trace_path图谱遍历追踪依赖路径
impact_analysis影响分析和反向依赖查找
why_changed变更历史追溯
recall_memory检索持久化的项目记忆

资料来源:README.md:25-40

性能优化策略

Token 估算与预算控制

系统使用简单的 token 估算方法控制输出大小:

function estimateTokens(text: string): number {
  return Math.ceil(text.length / 4);  // 粗略估算:每4字符约1个token
}

证据包生成时会根据用户指定的 budget 参数筛选内容,确保返回的上下文在 token 预算范围内。

结果去重

搜索结果通过引用标识符进行去重:

function dedupeHits(hits: SearchHit[]): SearchHit[] {
  const seen = new Set<string>();
  return hits.filter((hit) => {
    if (seen.has(hit.ref)) return false;
    seen.add(hit.ref);
    return true;
  });
}

图谱剪枝

图谱查询支持深度限制,防止返回过大的依赖路径:

const graphPaths = loadGraphPaths(kernel.db, paths, 20);  // 限制最多20条路径

总结

Contextful 的数据存储与索引系统通过模块化的设计实现了高效的代码检索能力。符号提取与边分析模块支持多种主流编程语言,SQLite+FTS5 的组合提供了可靠且快速的全文搜索能力。证据包机制将搜索结果包装为结构化的上下文响应,便于 AI 代理直接使用。整个系统的设计强调实用性和可扩展性,是构建代码智能助手的重要基础设施。

资料来源:[README.md:1-10]()

MCP 服务器集成

Contextful 项目通过 MCP(Model Context Protocol)协议提供服务器集成能力,使其能够作为标准的 MCP 服务器运行,为 AI 代理提供代码上下文理解服务。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 contextpack

继续阅读本节完整说明和来源证据。

章节 searchcode

继续阅读本节完整说明和来源证据。

章节 tracepath

继续阅读本节完整说明和来源证据。

概述

Contextful 项目通过 MCP(Model Context Protocol)协议提供服务器集成能力,使其能够作为标准的 MCP 服务器运行,为 AI 代理提供代码上下文理解服务。

MCP 服务器集成的核心设计理念是:代理请求上下文,Contextful 返回紧凑的证据包。这种设计避免了强制 AI 代理读取大量随机文件,通过结构化的证据打包机制提供精准、相关的上下文信息。

核心功能

Contextful MCP 服务器暴露以下核心工具:

工具名称功能描述
context_pack返回排名、引用、令牌预算内的证据包
search_code强大的代码、文档、符号和内存搜索
trace_path在文件、符号、模块和配置之间进行图遍历
impact_analysis逆向依赖和可能的测试
why_changed当前证据加 Git 历史
recall_memory搜索会话学习记录和持久化的项目经验
write_lesson写入带证据支撑的经验教训

架构设计

graph TD
    A[AI 代理] -->|MCP 协议| B[Contextful MCP 服务器]
    B --> C{功能路由}
    C -->|上下文打包| D[createContextPack]
    C -->|代码搜索| E[searchContext]
    C -->|图路径追踪| F[traceGraph]
    C -->|影响分析| G[impactAnalysis]
    C -->|历史分析| H[whyChanged]
    C -->|记忆检索| I[recallMemory]
    D --> J[SQLite Kernel DB]
    E --> J
    F --> J
    G --> J
    H --> J
    I --> J

工具参数规范

context_pack

参数类型必填说明
querystring要回答的查询
budgetnumber令牌预算,默认 2000
scopestring搜索范围,默认 "repo"

search_code

参数类型必填说明
querystring搜索查询
modestring搜索模式
filtersobject过滤条件

trace_path

参数类型必填说明
fromstring起始节点
tostring目标节点
edge_typesstring[]边类型过滤

搜索意图分类

系统会根据查询内容自动分类搜索意图:

意图类型触发关键词说明
codefunction, class, variable代码实体搜索
memorymemory, lesson, learned记忆和经验检索
impactimpact, depends, affected影响范围分析
historicalwhy, history, commit历史变更追溯
architecturalarchitecture, flow, dependency架构依赖分析
docsdocumentation, readme, how to文档搜索

资料来源:src/search.ts:1-15

查询扩展机制

系统包含智能查询扩展功能,根据用户查询自动添加相关术语:

// 相关术语扩展示例
if (/\b(tool|tools|registered|register)\b/.test(lower)) {
  additions.push("server", "tool", "tools", "callTool");
}
if (/\bmcp\b/.test(lower)) {
  additions.push("mcp", "server", "stdio");
}
if (/\bmemory|memories|remember\b/.test(lower)) {
  additions.push("memory", "memories", "lesson", "lessons", "claim", "ledger", "evidence");
}

资料来源:src/search.ts:45-60

证据包结构

context_pack 返回的结构化证据包包含以下字段:

字段类型说明
idstring唯一标识符
querystring原始查询
intentSearchIntent检测到的搜索意图
summarystring证据摘要
citationsSearchHit[]引用列表
filesFileInfo[]相关文件信息
symbolsSymbolRecord[]相关符号
graphPathsGraphPath[]图路径连接
memoryHitsSearchHit[]记忆命中
confidencenumber置信度 0-1
tokenEstimatenumber令牌估算
budgetnumber令牌预算
createdAtstring创建时间

启动方式

CLI 命令行启动

npx @inferensys/contextful server

MCP 服务器配置

服务器注册名称为 io.github.Inferensys/contextful,可通过 server.json 进行配置:

{
  "mcpServers": {
    "contextful": {
      "command": "npx",
      "args": ["@inferensys/contextful", "server"]
    }
  }
}

资料来源:package.json:40

依赖关系

MCP 服务器集成依赖以下核心包:

依赖包版本用途
@modelcontextprotocol/sdk^1.29.0MCP 协议实现
better-sqlite3^12.10.0本地索引数据库
zod^4.4.3类型验证

资料来源:package.json:19-32

内存管理功能

MCP 服务器提供持久化的记忆功能,支持通过 CLI 添加经验教训:

cxf memory add \
  --claim "使用 JWT 时必须验证签名" \
  --evidence "file:src/auth.ts:1-50" \
  --scope "repo" \
  --confidence 0.9

记忆数据与搜索系统集成,在相关查询时可以自动召回。

与 AI IDE 的集成

Contextful 支持多种 AI 编程辅助工具的 MCP 集成:

  • Windsurf
  • GitHub Copilot
  • VS Code
  • Cline
  • Roo Code
  • Continue
  • Zed

资料来源:package.json:8-15

工作流程示例

sequenceDiagram
    participant Agent as AI 代理
    participant MCP as Contextful MCP
    participant Kernel as Kernel DB
    participant FS as 文件系统

    Agent->>MCP: context_pack("用户认证逻辑在哪")
    MCP->>Kernel: 搜索相关索引
    Kernel-->>MCP: 命中结果 + 图路径
    MCP->>MCP: 构建证据包
    MCP->>Agent: 返回紧凑证据包
    Agent->>Agent: 基于证据回答

总结

MCP 服务器集成是 Contextful 的核心交互接口,它将复杂的代码索引和搜索能力通过标准化的 MCP 协议暴露给 AI 代理。通过结构化的证据包、图路径追踪和记忆系统,代理能够获得精准、可靠且可追溯的代码上下文,显著提升代码理解任务的准确性。

资料来源:[src/search.ts:1-15]()

解析与代码提取

解析与代码提取是 Contextful 项目中负责将源代码文件转换为可索引、可搜索的结构化数据的关键模块。该模块位于 src/extract.ts,是整个上下文检索系统的核心基础设施。其主要职责包括:

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 extractSymbols 函数

继续阅读本节完整说明和来源证据。

章节 extractEdges 函数

继续阅读本节完整说明和来源证据。

章节 分块策略概览

继续阅读本节完整说明和来源证据。

概述

解析与代码提取是 Contextful 项目中负责将源代码文件转换为可索引、可搜索的结构化数据的关键模块。该模块位于 src/extract.ts,是整个上下文检索系统的核心基础设施。其主要职责包括:

  • 符号提取:从源代码中识别函数、类、接口、类型等定义
  • 边关系提取:解析文件间的导入依赖关系
  • 代码分块:将大型文件语义化拆分为可管理的片段
  • Markdown 处理:提取标题结构并按章节分块

资料来源:src/extract.ts:1-50

核心功能架构

    A[源代码文件] --> B{文件类型判断}
    B -->|TypeScript/JavaScript| C[TypeScript/JS 解析器]
    B -->|Python| D[Python 解析器]
    B -->|Go| E[Go 解析器]
    B -->|Rust| F[Rust 解析器]
    B -->|Markdown| G[Markdown 处理器]
    B -->|JSON| H[JSON 处理器]
    
    C --> I[extractSymbols]
    D --> I
    E --> I
    F --> I
    
    I --> J[符号列表]
    C --> K[extractEdges]
    D --> K
    E --> K
    F --> K
    H --> K
    
    K --> L[边关系列表]
    J --> M[codeChunks]
    L --> M
    
    G --> N[markdownChunks]
    N --> O[文档分块]
    M --> P[索引数据库]
    O --> P

符号提取详解

extractSymbols 函数

extractSymbols 是符号提取的主入口函数,通过正则表达式匹配源代码中的各种声明语句。

资料来源:src/extract.ts:50-100

#### 支持的语言与符号类型

语言符号类型正则模式
TypeScript/JavaScript函数/^\s*(export\s+)?(?:async\s+)?function\s+([A-Za-z_$][\w$]*)/
TypeScript/JavaScript/^\s*(export\s+)?class\s+([A-Za-z_$][\w$]*)/
TypeScript/JavaScript接口/^\s*(export\s+)?interface\s+([A-Za-z_$][\w$]*)/
TypeScript/JavaScript类型/^\s*(export\s+)?type\s+([A-Za-z_$][\w$]*)/
Python函数/^\s*(?:async\s+)?def\s+([A-Za-z_][\w]*)/
Python/^\s*class\s+([A-Za-z_][\w]*)/
Go函数/^\s*func\s+(?:\([^)]*\)\s*)?([A-Za-z_][\w]*)/
Go结构体/接口`/^\s*type\s+([A-Za-z_][\w]*)\s+(struct\interface)/`
Rust函数/^\s*(pub\s+)?fn\s+([A-Za-z_][\w]*)/
Rust结构体/^\s*(pub\s+)?struct\s+([A-Za-z_][\w]*)/
Rust枚举/^\s*(pub\s+)?enum\s+([A-Za-z_][\w]*)/
RustTrait/^\s*(pub\s+)?trait\s+([A-Za-z_][\w]*)/

#### matchPush 辅助函数

matchPush 是一个通用的高阶函数,用于将正则匹配结果转换为符号记录:

function matchPush(
  line: string,
  pattern: RegExp,
  push: (name: string, kind: string, exported?: boolean) => void,
  kind: string
): void {
  const match = line.match(pattern);
  if (!match) return;
  push(match[2], kind, Boolean(match[1]));
}

该函数的设计允许:

  • 捕获符号名称(match[2])
  • 标记导出状态(match[1] 匹配 export 关键字)
  • 统一处理不同类型的符号

资料来源:src/extract.ts:120-130

边关系提取详解

extractEdges 函数

extractEdges 函数负责解析代码中的导入语句,构建模块间的依赖图。

资料来源:src/extract.ts:135-180

#### 各语言的导入语句识别

语言导入类型正则/匹配模式
TypeScript/JavaScriptES Module`/(?:from\s+\import\s*)"'["']/g`
TypeScript/JavaScriptCommonJS/require\("'["']\)/g
Pythonfrom import/^\s*from\s+([\w.]+)\s+import\s+/
Pythonimport/^\s*import\s+([\w.]+)/
Go导入路径/"([^"]+)"/g
Rustuse 语句/^\s*use\s+([^;]+);/
Rustmod 声明/^\s*mod\s+([A-Za-z_][\w]*);/

#### 特殊的 package.json 处理

当文件路径以 package.json 结尾时,函数会解析 JSON 内容并生成配置依赖边:

if (relativePath.endsWith("package.json")) {
  try {
    const parsed = JSON.parse(content) as Record<string, unknown>;
    for (const section of ["dependencies", "devDependencies", "peerDependencies", "scripts"]) {
      const values = parsed[section];
      if (!values || typeof values !== "object") continue;
      for (const key of Object.keys(values)) {
        edges.push({ targetName: `${section}:${key}`, targetType: "config", edgeType: "CONFIGURES", line: 1 });
      }
    }
  } catch {
    // Broken JSON 处理
  }
}

资料来源:src/extract.ts:175-195

代码分块机制

分块策略概览

Contextful 实现了多种分块策略以适应不同的文件类型和搜索需求:

    A[输入文件] --> B{文件类型}
    B -->|代码文件| C[codeChunks]
    B -->|Markdown| D[markdownChunks]
    B -->|纯文本| E[textChunks]
    
    C --> F[符号边界分块]
    C --> G[空行分块]
    G --> H[合并小片段]
    F --> H
    H --> I[生成 ChunkRecord]
    
    D --> J[提取标题]
    J --> K[按标题切分]
    K --> I
    
    E --> L[固定行数分块]
    L --> I

codeChunks 函数

codeChunks 是代码文件的主要分块实现,采用以下策略:

  1. 空行分割:在空行处将文件分割为候选块
  2. 符号保护:确保函数/类定义的完整性不被分割
  3. 小片段合并:将行数过少的片段合并到前一个块
  4. 测试文件优先:测试文件中的相关代码会被优先选中
function codeChunks(relativePath: string, content: string, language: string): ChunkRecord[] {
  const symbols = extractSymbols(relativePath, content, language);
  const symbolLines = new Set(symbols.map((s) => s.line));
  
  // 空行分割逻辑...
  // 符号边界保护...
  // 小片段合并...
  
  return chunks;
}

资料来源:src/extract.ts:200-250

测试文件识别

isTestFile 函数使用以下模式识别测试文件:

function isTestFile(relativePath: string): boolean {
  return /(^|\/)(tests?|__tests__)\/|(\.|-)(test|spec)\.[A-Za-z]+$/.test(relativePath);
}

符合以下任一条件的文件将被识别为测试文件:

  • 目录名包含 testtests__tests__
  • 文件名以 .test-test.spec-spec 结尾

资料来源:src/extract.ts:260-265

Markdown 处理

markdownChunks 函数

Markdown 文件的分块基于标题结构:

function markdownChunks(relativePath: string, content: string): ChunkRecord[] {
  const lines = content.split(/\r?\n/);
  const headings: Array<{ title: string; line: number }> = [];
  
  // 提取所有标题 (# 到 ######)
  lines.forEach((line, index) => {
    const match = line.match(/^(#{1,6})\s+(.+)$/);
    if (match) headings.push({ title: match[2].trim(), line: index + 1 });
  });
  
  // 无标题时返回整个文件
  // 有标题时按标题切分
}

资料来源:src/extract.ts:280-310

CLI 命令集成

解析与代码提取功能通过 CLI 模块对外提供服务:

    A[CLI 入口] --> B[index 命令]
    A --> C[daemon 命令]
    A --> D[query 命令]
    A --> E[search 命令]
    A --> F[report 命令]
    
    B --> G[ensureIndexed]
    G --> H[索引工作区]
    H --> I[调用 extract.ts]
    
    D --> J[createContextPack]
    J --> K[搜索索引]
    K --> I

主要 CLI 命令

命令功能相关源码
index索引工作区中的所有代码文件src/cli.ts:30-50
daemon启动本地索引守护进程src/cli.ts:55-65
query根据查询创建证据包src/cli.ts:70-85
search在索引中搜索上下文src/cli.ts:90-105
report生成上下文报告src/cli.ts:110-120

资料来源:src/cli.ts:1-100

搜索与索引集成

搜索上下文流程

解析提取的数据最终服务于搜索功能:

    A[searchContext] --> B[classifyQuery]
    B --> C{意图类型}
    C -->|exact| D[精确匹配]
    C -->|code| E[FTS 代码搜索]
    C -->|docs| F[FTS 文档搜索]
    C -->|symbol| G[符号搜索]
    C -->|memory| H[记忆搜索]
    
    D --> I[rankResults]
    E --> I
    F --> I
    G --> I
    H --> I
    
    I --> J[dedupeHits]
    J --> K[返回搜索结果]

查询意图分类

classifyQuery 函数根据查询特征判断用户意图:

意图触发关键词资料来源
symbolfunction, class, interfacesrc/search.ts:20-30
memorymemory, lesson, remembersrc/search.ts:35-40
impactimpact, affected, dependssrc/search.ts:42-44
historicalwhy, changed, historysrc/search.ts:46-48
architecturalarchitecture, flow, importssrc/search.ts:50-52
docsdocs, documentation, readmesrc/search.ts:54-56

资料来源:src/search.ts:15-60

证据包生成

createContextPack 函数

createContextPack 将搜索结果整合为结构化的证据包:

export async function createContextPack(options: CreatePackOptions): Promise<EvidencePack> {
  const search = await searchContext({ workspace, query, limit: budget });
  
  // 选择性合并...
  const selected = search.hits.slice(0, maxChunks);
  
  const tokenEstimate = estimateTokens(selected.map((h) => h.text).join("\n"));
  
  const kernel = openKernelDb(workspace);
  const graphPaths = loadGraphPaths(kernel.db, paths, 20);
  
  const pack: EvidencePack = {
    id: `ctx_${shortHash(`${query}:${nowIso()}`)}`,
    query,
    scope,
    intent: search.intent,
    summary: summarizePack(query, search.intent, selected, graphPaths, memoryHits),
    citations: selected,
    confidence: confidenceFor(selected, graphPaths, memoryHits),
    // ...
  };
  
  return pack;
}

资料来源:src/search.ts:150-200

工具函数

行范围提取

lineRange 函数从文本中提取指定行范围:

export function lineRange(text: string, startLine: number, endLine: number): string {
  const lines = text.split(/\r?\n/);
  return lines.slice(Math.max(0, startLine - 1), Math.min(lines.length, endLine)).join("\n");
}

资料来源:src/util.ts:30-35

二进制文件检测

isLikelyBinary 函数通过检测空字节判断文件类型:

export function isLikelyBinary(buffer: Buffer): boolean {
  const sample = buffer.subarray(0, Math.min(buffer.length, 4096));
  return sample.includes(0);
}

资料来源:src/util.ts:20-25

数据模型

ChunkRecord 结构

interface ChunkRecord {
  ref: string;           // 文件引用,如 "file:src/auth.ts:1-20"
  filePath: string;      // 相对文件路径
  startLine: number;     // 起始行号
  endLine: number;       // 结束行号
  kind: "code" | "doc" | "file";  // 块类型
  title: string;         // 标题/符号名
  text: string;          // 块内容
  tokenEstimate: number; // token 估算值
}

RawEdge 结构

interface RawEdge {
  targetName: string;    // 目标名称
  targetType: "module" | "config" | "symbol";  // 目标类型
  edgeType: "IMPORTS" | "CONFIGURES";  // 边类型
  line: number;          // 所在行号
  filePath?: string;     // 文件路径
}

资料来源:src/extract.ts:40-48

报告生成

generateReport 函数

generateReport 汇总索引状态并生成统计报告:

export async function generateReport(options: { workspace?: string }): Promise<ContextReport> {
  const workspace = resolveWorkspace(options.workspace);
  await ensureIndexed(workspace);
  const kernel = openKernelDb(workspace);
  
  const languageRows = kernel.db
    .prepare("SELECT language, COUNT(*) AS count FROM files GROUP BY language ORDER BY count DESC")
    .all();
  
  // 收集统计信息...
  // 生成报告...
}

资料来源:src/report.ts:50-80

总结

解析与代码提取模块是 Contextful 的核心基础设施,通过模块化的设计实现了对多种编程语言的支持。其关键设计特点包括:

  1. 正则驱动:使用正则表达式实现轻量级代码解析
  2. 语义分块:保持函数/类边界的完整性
  3. 多语言支持:覆盖 TypeScript、JavaScript、Python、Go、Rust 等主流语言
  4. 测试优先:自动识别并优先处理测试文件
  5. 可扩展架构:通过 matchPush 等高阶函数便于添加新语言支持

该模块与搜索模块紧密集成,共同构成了上下文检索的能力基础。

资料来源:[src/extract.ts:1-50]()

CLI 命令行工具

Contextful 的 CLI(命令行界面)是用户与上下文索引系统交互的主要入口点。该工具提供了索引工作区、查询证据包、搜索上下文、生成报告以及管理 MCP 服务器等功能。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 命令层次结构

继续阅读本节完整说明和来源证据。

章节 命令总览

继续阅读本节完整说明和来源证据。

章节 index

继续阅读本节完整说明和来源证据。

概述

Contextful 的 CLI(命令行界面)是用户与上下文索引系统交互的主要入口点。该工具提供了索引工作区、查询证据包、搜索上下文、生成报告以及管理 MCP 服务器等功能。

CLI 采用 Commander.js 框架构建,支持多种子命令,覆盖了从代码索引到证据管理的完整工作流程。cxf 是主二进制文件名称,同时提供 contextful 作为可读别名。

资料来源:src/cli.ts:1-20

核心命令架构

命令层次结构

graph TD
    A[cxf / contextful] --> B[index]
    A --> C[daemon]
    A --> D[query]
    A --> E[search]
    A --> F[report]
    A --> G[memory]
    A --> H[server]
    
    G --> G1[memory add]

命令总览

命令功能描述输出格式
index索引工作区文件JSON
daemon启动本地索引守护进程JSON(流式)
query创建证据包Markdown / JSON
search搜索索引上下文JSON
report生成上下文报告Markdown / JSON / HTML
memory add存储证据-backed 经验JSON
server运行 MCP stdio 服务器-

资料来源:src/cli.ts:20-80

索引命令

index

索引命令用于扫描工作区中的代码文件,建立搜索索引。

cxf index --workspace <path> [--watch]

#### 参数与选项

参数类型必需默认值说明
--workspace <path>stringprocess.cwd()工作区路径
--watchflagfalse监听文件变化

#### 功能说明

  • 扫描指定工作区路径下的所有代码文件
  • 支持 TypeScript、JavaScript、Python、Go、Rust 等多种语言
  • 提取文件中的符号(symbols)、边(edges)和代码块(chunks)
  • 将索引数据存储到 SQLite 数据库中

资料来源:src/cli.ts:20-35

daemon

守护进程命令启动一个持续运行的索引服务,监听文件系统变化并实时更新索引。

cxf daemon --workspace <path>

#### 特性

  • 实时监听工作区文件变化
  • 增量更新索引,而非完全重建
  • 通过 stdout 流式输出 JSON 格式的索引结果

资料来源:src/cli.ts:36-45

查询命令

query

query 命令是 Contextful 的核心功能,用于创建紧凑的证据包回答用户查询。

cxf query "<query>" --workspace <path> --budget <tokens> [--json]

#### 参数与选项

参数类型必需默认值说明
<query>string-要回答的查询语句
--workspace <path>stringprocess.cwd()工作区路径
--budget <tokens>integer2000近似 token 预算
--jsonflagfalse输出 JSON 而非 Markdown

#### 工作流程

graph LR
    A[用户查询] --> B[搜索索引]
    B --> C[意图分类]
    C --> D[BM25 排序]
    D --> E[图路径分析]
    E --> F[选择证据]
    F --> G[生成证据包]
    G --> H[返回结果]

#### 输出内容

证据包包含以下结构化信息:

  • id: 证据包唯一标识符
  • query: 原始查询
  • intent: 搜索意图分类
  • summary: 结果摘要
  • citations: 选中的证据引用列表
  • files: 相关文件及原因
  • symbols: 匹配的符号记录
  • graphPaths: 图连接路径
  • memoryHits: 记忆命中
  • confidence: 置信度分数
  • tokenEstimate: 估算的 token 数量
  • budget: 分配的 token 预算
  • createdAt: 创建时间戳

资料来源:src/cli.ts:46-60, src/search.ts:80-150

搜索命令

search 命令提供轻量级的上下文搜索功能,不生成完整证据包。

cxf search "<query>" --workspace <path> --limit <count> --kind <kind>

#### 参数与选项

参数类型必需默认值说明
<query>string-搜索查询
--workspace <path>stringprocess.cwd()工作区路径
--limit <count>integer10最大命中数
--kind <kind>enumall搜索类型

#### kind 参数选项

说明
all所有类型
code仅代码
docs仅文档
symbols仅符号
memory仅记忆

资料来源:src/cli.ts:70-80

报告命令

report

生成工作区的上下文索引报告。

cxf report --workspace <path> --format <format>

#### 参数与选项

参数类型必需默认值说明
--workspace <path>stringprocess.cwd()工作区路径
--format <format>enummarkdown输出格式

#### format 参数选项

说明
markdownMarkdown 格式(默认)
jsonJSON 格式
htmlHTML 格式

#### 报告内容

报告包含以下部分:

  • 索引状态概览
  • 语言覆盖率统计
  • 热门查询记录
  • 陈旧记忆列表
  • Agent 使用建议
  • 警告信息(如有)

资料来源:src/cli.ts:81-90, src/report.ts:1-100

记忆管理命令

memory add

存储证据-backed 的经验教训到记忆账本中。

cxf memory add \
  --claim <text> \
  --evidence <ref...> \
  --workspace <path> \
  --scope <scope> \
  --confidence <number>

#### 参数与选项

参数类型必需默认值说明
--claim <text>string-经验声明
--evidence <ref...>string[]-证据引用列表
--workspace <path>stringprocess.cwd()工作区路径
--scope <scope>stringrepo记忆作用域
--confidence <number>float0.7置信度(0-1)

#### 证据引用格式

证据引用格式为:file:src/auth.ts:1-20,表示从 src/auth.ts 文件的第 1-20 行提取证据。

#### 功能说明

  • 验证证据引用的有效性
  • 将经验存储到 SQLite 数据库
  • 支持覆盖(supersedes)旧记忆

资料来源:src/cli.ts:92-125

MCP 服务器命令

server

启动 MCP(Model Context Protocol)stdio 服务器。

cxf server

#### 功能说明

  • 提供 MCP 标准工具接口
  • 支持 context_packsearch_codetrace_path 等工具
  • 通过 stdio 与 AI 代理通信

资料来源:src/cli.ts:126-135

工具函数

参数解析辅助函数

function parseInteger(value: string): number
function parseReportFormat(value: string): ReportFormat
函数输入输出错误处理
parseInteger字符串整数无效整数抛出错误
parseReportFormat字符串markdown/json/html无效格式抛出错误

资料来源:src/cli.ts:148-165

错误处理

CLI 采用统一的错误处理机制:

program.parseAsync(process.argv).catch((error) => {
  process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
  process.exitCode = 1;
});

错误处理特点:

  • 错误信息输出到 stderr
  • 非零退出码表示失败
  • 区分 Error 实例与普通字符串

资料来源:src/cli.ts:136-145

安装与使用

安装方式

npx @inferensys/contextful index --workspace .
npx @inferensys/contextful query "where is user auth handled" --workspace . --budget 2000

MCP 服务器启动

npx @inferensys/contextful server

环境要求

  • Node.js >= 20
  • 支持 Unix-like 系统及 Windows

资料来源:package.json:1-30, README.md:1-30

快速参考

命令用途
cxf index --workspace . --watch索引并监听变化
cxf query "认证逻辑在哪里"查询证据包
cxf search "auth" --kind code搜索代码
cxf report --format html生成 HTML 报告
cxf memory add --claim "..." --evidence file:src/x.ts:1-10添加记忆
cxf server启动 MCP 服务器

资料来源:[src/cli.ts:1-20]()

部署与配置

部署与配置 是 Contextful 项目的安装、环境设置及运行时参数管理模块。该模块涵盖了从 NPM 包安装到 MCP 服务器运行的完整部署链路,为开发者提供命令行界面(CLI)和 MCP(Model Context Protocol)服务器两种使用方式。Contextful 是一个上下文管理工具,帮助智能体(Agent)在处理复杂任务时获取精确的代码证据和上下文信息。

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 本地 CLI 部署

继续阅读本节完整说明和来源证据。

章节 MCP 服务器部署

继续阅读本节完整说明和来源证据。

章节 索引命令 (index)

继续阅读本节完整说明和来源证据。

概述

部署与配置 是 Contextful 项目的安装、环境设置及运行时参数管理模块。该模块涵盖了从 NPM 包安装到 MCP 服务器运行的完整部署链路,为开发者提供命令行界面(CLI)和 MCP(Model Context Protocol)服务器两种使用方式。Contextful 是一个上下文管理工具,帮助智能体(Agent)在处理复杂任务时获取精确的代码证据和上下文信息。

核心部署模式

Contextful 支持两种主要的部署模式,适用于不同的使用场景。

本地 CLI 部署

本地 CLI 部署适合开发者直接在终端环境中使用,适用于代码浏览、上下文搜索和报告生成等场景。CLI 模式通过 cxfcontextful 命令行工具提供完整功能集。

# 基本索引操作
npx @inferensys/contextful index --workspace .

# 创建证据包
npx @inferensys/contextful query "where is user auth handled" --workspace . --budget 2000

资料来源:README.md

MCP 服务器部署

MCP 服务器部署适用于将 Contextful 作为智能体工具集成的场景。服务器通过标准输入/输出(stdio)接口与 MCP 客户端通信,提供标准化的工具调用接口。

npx @inferensys/contextful server

MCP 服务器模式下,Contextful 提供以下核心工具接口供智能体调用:

工具名称功能描述主要参数
context_pack返回排序的、带引用的、符合token预算的证据包query, budget, scope
search_code强大的代码、文档、符号和内存搜索query, mode, filters
trace_path跨文件、符号、模块和配置的图遍历from, to, edge_types
impact_analysis反向依赖分析和可能的测试识别symbol_or_file
why_changed结合当前证据和Git历史解释变更原因symbol_or_file, limit
recall_memory搜索跨会话持久化的项目经验query, scope, limit
write_lesson将带证据的经验写入内存账本claim, evidence_refs, scope, confidence

资料来源:README.md, src/mcp-server.ts

CLI 命令详解

CLI 是 Contextful 的主要交互接口,命令结构遵循 cxf <command> [options] 的格式。

索引命令 (index)

索引命令用于扫描和索引工作区内的代码文件,建立搜索和图遍历的基础数据。

cxf index --workspace <path> [--watch]
选项类型默认值说明
--workspacepathprocess.cwd()工作区路径
--watchflagfalse监视模式,持续监听文件变化

资料来源:src/cli.ts

守护进程命令 (daemon)

守护进程命令启动本地索引服务,持续监视工作区文件变化并更新索引。

cxf daemon --workspace <path>

当工作区文件发生变更时,守护进程会主动推送更新结果到标准输出:

await watchWorkspace(options.workspace, (result) => {
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
});

资料来源:src/cli.ts

查询命令 (query)

查询命令是 Contextful 的核心功能,根据自然语言查询创建包含证据的上下文包。

cxf query "<query>" --workspace <path> --budget <tokens> [--json]
选项类型默认值说明
--workspacepathprocess.cwd()工作区路径
--budgetnumber2000近似token预算
--jsonflagfalse输出JSON格式而非Markdown

查询命令内部调用 createContextPack 函数,生成包含以下信息的证据包:

  • 查询意图分类(intent)
  • 置信度评分(confidence)
  • 相关代码引用(citations)
  • 依赖图路径(graphPaths)
  • 内存命中(memoryHits)

资料来源:src/cli.ts, src/search.ts

搜索命令在不编译完整证据包的情况下搜索索引上下文,适用于快速定位信息。

cxf search "<query>" --workspace <path> --limit <count> --kind <kind>
选项类型默认值说明
--workspacepathprocess.cwd()工作区路径
--limitnumber10最大命中数
--kindenum"all"搜索类型:all/code/docs/symbols/memory

搜索类型参数决定搜索结果的过滤范围:

  • all:搜索所有类型的索引块
  • code:仅搜索代码文件块
  • docs:仅搜索文档块
  • symbols:仅搜索符号定义块
  • memory:仅搜索内存记录块

资料来源:src/cli.ts, src/search.ts

报告命令 (report)

报告命令生成工作区的上下文索引报告。

cxf report --workspace <path> --format <format>
选项类型默认值说明
--workspacepathprocess.cwd()工作区路径
--formatenum"markdown"输出格式:markdown/json/html

报告生成器调用 generateReport 函数,收集工作区的索引统计信息并渲染为指定格式。

资料来源:src/cli.ts, src/report.ts

内存管理命令 (memory)

内存命令用于管理证据支持的智能体内存,允许存储和检索跨会话的项目经验。

#### 添加经验 (add)

cxf memory add --claim <text> --evidence <ref...> --workspace <path> --scope <scope> --confidence <number>
选项类型默认值说明
--claimtext必需经验声明/教训
--evidenceref[]必需证据引用,如 file:src/auth.ts:1-20
--workspacepathprocess.cwd()工作区路径
--scopestring"repo"内存范围
--confidencenumber0.7置信度(0-1)

经验引用格式:file:<relativePath>:<startLine>-<endLine>

cxf memory add \
  --claim "用户认证模块位于 src/auth.ts" \
  --evidence "file:src/auth.ts:1-50" \
  --workspace . \
  --confidence 0.9

资料来源:src/cli.ts

MCP 服务器命令 (server)

服务器命令启动 MCP stdio 服务器,供 MCP 客户端连接使用。

cxf server

服务器接收来自客户端的工具调用请求,执行相应操作并返回 JSON 格式的结果。工具参数使用 Zod 模式进行验证。

资料来源:src/cli.ts, src/mcp-server.ts

工作区配置

工作区路径解析

工作区路径的解析遵循以下优先级:

  1. CLI 选项 --workspace 显式指定
  2. 环境变量 WORKSPACE(如果实现)
  3. 当前工作目录 process.cwd() 作为默认值
.option("--workspace <path>", "Workspace path.", process.cwd())

资料来源:src/cli.ts

索引结构

工作区索引数据库(kernel.db)包含以下核心表结构:

表名用途关键字段
files已索引文件元数据path, language, indexed_at
chunks_fts全文搜索索引ref, path, title, text, bm25
symbols代码符号索引name, kind, file_path, line
edges导入/依赖关系图from, to, edge_type, file_path, line
lessons经验记忆存储id, claim, scope, confidence, evidence
query_log查询历史记录query, intent, timestamp

文件类型支持

索引器支持多种编程语言的符号提取和边关系提取:

语言符号类型边关系类型
TypeScript/JavaScriptfunction, class, interface, type, constES imports, require()
Pythondef, classfrom...import, import
Gofunc, struct, interfaceimport
Rustfn, struct, enum, trait, impluse, mod
Markdownheading-
JSONconfig-key-

资料来源:src/extract.ts

报告生成配置

报告格式选项

报告支持三种输出格式,通过 --format 选项指定:

#### Markdown 格式

默认格式,生成人类可读的 Markdown 文档,包含以下章节:

  • 工作区概览
  • 文件语言分布
  • 索引警告
  • Token 使用统计

#### JSON 格式

机器可读的 JSON 输出,适合程序化处理:

{
  "status": { "workspace": "...", "indexedAt": "...", "languageDistribution": [...] },
  "summary": { "totalChunks": 123, "totalSymbols": 456, "totalEdges": 789 },
  "tokenSavingsEstimate": { "indexedTokens": ..., "averagePackTokens": ... }
}

#### HTML 格式

自包含的 HTML 文档,内嵌样式,适合浏览器查看:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Contextful Report</title>
  <style>
    body { font: 15px/1.55 system-ui, sans-serif; margin: 0; ... }
  </style>
</head>
<body><main><pre>[Markdown content]</pre></main></body>
</html>

资料来源:src/report.ts

运行时参数配置

查询预算配置

--budget 参数控制返回证据包的 token 上限,影响搜索结果的精选程度:

预算值适用场景示例
1000-2000简短查询、精确查找cxf query "auth middleware" --budget 1500
2000-5000标准查询、代码理解cxf query "how does cache work" --budget 3000
5000+复杂查询、架构分析cxf query "dependency injection flow" --budget 8000

搜索类型过滤

--kind 参数过滤搜索结果的类型范围:

# 仅搜索代码符号
cxf search "UserService" --kind symbols

# 仅搜索文档
cxf search "installation guide" --kind docs

# 仅搜索记忆
cxf search "previous lessons" --kind memory

置信度阈值

经验记忆的置信度参数(--confidence)影响信息优先级排序:

  • 0.9-1.0:高置信度,直接可用于决策
  • 0.7-0.9:中高置信度,建议交叉验证
  • 0.5-0.7:中等置信度,需要更多证据支持
  • 0.0-0.5:低置信度,仅作参考

部署架构图

graph TD
    A[开发者终端] --> B[CLI 界面]
    A --> C[MCP 客户端]
    
    B --> D[index 命令]
    B --> E[query 命令]
    B --> F[search 命令]
    B --> G[report 命令]
    B --> H[memory 命令]
    
    C --> I[MCP Server]
    I --> J[context_pack 工具]
    I --> K[search_code 工具]
    I --> L[trace_path 工具]
    I --> M[impact_analysis 工具]
    I --> N[why_changed 工具]
    I --> O[recall_memory 工具]
    I --> P[write_lesson 工具]
    
    D --> Q[文件系统扫描]
    Q --> R[SQLite 数据库]
    
    E --> S[证据包生成]
    S --> R
    S --> T[Token 预算控制]
    
    F --> U[全文搜索]
    U --> R
    
    G --> V[报告渲染]
    V --> W[Markdown/JSON/HTML]
    
    H --> X[记忆存储]
    X --> R

环境变量参考

变量名类型说明默认值
WORKSPACEstring工作区根目录路径当前工作目录
CONTEXTFUL_BUDGETnumber默认 token 预算2000

常见部署场景

场景一:本地开发环境

适用于开发者在本地机器上浏览和分析代码库:

# 首次索引
cxf index --workspace /path/to/project

# 启动守护进程监视变化
cxf daemon --workspace /path/to/project &

# 执行查询
cxf query "用户认证流程" --workspace /path/to/project --budget 3000

场景二:智能体集成

将 Contextful 作为智能体工具集成的标准模式:

  1. 启动 MCP 服务器
  2. 配置 MCP 客户端连接
  3. 通过 context_pack 工具获取上下文
# 服务器端
cxf server

# 客户端调用示例(伪代码)
result = mcp_client.call_tool("context_pack", {
  query: "where is user auth handled",
  budget: 2000,
  scope: "repo"
})

场景三:CI/CD 集成

在持续集成流程中生成索引报告:

# .github/workflows/context-report.yml
- name: Generate Context Report
  run: |
    npx @inferensys/contextful index --workspace .
    npx @inferensys/contextful report --workspace . --format html > report.html

安全考虑

敏感信息处理

Contextful 在日志输出和报告生成中自动过滤敏感信息:

// 邮箱地址脱敏
if (match.includes("@") && !match.toLowerCase().includes("token")) return "<email>";

// 密钥脱敏
const key = match.split(/[:=]/)[0]?.trim();
return key && key.length < match.length ? `${key}=<redacted>` : "<secret>";

资料来源:src/util.ts

二进制文件检测

索引器自动跳过二进制文件以避免处理错误:

export function isLikelyBinary(buffer: Buffer): boolean {
  const sample = buffer.subarray(0, Math.min(buffer.length, 4096));
  return sample.includes(0);
}

故障排除

问题可能原因解决方案
索引失败工作区路径不存在或无权限检查 --workspace 参数,确保路径可访问
查询无结果文件未被索引确认已运行 cxf index,检查文件类型是否支持
服务器连接失败端口占用或权限问题使用 stdio 模式,确认客户端配置正确
报告生成错误数据库损坏删除 .contextful 目录后重新索引

扩展阅读

资料来源:[README.md]()

失败模式与踩坑日记

保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。

medium 可能修改宿主 AI 配置

安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。

medium 能力判断依赖假设

假设不成立时,用户拿不到承诺的能力。

medium 维护活跃度未知

新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。

medium 下游验证发现风险项

下游已经要求复核,不能在页面中弱化。

Pitfall Log / 踩坑日志

项目:Inferensys/contextful

摘要:发现 7 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:配置坑 - 可能修改宿主 AI 配置。

1. 配置坑 · 可能修改宿主 AI 配置

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:项目面向 Claude/Cursor/Codex/Gemini/OpenCode 等宿主,或安装命令涉及用户配置目录。
  • 对用户的影响:安装可能改变本机 AI 工具行为,用户需要知道写入位置和回滚方法。
  • 建议检查:列出会写入的配置文件、目录和卸载/回滚步骤。
  • 防护动作:涉及宿主配置目录时必须给回滚路径,不能只给安装命令。
  • 证据:capability.host_targets | github_repo:1240001007 | https://github.com/Inferensys/contextful | host_targets=claude, claude_code

2. 能力坑 · 能力判断依赖假设

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:README/documentation is current enough for a first validation pass.
  • 对用户的影响:假设不成立时,用户拿不到承诺的能力。
  • 建议检查:将假设转成下游验证清单。
  • 防护动作:假设必须转成验证项;没有验证结果前不能写成事实。
  • 证据:capability.assumptions | github_repo:1240001007 | https://github.com/Inferensys/contextful | README/documentation is current enough for a first validation pass.

3. 维护坑 · 维护活跃度未知

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:未记录 last_activity_observed。
  • 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
  • 建议检查:补 GitHub 最近 commit、release、issue/PR 响应信号。
  • 防护动作:维护活跃度未知时,推荐强度不能标为高信任。
  • 证据:evidence.maintainer_signals | github_repo:1240001007 | https://github.com/Inferensys/contextful | last_activity_observed missing

4. 安全/权限坑 · 下游验证发现风险项

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:no_demo
  • 对用户的影响:下游已经要求复核,不能在页面中弱化。
  • 建议检查:进入安全/权限治理复核队列。
  • 防护动作:下游风险存在时必须保持 review/recommendation 降级。
  • 证据:downstream_validation.risk_items | github_repo:1240001007 | https://github.com/Inferensys/contextful | no_demo; severity=medium

5. 安全/权限坑 · 存在评分风险

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:no_demo
  • 对用户的影响:风险会影响是否适合普通用户安装。
  • 建议检查:把风险写入边界卡,并确认是否需要人工复核。
  • 防护动作:评分风险必须进入边界卡,不能只作为内部分数。
  • 证据:risks.scoring_risks | github_repo:1240001007 | https://github.com/Inferensys/contextful | no_demo; severity=medium

6. 维护坑 · issue/PR 响应质量未知

  • 严重度:low
  • 证据强度:source_linked
  • 发现:issue_or_pr_quality=unknown。
  • 对用户的影响:用户无法判断遇到问题后是否有人维护。
  • 建议检查:抽样最近 issue/PR,判断是否长期无人处理。
  • 防护动作:issue/PR 响应未知时,必须提示维护风险。
  • 证据:evidence.maintainer_signals | github_repo:1240001007 | https://github.com/Inferensys/contextful | issue_or_pr_quality=unknown

7. 维护坑 · 发布节奏不明确

  • 严重度:low
  • 证据强度:source_linked
  • 发现:release_recency=unknown。
  • 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
  • 建议检查:确认最近 release/tag 和 README 安装命令是否一致。
  • 防护动作:发布节奏未知或过期时,安装说明必须标注可能漂移。
  • 证据:evidence.maintainer_signals | github_repo:1240001007 | https://github.com/Inferensys/contextful | release_recency=unknown

来源:Doramagic 发现、验证与编译记录