npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@easbot/memory

v0.3.23

Published

Memory management library for EASBOT ecosystem - 智能记忆管理库,支持混合搜索、中英文分词、增量索引

Readme

@easbot/memory

English | 中文

EASBOT 生态系统的长期记忆管理库(v0.4.0)。提供分层记忆、KG scope 三档隔离、9 op 统一调度、混合搜索与可观测治理。

特性(v0.4.0)

  • 10 op 统一入口(ADR 0069 +1 sync):recall / remember / forget / extract / consolidate / sync / graph_query / status / doctor / init,MCP / CLI / Agent Tool 三端共享。
  • KG scope 三档隔离:每个节点带 owner_agent_idscope ∈ {agent_only, shared_only, both};MCP 默认 agent_only,trusted local 可 bothgraph_query / status / doctor / initagentIdoptional,缺省 fallback 'default'(ADR 0068 P0-A 反转)。
  • 分层记忆:短期 / 可写自记忆 / 历史长期记忆三层,混合搜索(FTS + 向量 + 图)。
  • 可观测性:10 op 全部走 Log.create({ service }) 英文结构化日志;status / doctor 提供离线诊断。
  • i18nzh-CN / en-US 双 locale;@easbot/memory API 日志保持英文,文案走 t()
  • 可移植:纯 TS 6.x;依赖 better-sqlite3(transitive via @easbot/database)+ @easbot/database(sync facade)+ @easbot/types / @easbot/utils(决策 0036 统一封装,禁止直接 require better-sqlite3 / @modelcontextprotocol/sdk)。
  • 三包统一后台支撑(决策 0036 / 0049 / 0051 / 0052):database 走 @easbot/database createSyncSqliteConnection;MCP 走 @easbot/mcp ToolRegistry + createAndStartStdioServer;CLI 输出走 @easbot/terminal printHuman + emitJsonOk + COMMANDS_HELP 单一数据源。

安装

pnpm add @easbot/memory

使用示例

9 op 入口

import { executeOp } from '@easbot/memory';

// v0.4.0 简化:不再有 `createMemorySystem` + `setOpSystem` 主类;
// 全部 op 走 `executeOp(name, args, ctx)` 统一入口(agentId 走 ctx 注入)。

// 1. recall
const recall = await executeOp<{ hits: unknown[] }>(
  'recall',
  {
    // 不再传 agentId 到 args 顶层 —— 走 ctx.agentId
    query: 'user preference',
    limit: 10,
    scope: 'agent_only',
    // dbPath / workspaceDir 走 ctx 或 service 配置;可省略
    dbPath: '/path/to/memory.db',
    workspaceDir: '/path/to/workspace',
    rootDir: '/path/to/workspace',
    locale: 'en-US',
    remote: false,
  },
  {
    agentId: 'agent-1',
    isTrustedLocal: true,
  },
);

// 2. remember
const saved = await executeOp<{ id: string }>(
  'remember',
  {
    content: 'prefers TypeScript',
    category: 'user_preference',
    importance: 9,
    dbPath: '/path/to/memory.db',
    workspaceDir: '/path/to/workspace',
    rootDir: '/path/to/workspace',
    locale: 'en-US',
    remote: false,
  },
  { agentId: 'agent-1', isTrustedLocal: true },
);

// 3. forget(按 category 全删)
await executeOp(
  'forget',
  {
    category: 'user_preference',
    maxDelete: 1000,
    dryRun: false,
    dbPath: '/path/to/memory.db',
    workspaceDir: '/path/to/workspace',
    rootDir: '/path/to/workspace',
    locale: 'en-US',
    remote: false,
  },
  { agentId: 'agent-1', isTrustedLocal: true },
);

KG scope 三档

// 只看本 Agent 节点(默认;MCP 入口强制)
await executeOp('graph_query', { agentId: 'agent-1', kind: 'nodes', scope: 'agent_only' }, { agentId: 'agent-1', isTrustedLocal: true });

// 只看共享节点
await executeOp('graph_query', { agentId: 'agent-1', kind: 'nodes', scope: 'shared_only' }, { agentId: 'agent-1', isTrustedLocal: true });

// 本 Agent + 共享(trusted local only;MCP 入口会拒绝)
await executeOp('graph_query', { agentId: 'agent-1', kind: 'nodes', scope: 'both' }, { agentId: 'agent-1', isTrustedLocal: true });

