Skip to content

Repository files navigation

Mebular 分布式记忆网络

Mebular

面向 Agent 的分布式图记忆网络

Mebular 把记忆存成一张带签名事件的知识图谱,每条事实都记得自己什么时候有效、由谁写入。设备之间用向量时钟做增量同步,离线也能用,重连后自动收敛,改过什么都能查。

Website GitHub

License: MIT Node.js TypeScript Tests Coverage

官网 · 快速上手 · 系统架构 · 项目状态 · 贡献


为什么需要 Mebular?

Agent 的记忆大多还躺在单个进程里:一个列表或键值存储,换台设备就断了,被谁改过也说不清,离线直接罢工。具体来说有四个问题。

问题 现在的做法 Mebular 的做法
记忆是扁平队列 用列表或键值对存,没有实体和关系 图式记忆模型:Entity / Fact / Episode / Skill / Meta 五类节点,事实带 validFrom / validTo 有效期
写入不可验证 没有签名、没有内容寻址,也认不出作者 每次写入生成一条 Ed25519 签名、Blake3 寻址的事件,改了什么、谁改的都能查
同步依赖中心服务 必须在线,还要信任中间商 向量时钟做增量同步,冲突按「删除优先 > 时间窗 > LWW」裁决,离线可用
生态各自为政 Hermes、mem0、Zep、Graphiti 之间不互通 CMF v1 交换格式加适配器,Obsidian、日志型端、json-memo 都能接

除这四点之外,还带了 X25519 + AES-256-GCM 的加密信道、可用用户主密钥静态加密落盘(HKDF 派生 + AES-256-GCM,落盘密文、内存明文)、可选本地 embedding 语义召回(默认多语言 MiniLM,覆盖中文;缺包自动降级关键词并告警;真实模型能力由独立 CI job semantic-realnpm run verify:semantic:real 验证)、Hermes 的七方法 Provider 和幂等导入、可选的 libp2p 真实网络(含 circuit relay v2 跨网段寻址与手动 multiaddr 降级)、可切换的存储后端(JSONL 或 Node 内建 SQLite,均复用静态加密)与大图初始同步快照,以及一套带覆盖率门槛的测试。


30 秒上手

还没发 npm 包,先从源码构建。运行时只依赖 bonjourulid,libp2p 是可选的。

git clone https://github.com/Windsander/Mebular.git
cd Mebular
npm install
npm run build          # TypeScript strict → dist/
npm test               # 47 套件 / 359 用例全绿

最简例子(复制即跑)

首次初始化需要用户主密钥为本机签发设备证书。用 Mebular.generateUserMasterKey() 生成后,请自行持久化主私钥(信任根,示例见 examples/quickstart/index.mjs)。

import { Mebular, HermesMemoryProvider } from 'mebular';

const master = await Mebular.generateUserMasterKey();

const mebular = new Mebular({
  storagePath: './store.jsonl',
  deviceId: 'device-A',
  encryption: {
    userMasterKey: master.publicKey,
    userMasterPrivateKey: master.privateKey,
  },
  network: { enabled: false }, // 单设备先从这里开始
});

await mebular.initialize();
const provider = new HermesMemoryProvider(mebular);

await provider.storeMemory({
  type: 'preference',
  content: '深色主题',
  metadata: { preferenceType: 'theme', confidence: 0.9 },
});

const { memories } = await provider.retrieveMemory({ types: ['preference'] });
console.log(memories); // → [ { type: 'preference', content: '深色主题', ... } ]

await mebular.shutdown();

network.enabled 改成 true 并配置传输,同一段代码就能跑在两台设备上,断线重连后自己收敛。

上面这段的可执行版本在 examples/quickstart/index.mjs(含主密钥持久化),npm run build 之后直接 node examples/quickstart/index.mjs 即可:

npm run build
node examples/quickstart/index.mjs

examples/ 下另有 obsidian-vaultlog-journaljson-memo 三份带 README 的示例数据,供对应适配器导入,本身不是可执行脚本。


广域网同步(实验)

scripts/wan-sync.mjs 把「两主机增量同步 + 冲突收敛」脚本化,并接上 circuit relay 与手动 multiaddr 两条寻址路径。

# 本地编排自测(共享身份 + 两阶段 + relay 密文;non-evidence,退出码 0)
npm run verify:wan:cross:selftest
# 隔离自测:两个独立进程 + 各自独立存储 + 无共享路径(non-evidence)
npm run verify:wan:cross:selftest:isolated

# 本地回归(loopback,非证据)
npm run verify:wan         # 手动 multiaddr 直连
npm run verify:wan:relay   # 内嵌 circuit relay

# 跨机两阶段(异网段,无需共享文件系统):先分发用户主密钥,再 A=peer / B=cross
node scripts/wan-sync.mjs user-keygen --out key.json
node scripts/wan-sync.mjs relay --port 4000 --unlimited            # 可选,异网段需要
node scripts/wan-sync.mjs peer  --role a --user-master-key-file key.json \
  --bind /ip4/0.0.0.0/tcp/4001 --relay <relay>     # 固定地址+持久身份 → 地址稳定;打印 PEER_READY
