@esankhan3/anvil-knowledge-core

中文文档
0.4.13发布于 2026/11/13MITTypeScriptES Module构建来源已验证近 30 天下载 2182

Shared knowledge stack (chunking, AST, embedders, vector store, hybrid retrieval) for cli + code-search-mcp.

原始使用文档
文档目录17 节
  1. The problem with grep + embeddings
  2. What you get
  3. AST-aware chunking
  4. Incremental by default
  5. Hybrid retrieval, four phases
  6. Six embedding providers, four rerankers
  7. Explicit config + env-override
  8. Vector-space safety
  9. Project graph
  10. Cross-repo edge detection
  11. LLM-driven where it matters
  12. Structural hashing
  13. Architecture at a glance
  14. Storage layout
  15. Philosophy
  16. Status
  17. Part of Anvil — the AI development pipeline.

@anvil/knowledge-core

Your codebase, retrievable.

A code-aware knowledge stack — AST-level chunking, hybrid retrieval, project graphs, and cross-repo edge detection. Built so agents see the whole codebase, not just the file you happened to open.


The problem with grep + embeddings

Code search works one of two ways: lexical (grep, fast, dumb) or embedding-based (vector DB, slow on edits, blind to structure). Both miss the same thing: code has graph structure. A function isn't just a chunk of text — it imports things, gets called by things, implements things, lives in a package, talks to other repos.

knowledge-core treats the codebase like a graph and a corpus at the same time. Tree-sitter parses every supported language into AST chunks. A vector store + BM25 + a project graph all answer the same query, fused into one ranked list. The retriever knows when you're asking about an identifier vs an error code vs a natural- language question and weights the signals accordingly.

import {
  indexFromPath,
  getRetriever,
  loadKnowledgeConfig,
} from '@esankhan3/anvil-knowledge-core';

// Build a fully-resolved KnowledgeConfig: YAML at
// ~/.anvil/projects/<project>/factory.yaml, overlaid by CODE_SEARCH_*
// env vars. Or hand-construct one — the indexer accepts any shape.
const config = loadKnowledgeConfig('space-tourism');

// Index once — incremental thereafter. Pass config explicitly so
// CODE_SEARCH_* env vars (provider, model, dims, API key, base URL)
// actually reach the embedder — pre-P1 they were silently ignored.
await indexFromPath('space-tourism', '/path/to/workspace', { config });

// Retrieve — vector + BM25 + 1-hop graph + cross-encoder rerank.
// Pass the same config so query-time embedder matches the index.
// getRetriever() also hard-errors on vector-space mismatch (P2) so
// silent provider drift is impossible.
const retriever = await getRetriever('space-tourism', config);
const result = await retriever.retrieve(
  'where do we validate booking seat tiers?',
);

console.log(result.chunks.length, 'chunks');     // ranked, deduped
console.log(result.graphContext);                // related symbols
console.log(result.totalTokens);                 // budgeted

What you get

AST-aware chunking

tree-sitter WASM parses TypeScript, JavaScript, TSX, Go, Python, Rust, Java, and PHP into proper function / class / method boundaries. No more chunks that cut a function in half. Regex fallback for languages without a grammar so nothing is unindexed.

Incremental by default

The indexer reads git rev-parse HEAD, diffs against the last indexed SHA, and re-chunks only what changed. Deleted files get removed from the vector store. Embedding is independently incremental — it diffs new chunk IDs against LanceDB and only embeds the deltas. Big repos stay fast forever.

Hybrid retrieval, four phases

  1. Vector ⫽ BM25 in parallel — semantic recall + lexical recall.
  2. Reciprocal Rank Fusion — combine without one dominating.
  3. AST tripartite expansion — pull in callers, callees, and type references via the project graph.
  4. Cross-encoder rerank — Qwen3-Reranker by default; Cohere / Voyage / OpenAI-compatible swappable.

The query classifier picks adaptive weights — identifiers lean BM25, natural-language leans vector, error codes lean both.

Six embedding providers, four rerankers