// v0.4.1+:不传 agentId → fallback 'default',全局 KG 视图(trusted local only)
await executeOp('graph_query', { kind: 'nodes', scope: 'both' }, { isTrustedLocal: true });

Markdown 渲染

import { renderOperationMarkdown } from '@easbot/memory';
const md = await renderOperationMarkdown('recall', recallResult, { toolName: 'memory_recall' });

9 op 清单

| op | trusted local only | agentId | 用途 | |---|---|---|---| | recall | ❌ | ✅ 必填 | 混合搜索(FTS + vector + graph) | | remember | ❌ | ✅ 必填 | 持久化一条 self-memory fact | | forget | ❌ | ✅ 必填 | 按 factId / category / 时间窗删除(支持 dryRun) | | extract | ❌ | ✅ 必填 | 从 session 抽取 facts | | consolidate | ✅ | ✅ 必填 | 整理 / 去重 / 摘要 | | sync | ✅ | ✅ 必填 | db → .md 兜底生成(幂等)+ active/ 过期文件归档(默认 30 天) | | graph_query | ❌ (scope=both 时 ✅) | ⚠️ optional,缺省 'default' | KG 节点 / 边 / 邻居查询 | | status | ❌ | ⚠️ optional,缺省全局聚合 | 系统状态快照 | | doctor | ✅ | ⚠️ optional,缺省全库扫描 | 数据完整性检查(支持 repair) | | init | ✅ | ⚠️ optional,缺省 'default' | 初始化 workspace(支持 force) |

P0-A 反转说明(v0.4.1 起):

