Open Point
AI 原生知识点引擎:把长文档解构为原子知识点(Point),以纯 Markdown 存储,通过 CLI 与 MCP 供 AI Agent 直接消费。
设计规格见 docs/superpowers/specs/2026-09-07-open-point-design.md。
安装与构建
npm install
npm run build
npm link # 可选,注册 openpoint 命令
要求 Node.js 22+。
快速开始
mkdir my-kb && cd my-kb
openpoint init
openpoint deconstruct some-doc.md --dry-run # 人工评审候选点
openpoint deconstruct some-doc.md # 正式落盘(原文先存 raw/)
openpoint lint # 9 条健康检查
openpoint query "mcp" # 关键词搜索(中英文均可)
openpoint show point-20260908-mcp-intro # 查看一个点
openpoint review # 待复核列表
openpoint review point-20260908-mcp-intro --set verified # 复核结论:draft | verified
openpoint graph point-20260908-mcp-intro # 依赖树
openpoint skill "mcp" -o SKILL.md # 组装按依赖排序的知识包
解构:两阶段管线
deconstruct 先判定、再生成,只为真正值得沉淀的段落付费:
- 决策 — 按
##/###切段,逐段回答四个问题:是否成点 / 类型 / 可信度档位 / 是否与既有点重复。未确认的段落直接跳过。 - 生成 — 只把确认段落交给生成模型产出 Point,要求标注来源段号(
segmentIndex)并尽量附带evidence(来源原文的逐字摘句)。
生成之后由宿主做两道本地校验:
- 证据逐字校验 — 模型摘句必须是所在段落原文的逐字子串:通过记
model;不通过打evidence-unverified并降pending-review;模型未给摘句时宿主机械截取该段最长句子(记host,天然是逐字子串)。 - 冲突检测 — 归一化标题相同或标签 Jaccard ≥ 0.5 → 新点降
pending-review。
命中 冲突 / 重复 / 低可信度 / 证据未校验 任一原因即降 pending-review;仅类型分歧(type-mismatch)不降级。
复核闭环:openpoint review 列出待复核点,openpoint review <id> --set draft|verified 给出结论并回写 frontmatter(confidence + updated)。
每次运行(含 --dry-run 与失败)都写审计目录 runs/<YYYYMMDD-HHmmss>/:
| 文件 | 内容 |
|---|---|
manifest.json |
来源文件与 sha256、选项(dry-run / 决策后端 / 模型)、计数、状态与错误 |
decisions.jsonl |
逐段决策日志(确认 / 类型 / 低可信度 / 重复) |
points.jsonl |
逐点日志(id / 段号 / 类型 / 置信度 / 证据来源 / 降级原因) |
幂等:同一内容重复 deconstruct 会直接跳过(不调模型、不写盘),只记一条带 skipped 的空审计;--force 强制重跑并复用 raw/ 既有副本。内容变更则照常处理,raw 副本按重名追加 -2。
runs/ 与 .openpoint/ 由 init 写入 .gitignore;需要留档可自行移除该行。
环境变量
生成模型(解构必需)
| 环境变量 | 说明 |
|---|---|
OPENPOINT_BASE_URL |
OpenAI 兼容端点,如 https://dashscope.aliyuncs.com/compatible-mode/v1 |
OPENPOINT_API_KEY |
API Key |
OPENPOINT_MODEL |
模型名,如 qwen-max |
决策后端(可选,默认复用上面三项)
| 环境变量 | 默认 | 说明 |
|---|---|---|
OPENPOINT_DECISION_BACKEND |
llm |
llm = OpenAI 兼容接口;jev = Jev decisions API |
OPENPOINT_JEV_BASE_URL |
https://openrouter.ai/api |
仅 jev 后端 |
OPENPOINT_JEV_API_KEY |
回退 OPENPOINT_API_KEY |
仅 jev 后端 |
OPENPOINT_JEV_MODEL |
typesafe/jev-1.13 |
仅 jev 后端 |
MCP 接入(给 Agent 用)
{
"mcpServers": {
"open-point": { "command": "openpoint", "args": ["mcp"], "cwd": "/path/to/my-kb" }
}
}
4 个 tool:
search_points— 关键词搜索,精简列表get_point— 完整点 + 邻居get_dependencies— depends-on 闭包,拓扑序,自带执行顺序list_pending_reviews— 待人工复核的点(含证据未校验、冲突、低可信度)
Web UI
openpoint serve --root /path/to/my-kb --port 4321
# 可选:--host(默认 127.0.0.1,仅本机可见)、--token(为 /api 与 /mcp 开启 Bearer 鉴权)
浏览器打开 http://localhost:4321,三个场景都在同一个界面里:
| 场景 | 入口 |
|---|---|
| 人类阅读 | #/browse 搜索/过滤、#/point/<id> 全文与邻接、#/graph 依赖图(SVG,可拖拽缩放) |
| 驱动本地能力 | #/reviews 预览 diff → 确认复核;#/deconstruct 异步解构(默认 dry-run,1s 轮询日志);#/skill 预览 → 确认生成知识包 |
| 使用 MCP | #/mcp 调试台直连本服务的 /mcp;外部 agent 则连 Streamable HTTP 端点 |
给 agent 配置 HTTP 版 MCP(与 stdio 共用同一份 tool 实现):
{
"mcpServers": {
"open-point": { "url": "http://127.0.0.1:4321/mcp" }
}
}
安全模型(详见 docs/web-ui.md):
- 默认只绑
127.0.0.1;换--host绑非回环地址且未给--token时会打印醒目警告。 - 所有写操作走 预览 → 确认(一次性令牌,300s 过期);预览与确认之间文件被改动会返回 409。
skill的输出路径沙箱在库 root 内,拒绝..与绝对路径;服务端从不调用skillCommand的任意路径写入。- 不发 CORS 头、写操作要求
content-type: application/json并校验 Origin/Host —— 本地网页无法伪造这些请求。 - 请求体一律 zod 校验,1 MB 上限;
--token开启后/api与/mcp都要带Authorization: Bearer。
人类视图
直接用 Obsidian 打开 points/ 目录:每个点是带 frontmatter 的 Markdown 文件,edges 即双链。
开发
npm test # vitest
npm run typecheck
npm run build