Embed: Codestral / Mistral · Voyage · OpenAI · Ollama · Gemini OAuth (auto-refreshes expired access tokens via refresh_token) · OpenAI-compatible / Custom · auto (picks based on what's configured). Rerank: Ollama (default qwen2.5-coder:7b — qwen3:0.6b was a silent no-op and was dropped) · Cohere · Voyage · OpenAI-compatible. Plug in whatever fits your cost/quality/latency curve.

Explicit config + env-override

KnowledgeConfig is the single contract. EmbeddingProviderConfig takes {provider, model?, dimensions?, apiKey?, baseUrl?, ollamaHost?}; RerankerProviderConfig takes {provider, model?, apiKey?, baseUrl?, timeoutMs?}. loadKnowledgeConfig(project) reads the project YAML then overlays CODE_SEARCH_* env vars (EMBEDDING_PROVIDER / _MODEL / _DIMENSIONS / _API_KEY / _BASE_URL / OLLAMA_HOST / RERANKER_PROVIDER / _MODEL / _API_KEY / _BASE_URL / RETRIEVAL_MAX_CHUNKS / _MAX_TOKENS / AUTO_INDEX). Provider classes still read documented vendor env vars (MISTRAL_API_KEY, OPENAI_API_KEY, ...) as a deprecated fallback — every first read emits a one-shot stderr warning; library env reads are removed in 1.0.

Vector-space safety

getRetriever(project, config?) reads each repo's index_meta.json on open. If the recorded embeddingProvider doesn't match the current config, it throws a hard error — never returns garbage vectors from a config drift. (Pre-P2, silent space mismatch was the canonical "results are useless and there's no error" bug.)

Project graph

A graphology directed multi-graph stitches every repo together. Nodes are entities (functions, classes, types, modules), edges are imports / calls / inheritance / contains / type-refs. Louvain community detection clusters semantically related code so retrieval can surface "the auth subsystem" rather than four scattered files.

Cross-repo edge detection

Fourteen strategies covering shared types, Kafka topics, HTTP endpoints, gRPC, databases, env vars, npm/workspace deps, k8s, docker-compose, proto definitions, Redis, S3, and shared constants. Plus an LLM-inferred semantic edge layer for the cases regex can't catch.

LLM-driven where it matters

Repo profiling (fingerprint files → LLM → typed RepoProfile, cached by fingerprint hash), semantic edge inference, project summary generation, RAG quality evaluation. All routed through @anvil/agent-core so the same router, retries, and cost ledger that power the agent stack power knowledge ingestion.

Structural hashing

computeStructuralHash canonicalizes source — strips comments, collapses whitespace, normalizes identifiers — and SHA-256s the result. Used for chunk dedup and shared with @anvil/memory-core so memory drift detection and chunk dedup speak the same language.


Architecture at a glance

   git repo(s)
       │
       ▼
   ┌─────────────────────────────────────────────────────────┐
   │  Indexing                                               │
   │   walk + git diff → tree-sitter chunks → AST graph      │
   │           │              │            │                 │
   │           ▼              ▼            ▼                 │
   │     LanceDB         BM25 (FTS)    project graph         │
   │     (vectors)                     + cross-repo edges    │
   └─────────────────────────────────────────────────────────┘
                                │
                                ▼
   ┌─────────────────────────────────────────────────────────┐
   │  HybridRetriever                                        │
   │   query classifier ─▶ adaptive weights                  │
   │   vector ⫽ BM25  →  RRF  →  AST expansion  →  rerank    │
   └─────────────────────────────────────────────────────────┘
                                │
                                ▼
                       ranked chunks + graph context

Two consumers, one stack: @esankhan3/anvil-cli indexes via anvil index and retrieves during pipelines; @esankhan3/code-search-mcp exposes the same retriever as MCP tools that any agent can call.


Storage layout

~/.anvil/knowledge-base/<project>/
  <repo>/chunks.ndjson           # the repo's chunks (consumed by embedder)
  deleted_files.json             # incremental embed cleanup
  system_graph_v2.json           # merged project graph
  PROJECT_GRAPH.json             # LLM-generated semantic graph
  PROJECT_SUMMARY.md             # human-readable companion
  lancedb/                       # vector store
  <repo>/
    profile.json                 # cached RepoProfile
    graph.json                   # per-repo AST graph
    GRAPH_REPORT.md              # quality report
    index_meta.json              # { lastIndexedSha, files, chunkCount }

Everything is on disk, inspectable, git-friendly where it makes sense (project graph + summary).


Philosophy

Chunks should follow code shape, not byte count. AST boundaries keep functions whole. Retrieval quality starts at the chunker.

No single retrieval signal is enough. Vector misses identifiers. BM25 misses paraphrases. Graph misses everything text-shaped. Hybrid + adaptive weighting is the only honest answer.

Incremental or nothing. Anvil indexes on every pipeline run. A full re-index isn't acceptable; the engine treats the previous SHA as a load-bearing input.

No vendor lock-in. LanceDB on disk. graphology in-process. Pluggable embedders + rerankers. Swap any layer without rewriting the rest.

Two surfaces, one engine. CLI users get retrieval through pipelines; MCP users get it through tool calls. The retrieval pipeline is the same code path.


Status

Stable: chunking, AST graph, hybrid retrieval, incremental indexing, six embedders, four rerankers, fourteen cross-repo strategies, project graph, structural hashing. In flight: richer graph queries and a deeper RAG-eval harness.


Part of Anvil — the AI development pipeline.

版本与发布记录

@esankhan3/anvil-knowledge-core 共发布 32 个版本,首次发布于 2026/05/05;过去 12 个月发布了 32 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.4.13latest2026/11/131 天前
0.4.122026/11/121 天前
0.4.112026/11/122 天前
0.4.102026/10/2520 天前
0.4.92026/10/2420 天前
0.4.82026/10/2420 天前

关于 @esankhan3/anvil-knowledge-core 的常见问题

@esankhan3/anvil-knowledge-core 是什么?

Shared knowledge stack (chunking, AST, embedders, vector store, hybrid retrieval) for cli + code-search-mcp.

如何安装 @esankhan3/anvil-knowledge-core?

在项目目录运行 npm install @esankhan3/anvil-knowledge-core,或使用 pnpm add / yarn add / bun add。

@esankhan3/anvil-knowledge-core 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@esankhan3/anvil-knowledge-core 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@esankhan3/anvil-knowledge-core 可以商用吗?

@esankhan3/anvil-knowledge-core 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@esankhan3/anvil-knowledge-core 的下载量有多少?

根据 npm 官方下载统计,@esankhan3/anvil-knowledge-core 在 2026/10/14 – 2026/11/12 这 30 天内被下载 2,182 次,日均约 73 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@esankhan3/anvil-knowledge-core 还在维护吗?

最新版本 0.4.13 发布于 2026/11/13(1 天前);至今共发布 32 个版本,其中过去 12 个月发布了 32 个;首次发布于 2026/05/05。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。