graph_query / status / doctor / init 四个 op 的 agentId 改为 optional,缺省时 fallback 到固定值 'default',不再因缺失 agentId 抛错。这条决策与 ADR 0055 / 0056 / 0057 中"agent scope 必填"的早期语义相反,目的是让 CLI / 状态查询 / 一次性诊断场景可以无 agent 上下文运行。

  • graph_query 不传 agentId → 全局 KG 视图(scope 仍由调用方决定,trusted local 默认 'both'
  • status 不传 agentId → 跨 agent 聚合统计(不再是单一 agent 视图)
  • doctor / init 不传 agentId → 全局默认 agent = 'default',与 status / graph_query 口径一致

API 分类

services(9 op 业务层)

import { recall, remember, forget } from '@easbot/memory/services';

operations(9 op 注册表 + executeOp)

import { executeOp, OP_REGISTRY, ALL_OPS } from '@easbot/memory/operations';

format(schema + markdown + text + truncate + render)

import { renderOperationMarkdown } from '@easbot/memory/format/render';

hooks(4 hook 类型)

import type { PreCompactHook, SessionStartHook, SessionEndHook, PostToolFailureHook } from '@easbot/memory/hooks';

CLI / MCP 双入口(v0.4 stage 4 落地)

独立 CLI(easbot-memory

# 安装后即可用(package.json bin: easbot-memory)
easbot-memory init --workspace-dir <dir> [--agent <id>]
easbot-memory status [--agent <id>] [--json]
easbot-memory doctor [--repair] [--agent <id>]
easbot-memory recall --query <q> --agent <id> [--limit <n>] [--json]
easbot-memory remember --content <text> --category <c> --importance <1-10> --agent <id>
easbot-memory forget --agent <id> [--fact-id <id>] [--dry-run]
easbot-memory extract --session <sessionId> [--last-n <n>] --agent <id>
easbot-memory consolidate --agent <id> [--window-days <n>]
easbot-memory sync --agent <id> [--window-days <n>] [--dry-run] [--json]
easbot-memory graph --kind <nodes|edges|neighbors> [--query <q>] [--agent <id>]
easbot-memory config [--json]
easbot-memory mcp

Status / Doctor 统一输出格式(决策 0073 / CLI 规范 v1.4)

memory status / memory doctorcodebase / note 三包统一走 @easbot/terminalformatKnowledgeStatus / formatKnowledgeDoctor 渲染,视觉与字段结构完全一致。

status 输出示例

$ easbot memory status
─ memory status ───────────────────────────────────────────────────
  Root directory    E:/work/my-project
  Config            ✓ E:/work/my-project/.easbot/memory.json
  DB                ✓ E:/work/my-project/.easbot/db/memory.db (5242880 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    ✗
  Counts:
    facts           256
    agent_only      180
    shared_only     42
    both            34
  Healthy           ✓

doctor 输出示例

$ easbot memory doctor
─ memory doctor ───────────────────────────────────────────────────
  Healthy           ✓
  Duration          98 ms
  Backend availability:
    - better-sqlite3                ✓
    - node:sqlite                   ✗
    - @tursodatabase/database       ✗
  DB stats:
    page_count                      320
    page_size                       4096
    freelist_count                  0
  Checks            10 total (0 error, 0 warn, 1 info, 9 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]    ✓ embedding_cache_unused: no 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,各显示模型名或 ✗ | | Vector enabled | 向量索引是否启用 | | Embedding dims | 实测 embedding 维度(非仅读 config),status 末尾探测并回填 meta 表 | | embedding_dims_consistency | doctor 第 9 项检查:对比 meta / probe / config 三方维度是否一致 | | factsByCategory | memory 独有:按 category 统计的 fact 数量(Counts 段展示) |

JSON 输出(--json

$ easbot memory 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": false },
      "embeddingModel": "text-embedding-3-small",
      "graphModel": "gpt-4o-mini",
      "providerId": "openai"
    },
    "counts": { "facts": 256, "agent_only": 180, "shared_only": 42, "both": 34 },
    "healthy": true
  },
  "meta": { "scope": "all" }
}

兼容 CLI 输出规范 v1.4 / 决策 0040

v0.4.1 起:init / status / doctor / graph--agent 为可选,缺省时 fallback 到 'default'(CLI / 一次性诊断场景无需 agent 上下文);其余 6 op(recall / remember / forget / extract / consolidate / sync)仍要求显式 --agent,缺失时返回非 0 退出码。

Agent 委派模式(v0.4 stage 4 T-M017a)

# @easbot/agent 的 memory 子命令直接委派 handleMemoryCli(决策 0049)
easbot memory recall --query "user preference"
easbot memory remember --content "prefers TypeScript"
easbot memory mcp  # 启动 MCP stdio server

MCP stdio server(v0.4 stage 4 T-M013abc)

import { MemoryStdioServer } from '@easbot/memory';

// 启动 9 tool 的 MCP stdio server(Cline / Claude Code / Continue 可调用)
// v0.4.0:start 签名简化(不需要 `memorySystem` 参数,handler 走 executeOp 调度 services)
await MemoryStdioServer.start({
  name: 'easbot-memory',
  version: '0.4.0',
  description: 'EASBot memory MCP server',
});

// 列出 10 个 tool 名(ADR 0069 +1 sync)
const tools = MemoryStdioServer.getToolNames();
// ['memory_recall', 'memory_remember', 'memory_forget', 'memory_extract', 'memory_consolidate', 'memory_sync', 'memory_graph_query', 'memory_status', 'memory_doctor', 'memory_init']

10 tool 清单(与 OP_REGISTRY 一一对应):

  • memory_recall / memory_remember / memory_forget / memory_extract / memory_consolidate / memory_sync / memory_graph_query / memory_status / memory_doctor / memory_init

handleMemoryCli 委派范式

import { handleMemoryCli, setGlobalAdapter, setInstanceAdapter } from '@easbot/memory';

// 1. 注入 adapter(cli 路径 / agent 路径)
setGlobalAdapter({ Path: { /* ... */ } });
setInstanceAdapter({ directory: process.cwd(), worktree: process.cwd() });

// 2. 委派给统一 handler
const result = await handleMemoryCli(['recall', '--query', 'test'], {
  version: '0.4.0',
  cwd: process.cwd(),
});

if (result.code !== 0) process.exit(result.code);

fact → .md 文档同步(v0.5+ ADR 0060)

remember op 在事务提交后会best-effort地将 fact 渲染为 Markdown 文件,便于:

  • debug:开发者直接看磁盘上的「人类可读副本」
  • 二次开发:未来 note 工具可通过 file watcher 检测 memory .md 变化触发 cross-reference 更新
  • 灾备:file 失败不阻塞 db 写入(与 v0.3 行为一致)

路径格式(v0.5.1+ 反馈修正)

{workspaceDir}/.easbot/memory/active/{category}/{YYYY-MM-DD}.md
  • category 分目录(task_context / workflow / user_preference / ...)
  • createdAt 本地日期分文件(一日一文件,append 模式,多 fact 共享)
  • 文件名 = {YYYY-MM-DD}.md(不再含 fact.id)
  • memory_facts.file_path 列存相对 workspaceDir 的 POSIX 路径
  • 归档路径(ADR 0069 sync):{workspaceDir}/.easbot/memory/archive/{YYYY-MM}/{category}/{YYYY-MM-DD}.md(扁平结构)

Markdown 模板

---
id: mem_xxx
agent_id: easbot-xxx
category: task_context
importance: 7
created_at: 2026-08-22T22:00:00Z
updated_at: 2026-08-22T22:00:00Z
tags: [tag1, tag2]
---

# fact 内容(一行一个)

**category**: task_context | **importance**: 7/10 | **source**: session_self_write

编程式调用(高级)

大多数场景不需要直接调 —— 走 executeOp('remember' / 'forget') 即可。需要精细控制时(如批量迁移 / 自定义路径策略):

import { factFileSync } from '@easbot/memory/services';

// 1. 计算路径(不写文件)
const absPath = factFileSync.resolvePath(fact, '/path/to/workspace');

// 2. 渲染 Markdown 字符串(不写文件)
const md = factFileSync.renderMarkdown(fact);

// 3. 写文件(best-effort;失败返回 ok=false + log.warn)
const { ok, relPath, absPath } = await factFileSync.write(fact, '/path/to/workspace');

// 4. 删文件(按 fact.filePath;不存在返回 ok=true,idempotent)
const { ok, absPath } = await factFileSync.delete(fact, '/path/to/workspace');

策略与限制

  • best-effort:写/删文件失败 → log.warn + 返回 ok=false不抛错,不阻塞主流程
  • 单进程假设:未实现跨进程文件锁(与 v0.3 一致)
  • 不做 stale orphan 清理:forget 删 db 后删文件;如 db 删成功文件删失败 → 留 stale .md(doctor 第 9 项「orphan file 检测」后续增强)

详见 docs/decisions/0060-memory-fact-file-sync-restore.md

数据库位置

默认存储位置:$XDG_DATA_HOME/easbot/memory.db

  • Linux: ~/.local/share/easbot/memory.db
  • macOS: ~/Library/Application Support/easbot/memory.db
  • Windows: %APPDATA%/easbot/memory.db

决策与迁移

  • ADR 0069(v0.5+ memory sync op:两阶段流水线 —— db → .md 兜底生成(幂等)+ active/ 过期归档):docs/decisions/0069-memory-sync-op.md
  • ADR 0068(v0.4.1 P0-A 反转:graph_query / status / doctor / init 的 agentId 改为 optional,缺省 fallback 'default'):docs/decisions/0068-p0a-agent-id-optional.md
  • ADR 0060(v0.5+ fact → .md 同步恢复):docs/decisions/0060-memory-fact-file-sync-restore.md
  • ADR 0055 / 0056 / 0057(v0.4 决策):.easbot/protocol.jsondocs/decisions/00NN-*.md
  • 迁移脚本:scripts/migrate/{scan,apply,review}.ts + scripts/db-backup.ts(v0.3 → v0.4 owner_agent_id 列添加 + 默认 scope = agent_only)
  • CI guard(v0.4 stage 5 三包统一后台支撑):
    • scripts/check-database-facade.sh(禁止直接 require better-sqlite3 / node:sqlite / createRequire)
    • scripts/check-mcp-facade.sh(禁止直接 import @modelcontextprotocol/sdk)
    • scripts/check-terminal-facade.sh(CLI 输出走 @easbot/terminal + COMMANDS_HELP 单一数据源)
    • scripts/check-cmd-i18n-coverage.sh(zh-CN / en-US 双 locale 一致性 + switch-case 路由校验)
  • L-M13 / L-M14 / L-M15 教训沉淀:.easbot/knowledge/tasks/memory-v04-refactor/findings.md

开发

# 安装
pnpm install

# 构建
pnpm build

# 测试(vitest 4)
pnpm test:run

# 类型检查
pnpm type-check

# lint(biome 2.x)
pnpm biome-lint

许可证

MIT