node scripts/wan-sync.mjs cross --user-master-key-file key.json \
  --peer <A-stable-multiaddr> --peer-id <A-deviceId> --relay <relay> --out B-evidence.json
# 判定:cross 退出码 0 且 B-evidence.json 的 stateMatches=true、differentPublicNetwork=true、identityShared=true
  • 用户主密钥:user-keygen 生成,A/B 用同一把(否则设备证书互验失败);也可用 MEBULAR_USER_MASTER_KEY(内联 JSON)。
  • 协调无需共享文件:B 用 --peer/--peer-id 一次给定 A 的稳定地址,按图上阶段状态重试连接完成三阶段。
  • 前置预检:cross 启动前先检查 --peer/--peer-id/--relay 是否齐全且 TCP 可达;缺失/不可达立即报错并打印补齐指引,不跑到中途才失败(超时可用 MEBULAR_WAN_PREFLIGHT_TIMEOUT_MS 调整,默认 3000ms)。
  • 出口判据:MEBULAR_WAN_IP_ECHO(缺省 https://api.ipify.org?format=json)取公网出口 IP;任一私网/回环 → false,取不到 → 未知(绝不误判 true)。
  • relay 默认限额;需显式 --unlimitedLibp2pProvider.relayUnlimited)才允许任意协议过 circuit,调用方承担开放 relay 的滥用风险;relay --capture <path> 可捕获线上字节供「只见密文」取证。
  • 诚实边界:上述本机命令都是 non-evidence;真实 G3-E 需两台不同公网主机 + 可达 relay,当前未达成(阻塞报告 docs.design/g3r-blocker-2026-09-13.md)。npm run verify:wan:cross 无环境时退出码 1 并打印所需环境。

系统架构

Mebular 系统架构图

图分三层,层与层之间只靠接口耦合:

  • Hermes 侧只依赖 Provider 和 Importer 接口,不碰核心实现。
  • 核心层负责图存储、事件日志、同步和持久化,纯 TypeScript,不依赖网络。
  • P2P 层管握手、加密信道和传输抽象,可以换成 libp2p、InMemoryHub 或自己实现。

矢量源文件在 assets/architecture.svg,独立页面在 assets/architecture.html,克隆到本地直接打开就能看。


适用与取舍

Mebular 没走云端记忆 SaaS 那条路,也就有相应的代价。

更看重 代价
离线可用、数据自己拿着 不做 SaaS,节点要自己跑
写入可验证、抗篡改 每次写入多出签名和哈希的开销
图结构、能表达关系和时效 比扁平键值模型复杂,上手要花点时间
生态互通、方便迁移 功能还没成熟方案全

适合愿意自己管数据、要在多台设备或多端之间共享 Agent 记忆、也能接受早期项目的人。想开箱即用,或者要生产级 SLA 的,现在还不合适。


项目状态

Mebular 还在早期设计阶段。Phase 0 到 6 的功能都能用了,但 API 还没稳定,也没发 npm 包,放到生产环境前请自己评估。

里程碑 状态
核心引擎(图存储 / 加密身份 / 事件日志) 完成
P2P 网络(握手 / 信道 / NAT / 发现) 完成
图同步(增量同步 / 冲突收敛 / 离线恢复) 完成
Hermes 集成(门面 / Provider / 导入器) 完成
跨端互通(证书链 / CMF / 适配器 / 故障注入) 完成
质量收口、生态适配、广域网桥接 完成
静态加密、语义召回、真实广域网、SQLite 存储与快照同步 完成
信任模型 v2(证书吊销)、跨 NAT 实测回填 规划中

测试和质量方面:

项目 情况
测试 47 个套件、359 条用例全绿,覆盖单元、双设备端到端、四端互通和故障注入
覆盖率 行 90.3%、分支 77.1%,全库门槛 85/65,关键文件另有底线
类型检查 tsc --noEmit,strict 加 noUncheckedIndexedAccess,零错误
Lint ESLint(typescript-eslint)零告警
质量门禁 每个阶段跑 verify 脚本加构建产物冒烟,src 里不留裸的 throw new Error
分阶段验证脚本
# 每阶段:文件检查 + 编译 + 全量测试 + 实现点抽查 + 构建产物冒烟
node scripts/verify-phase6.mjs   # 质量收口 · 生态适配 · 广域网桥接
node scripts/verify-phase5.mjs   # 跨端互通
node scripts/verify-phase4.mjs   # Hermes 集成
node scripts/verify-phase3.mjs   # 图同步
node scripts/verify-phase2.mjs   # P2P 网络

文档导航

方向 入口
核心 API src/mebular.ts · src/types/
记忆模型和存储 src/memory/ · src/core/ · src/storage/
P2P 网络和同步 src/p2p/ · src/sync/ · src/eventlog/
CMF 交换和适配器 src/exchange/
Hermes 集成 src/hermes/
可运行示例 examples/
贡献指南 CONTRIBUTING.md

贡献

想参与就开个 Issue 先聊聊,再发 PR,具体约定见 CONTRIBUTING.md

觉得有用的话,点个 star。


官网 · GitHub · © 2026 Windsander · MIT License

About

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages