@easbot/note
v0.3.19
Published
Note Knowledge Base - 非结构化记忆和文档知识库管理系统,支持混合搜索(向量+FTS+图)和 LLM 驱动的知识摄取
Maintainers
Readme
English | 中文
@easbot/note
Note Knowledge Base - 文档知识库 + KG 节点图,支持混合搜索(FTS + 向量 + rerank)和 LLM 驱动的智能摄取
简介
@easbot/note 是 EASBot 生态的文档知识库模块(v0.4),提供非结构化文档(markdown / text / html / ast)的摄取、混合搜索、KG 节点关系推理与多模态 LLM 能力。
v0.4 架构变化:不再持有 v0.3 的 NoteKnowledge 主类 / IngestionPipeline / SearchEngine / GraphQueryInterface / DatabaseManager 这 5 个核心实体。所有能力下沉到 v0.4 service 层(services/*.ts)+ 9 op 注册表(NOTE_OPERATIONS);外部调用通过 executeNoteOp 三端统一派发(CLI / MCP / agent tool 共用)。
特性
- 混合搜索:FTS5 + 向量相似度 + 可选 LLM rerank(mode = conservative / balanced / tokenmax)
- KG 集成:文档摄取自动抽取 entities + relations,节点 / 边图查询(BFS + 子图)
- 多格式摄取:markdown / text / html / ast(PDF / DOCX 占位 stage 2)
- 状态监控:db stats / ingest queue / KG size 全方位
- 三端统一:
- 独立 CLI
easbot-note <command> - Agent CLI
easbot note <command> - MCP stdio server(暴露 9 个
note.<op>工具) - Agent tool 9 op(
note(operation='search' | 'ingest' | ...))
- 独立 CLI
安装
pnpm add @easbot/notev0.4 API
导出总览
// 9 op Operations 注册表(真源;CI guard 校验)
import { NOTE_OPERATIONS, findOperation, executeNoteOp } from '@easbot/note';
// CLI handler(@easbot/agent 复用 + 独立 CLI easbot-note)
import { handleNoteCli, renderBanner, COMMANDS_HELP } from '@easbot/note';
// MCP stdio server
import { NoteStdioServer, formatFailClosed, toMcpText, TOOL_NAMES } from '@easbot/note';
// Format renderer(service result → markdown)
import { renderOperationMarkdown } from '@easbot/note';
// Database facade(决策 0036)
import { NoteDatabaseManager, getNoteDbPath } from '@easbot/note';
// 工具
import { FileScanner, chunkText } from '@easbot/note';
import { Llm } from '@easbot/note';v0.4 不再导出:
NoteKnowledge/createNoteKnowledge/IngestionPipeline/SearchEngine/GraphQueryInterface/DatabaseManager(v0.3 实体全部随重构删除)。所有能力通过 9 op dispatch 走 service 层。
9 op(v0.4 stage 3-4 落地)
| op | scope | localOnly | 一句话 |
|---|---|---|---|
| note.search | read | no | 混合搜索(FTS + 向量 + rerank) |
| note.ingest | write | no | 摄入文档(md/text/html/ast) |
| note.extract | read | no | 抽取 chunk/document 的 KG 节点 + 关系 |
| note.remove | admin | yes | 删除文档 + 级联 KG |
| note.sync | admin | yes | 增量同步(async worker pool) |
| note.graph_query | read | no | KG 子图(nodes / edges / neighbors / path / explain) |
| note.status | read | no | 状态(db stats / ingest queue) |
| note.doctor | read | no | 健康检查(backend / FTS / parser) |
| note.init | admin | yes | 初始化 workspace |
localOnly op(remove / sync / init)由 executeNoteOp 集中 trust gate 拦截(ADR 0057),remote MCP caller 抛 TRUST_DENIED。
快速开始(程序化 API)
import { executeNoteOp } from '@easbot/note';
// 9 op dispatch(推荐入口;scope / localOnly 自动校验)
const result = await executeNoteOp('note.search', {
query: 'authentication flow',
mode: 'balanced',
maxResults: 10,
}, {
workspaceDir: process.cwd(),
rootDir: process.cwd(),
dbPath: '.easbot/note.db',
locale: 'zh-CN',
remote: false, // trusted local
});完整 service ctx 字段见 services/types.ts 的 NoteServiceContext。
MCP stdio server
# 启动 stdio MCP server(暴露 9 个 note tool)
easbot-note mcp
# 或从 agent CLI
easbot note mcpMCP tool 名:note.search / note.ingest / note.extract / note.remove / note.sync / note.graph_query / note.status / note.doctor / note.init
独立 CLI(easbot-note)
# lifecycle
easbot-note init [dir] [--force] [--skip-auto-sync]
easbot-note status [--dir <path>] [--json]
easbot-note doctor [--dir <path>] [--json]
# content
easbot-note search <query>... [--mode <conservative|balanced|tokenmax>] [--file <p>] [--kind <document|chunk|node>] [--max <n>] [--include-graph] [--rerank]
easbot-note ingest <path>... [--dir <path>] [--no-embed]
easbot-note extract <chunkId|documentId|path> [--dir <path>]
easbot-note remove <id|path> [--confirm] [--force]
easbot-note sync [--dir <path>] [--async] [--quiet]
# graph
easbot-note graph <nodeId> [--kind <nodes|edges|neighbors>] [--depth <n>] [--direction <incoming|outgoing|both>]
# external
easbot-note config <get|set> [key] [value]
easbot-note mcpStatus / Doctor 统一输出格式(决策 0073 / CLI 规范 v1.4)
note status / note doctor 与 codebase / memory 三包统一走 @easbot/terminal 的 formatKnowledgeStatus / formatKnowledgeDoctor 渲染,视觉与字段结构完全一致。
status 输出示例
$ easbot note status
─ note status ──────────────────────────────────────────────────────
Root directory E:/work/my-project
Config ✓ E:/work/my-project/.easbot/note.json
DB ✓ E:/work/my-project/.easbot/db/note.db (8388608 bytes)
Index state ready
Schema version 1
Extraction version 1
Backend better-sqlite3
Last sync 2026-08-31T14:23:11.000Z
Vector enabled ✓
Embedding dims 1536
LLM:
Initialized ✓
Provider openai
Capabilities:
Embedding ✓ text-embedding-3-small
Graph LLM ✓ gpt-4o-mini
Rerank LLM ✓ cohere-rerank-v3.5
Counts:
documents 42
chunks 156
nodes 389
edges 1024
Healthy ✓doctor 输出示例
$ easbot note doctor
─ note doctor ──────────────────────────────────────────────────────
Healthy ✓
Duration 145 ms
Backend availability:
- better-sqlite3 ✓
- node:sqlite ✗
- @tursodatabase/database ✗
DB stats:
page_count 512
page_size 4096
freelist_count 0
Checks 12 total (0 error, 1 warn, 1 info, 10 ok)
[ok] ✓ database: database file exists and accessible (12 ms)
[ok] ✓ fts: FTS5 available (8 ms)
[ok] ✓ vector: vector index usable (23 ms)
[ok] ✓ schema: schema version matches (2 ms)
[ok] ✓ lock: no lock contention (1 ms)
[ok] ✓ disk_space: sufficient (156 MB free) (3 ms)
[ok] ✓ orphan: no orphan records (18 ms)
[info] ℹ llm: LLM reachable (ping 42 ms) (42 ms)
[ok] ✓ chunks_fts_sync: FTS and chunks in sync (15 ms)
[ok] ✓ kg_node_types_consistency: node types match schema (21 ms)
[warn] ⚠ embedding_cache_unused: 12 unused embedding cache entries (5 ms)
[ok] ✓ embedding_dims_consistency: meta=1536 probe=1536 config=1536 (35 ms)关键字段说明
| 字段 | 说明 |
|------|------|
| LLM.initialized | LLM 是否已初始化(配置有效且可达) |
| LLM.capabilities | 三大能力:embedding / graphLlm / rerankLlm,各显示模型名或 ✗;note 独有 rerankLlm |
| Vector enabled | 向量索引是否启用 |
| Embedding dims | 实测 embedding 维度(非仅读 config),status 末尾探测并回填 meta 表 |
| embedding_dims_consistency | doctor 第 9 项检查:对比 meta / probe / config 三方维度是否一致 |
| rerankAvailable | note 独有:rerank 是否可用(LLM capabilities 中体现) |
JSON 输出(--json)
$ easbot note status --json
{
"ok": true,
"data": {
"rootDir": "E:/work/my-project",
"configExists": true,
"dbExists": true,
"indexState": "ready",
"schemaVersion": 1,
"llm": {
"initialized": true,
"capabilities": { "embedding": true, "graphLlm": true, "rerankLlm": true },
"embeddingModel": "text-embedding-3-small",
"graphModel": "gpt-4o-mini",
"rerankModel": "cohere-rerank-v3.5",
"providerId": "openai"
},
"counts": { "documents": 42, "chunks": 156, "nodes": 389, "edges": 1024 },
"healthy": true
},
"meta": { "scope": "all" }
}兼容 CLI 输出规范 v1.4 / 决策 0040。
Agent CLI(easbot note)
# 复用同一组 cmd
easbot note search "user authentication" --mode tokenmax
easbot note ingest ./docs/spec.md
easbot note extract --path docs/spec.md
easbot note status --json
easbot note mcpAgent tool 9 op
// LLM 调用(zod discriminated union)
note(operation='search', query='auth flow', mode='tokenmax', maxResults=10)
note(operation='ingest', path='./spec.md')
note(operation='extract', chunkId=42, documentId=1, path='./spec.md')
note(operation='remove', id='doc-123', confirm=true)
note(operation='sync', async=true, quiet=true)
note(operation='graph_query', nodeId='42', kind='neighbors', depth=2, direction='both')
note(operation='status')
note(operation='doctor', repair=true)
note(operation='init', dir='.', force=false, skipAutoSync=false)数据结构
| 类型 | 字段 | 用途 |
|---|---|---|
| Document | id / path / title / metadata | 文档元数据 |
| Chunk | id / documentId / content / startLine / endLine / nodeIds | 文档切片 |
| Node | id / name / type / properties | KG 节点 |
| Edge | id / source / target / relation / properties | KG 边 |
| SearchHit | chunkId / documentId / documentPath / score / snippet / source / nodes? | 搜索结果 |
| IngestResult | documentId / path / chunksCreated / vectorsCreated / durationMs / warnings | 摄入结果 |
| ExtractResult | entities / relations / documentId? / chunkId? / durationMs | 抽取结果 |
| SyncResult | filesAdded / filesUpdated / filesDeleted / filesSkipped / durationsMs / errors | 同步结果 |
| StatusResult | indexState / schemaVersion / documentsCount / chunksCount / nodesCount / edgesCount / ftsAvailable | 状态 |
| DoctorResult | healthy / checks[] / totalChecks | 健康检查 |
错误码(ADR 0057 LLM-friendly)
| code | 含义 |
|---|---|
| NOT_FOUND | 资源未找到 |
| AMBIGUOUS | 名称歧义 |
| INTERNAL | 内部错误 |
| NOT_INDEXED | 未索引 |
| OPTIONAL_DEP_MISSING | 可选依赖未装 |
| PATH_TRAVERSAL | 路径越界 |
| TRUST_DENIED | 不受信 caller |
| INGEST_FAILED | 摄入失败 |
| UNSUPPORTED_FORMAT | 不支持的文件格式 |
| CONTENT_REQUIRED | 缺必填参数 |
remote MCP caller 仅返 code(防 stack / SQL / 路径泄漏);trusted local 返 code + message。
开发
# 安装依赖
pnpm install
# 构建(dev / prod 两种)
pnpm --filter @easbot/note dev
pnpm --filter @easbot/note build
# 测试(Vitest 4)
pnpm --filter @easbot/note test:run
npx vitest run packages/note/src/mcp/__tests__/stdio-server.test.ts
# 类型检查 + Biome
pnpm --filter @easbot/note type-check
pnpm --filter @easbot/note lint
pnpm --filter @easbot/note format
# CI guards
bash ./scripts/check-no-process-cwd.sh note
bash ./scripts/check-localOnly-assert.sh note
bash ./scripts/check-service-handler-coverage.sh note许可证
MIT
2026-09-04 00:33:47 [force re-ingest test] (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') + ' [force re-ingest verify v0.7]' (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') + ' [force re-ingest v2]' (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') (Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
