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

@tr1v3r/dsh-ltm

v0.3.1

Published

Structured long-term memory for DeepSeek Harness: CJK-aware tokenized search, hybrid rerank, dedupe, expiry review, and migration from dsh-memory — zero mandatory network

Downloads

2,043

Readme

dsh-ltm(中文说明)

本文件是 README.md 的中文对照说明;内容以英文版为准,两者同步更新。

面向 DeepSeek Harness(dsh)的结构化长期记忆插件: 本地 SQLite 存储 + 中文感知分词检索(CJK 二元分词 + FTS5)、BM25 与字符 n-gram 余弦混合重排、 近似重复检测、过期复核、以及从 dsh-memory 的一次性迁移 —— 零强制联网依赖。

为什么需要

  • [email protected] 是纯文本 + 默认分词器的 FTS5:中文检索基本不可用(整句变成单个 token)。
  • 长期记忆需要追加/检索之外的生命周期管理:结构化 scope 与 tags、重复检测、复核时间戳、有界召回。

安装到 profile

@tr1v3r/dsh-ltm 0.1.2 及以上可用一条命令安装并注册 bundle 配置:

dsh plugin --profile web add @tr1v3r/dsh-ltm

把 web 换成你的 profile 名(例如 dsh-tui),然后重启该 profile。bundle 会把数据库路径设为 $DSH_HOME/memory/ltm.db;无需 API key 或 embedding 服务。

替换 dsh-memory 时先禁用其旧条目:两个插件都注册 memory_write / memory_search / memory_forget。若此前手工插入过 ltm 条目,启用 bundle 前先移除手工 insert,避免重复实例。 安装不会自动迁移旧库;见从 dsh-memory 迁移。

手工组合(含缺少 bundle manifest 的 0.1.0–0.1.1):安装 npm 依赖后,在 profile 的 cordis.patch.yml 里 insert:

- insert:
    - id: ltm
      name: '@tr1v3r/dsh-ltm'
      config:
        path: !!js dshHomePath('memory/ltm.db')

path 必填,代码侧无默认值。推荐的部署路径是 $DSH_HOME 下的 memory/ltm.db —— 独立新库,本插件绝不写旧 memory/memory.db。

配置

| 键 | 默认 | 含义 | |---|---|---| | path | (必填) | SQLite 文件,或 :memory: | | defaultScope | "" | 兜底 scope;关闭自动检测时作为固定 scope | | autoProjectScope | true | 从每个 agent 会话的 cwd/Git 仓库推导当前项目 | | escapeSequences | [] | 可选:渲染进提示词前以零宽空格打断的输出序列 | | promptRecentCount | 10 | 召回分节中未置顶的最近记忆数 | | promptMaxChars | 2000 | 分节硬性 UTF-16 字符预算;置顶记录优先保留 | | promptMaxTokens | (未设) | 可选的正安全整数硬 token 上限(与字符预算并存) | | promptTokenizerPath | (未设) | 本地受支持的 Hugging Face tokenizer.json;与 promptMaxTokens 成对必填 | | maxTextChars | 2000 | 单条记忆最大字符数 | | searchLimitDefault / searchLimitMax | 10 / 50 | 检索结果数量限制 | | promptOrder | 50 | 召回分节顺序 | | dedupeThreshold | 0.8 | Jaccard 相似度 ≥ 该值判定近似重复 | | dedupeCosineThreshold | 0.92 | 余弦相似度 ≥ 该值同样判定近似重复 | | staleAfterDays | 90 | 超过该天数未确认的记忆标记 stale |

默认情况下,记忆文本在召回提示词中逐字保留。escapeSequences 是部署级显式开关, 面向把渲染后的提示词再交给其它基于定界符解析器的环境;DSH 本身不需要。

非法值(空路径、非整数边界、阈值超出 [0,1]、短于 2 字符或含零宽空格的转义序列) 在插件加载时即抛错 —— fail loud,而不是等第一次工具调用。

自动项目隔离

autoProjectScope: true 时,每个 agent 解析自己的 session.header.cwd;绝不使用共享的 DSH 进程 cwd。Git 检出以其 canonical common Git directory 识别,因此子目录与 linked worktree 共享同一项目 scope;非 Git 工作区按 canonical 目录识别。Git scope 名只含 SHA-256 短摘要(各种 linked-worktree 布局保持一致);目录 scope 另带可读 basename。绝不存储绝对路径。

模型面默认刻意收窄:

  • 写入与近似重复检查使用当前项目 scope;
  • 检索与自动召回只看当前项目 + 全局记忆(scope="");
  • update / forget / confirm / merge 拒绝可见 scope 之外的记录,merge 绝不跨 scope;
  • memory_list 与 CLI 保留显式跨项目聚合/管理面。

设 autoProjectScope: false 可只用 defaultScope 作为固定部署 scope("" 即仅全局)。 scope 是上下文隔离边界,不是操作系统权限边界:能直接访问 SQLite 文件或 CLI 的人仍可管理所有记录。

可选离线提示词 token 预算

两个选项默认都不启用:既有纯字符输出保持不变。必须成对设置。可选依赖 @huggingface/[email protected] 只在配置了该功能的插件启动时加载一次;渲染保持同步, 无网络请求、下载或文件读取。CLI doctor 可用显式 JSON 配置渲染诊断投影(绝不读取运行中的 profile)。支持受限且经过保真测试的 ByteLevel/BPE 子集;不支持的管线/选项在启动时失败, 而不是静默近似。上限统计完整的转义后召回分节(含头部、元数据、换行、截断省略号与 省略提示);置顶记录优先,recent 绝不为了省略提示挤掉置顶。离线计数对所选 tokenizer 定义是 精确的,不是服务端用量的承诺。详见 docs/prompt-token-budget.md。

模型工具

兼容 dsh-memory 习惯:

  • memory_write(text, tags?, pinned?, force?) —— 先做去重检查;近似重复返回候选而非写入, 除非 force: true
  • memory_search(query, limit?) —— 中文感知分词 + 混合重排
  • memory_forget(id, expectedRevision?)

新增:

  • memory_update(id, text?, tags?, pinned?, expectedRevision?) —— 原位修订,保留 id
  • memory_confirm(id | "*", expectedRevision?) —— 刷新复核时间戳、清除 stale
  • memory_list(scope?, tags?, stale?, limit?) —— 过滤浏览(tags AND 语义)
  • memory_merge(targetId, sourceIds[], text?, tags?, expectedRevision?, expectedSourceRevisions?) —— 合并重复;tags 默认取并集

身份未知时先检索既有事实/主题再写入。同一事实的状态变化应走 memory_update, 而不是再写一条或 force 写入近似重复。相似度不能证明等价或矛盾;请审阅候选。这是指引, 不是强制的额外检索调用。

成功的置顶写入与相关更新附带可选 budget 反馈;去重拦截的写入不声明新的置顶预算。

乐观并发(revision CAS,#32 阶段一)

每条存储的记忆都带 revision(正整数,从 1 起,与时钟无关)。所有读取 —— 检索结果、 list、提示行((#id, rev N, …))、去重候选 —— 以及每次成功写入都会报告它。向 memory_update / memory_confirm / memory_forget / memory_merge 传入 expectedRevision(你最近读到的版本)即把该变更变成同一个 BEGIN IMMEDIATE 事务内的 比较交换:若记录在你读取之后发生了变化,操作以结构化 MEMORY_REVISION_CONFLICT ({code, operation, id, expectedRevision, currentRevision})失败且什么都不写 —— 不会自动重试你的旧内容。重新读取记录,用其当前版本重试。

  • 省略版本字段保持旧的、不受保护的行为;不带版本的调用绝不宣称受 CAS 保护。
  • 严格模式的 memory_merge 要求目标的 expectedRevision 加上恰好覆盖唯一源 id 集合的 expectedSourceRevisions;部分/重复/多余/包含目标的声明在任何读取之前即被拒绝。
  • id: "*" 的 memory_confirm 只刷新复核时间戳,不是逐条验证,且拒绝 expectedRevision。
  • 冲突与未知/已删除/越权 id 都是纯元数据失败(错误码:MEMORY_REVISION_CONFLICT、 MEMORY_NOT_FOUND、MEMORY_INVALID_ARGUMENT、MEMORY_SCOPE_MISMATCH、 MEMORY_REVISION_OVERFLOW);错误中绝不包含记忆正文。
  • 成功的 update/confirm/merge 返回新 revision;memory_forget 返回 deletedRevision (被删除时的版本)。
  • revision 计数有上限(Number.MAX_SAFE_INTEGER);到达上限的记录不能再被更新、确认或 作为 merge 目标 —— 整次操作拒绝,不静默溢出。删除不受上限限制。

阶段一限制(分阶段计划见 issue #32):CAS 只保护你观察到的版本,不证明内容正确; 阶段二至四(provenance/evidence、分层复核状态、历史/回滚)尚未实现;没有跨恢复/导入的 incarnation/tombstone 保护 —— 此类操作后请静默写入者并重新读取。

规模与限制

近似重复检测在每次非 force 的 memory_write 时扫描同 scope 的全部记忆。该设计面向个人 长期事实库而非大型文档集合。写成本随该 scope 内记忆的数量与长度增长;暂无基准支撑的 容量上限。多会话可共享本地 WAL 库:初始化后的兼容打开不抢 schema 写锁;首次初始化、 schema 修复与 token 索引重建仍需写入。SQLite 以 5 秒 busy 超时串行化写入者;SQLITE_BUSY 提示稍后重试,无自动应用层重试。这不是高并发服务,也不是跨机数据库同步。

CLI

npx -p @tr1v3r/dsh-ltm dsh-ltm --db /path/to/ltm.db <command> [--json]

list / search / show / edit / tag / pin / merge / confirm / forget / upgrade-schema / export / import —— 每个子命令都支持 --json。未知 flag、互斥 flag 与多余位置参数一律 拒绝。默认数据库:$DSH_HOME/memory/ltm.db。

edit/tag/pin/confirm <id>/forget 接受 --expected-revision N;merge 另有 --expected-source-revisions id:rev,id:rev(恰好覆盖唯一源集合)。这些 flag 在打开数据库 之前完成校验;confirm --all --expected-revision 拒绝。CAS 失败以退出码 1 结束,--json 输出与工具相同的结构化 error 详情,人类模式只输出错误码/id/版本与重读指引,绝不回显 未请求的正文。成功的 show/list/search/edit/tag/pin/merge 输出版本号; confirm <id> 报告 confirmed + revision,--all 只报告计数;forget 报告 deleted + deletedRevision。

Schema 升级(v1 → v2)

revision 列之前创建的数据库(schema v1)绝不隐式升级:普通 store/插件/CLI 打开时只读 拒绝,并指向显式升级入口。先停掉所有写入者(包括运行中的插件),然后:

dsh-ltm --db /path/to/ltm.db upgrade-schema            # 默认在库旁生成备份
dsh-ltm --db /path/to/ltm.db upgrade-schema --backup /path/to/new-backup.db

该命令先在只读连接上分类(未知、畸形、伪造 v1、较新版本、畸形/外来 memories_fts 对象、非法基础行——含仅存在于已提交 WAL 帧中的——一律拒绝,主库与已提交 WAL 字节不变、 不建备份),再用只读 VACUUM INTO 取一份 SQLite 一致的备份(默认名 <db>.pre-v2-backup-<UTC时间戳>,绝不覆盖既有文件、绝不指向数据库/sidecar),最后在 写锁下重新核验 v1 结构、FTS 形状与行完整性后,于同一事务应用 ALTER TABLE memories ADD COLUMN revision … 与 meta.schema_version = '2' 版本戳。 若并发升级赢得了该竞态,本次运行不改动任何内容,但会报告自己已取得的备份 (保留并明示、绝不静默删除——快照可能含私密正文,审阅后自行删除)。旧行保持正文/时间戳/scope/tags/pinned 并从 revision 1 开始;fts_token_version 不动。失败即回滚、无半升级状态、备份保留。回滚需 手工进行:停掉写入者并恢复备份快照(升级后的写入会丢失)。已升级库是 metadata-only no-op;该命令绝不创建缺失或空数据库。旧的 dsh-memory → dsh-ltm 一次性迁移是独立的 仓库内工具(见下)。

export 输出 dsh-ltm-export/2(每条记录携带 revision);--out 必须是新文件: 既有文件(含符号链接与硬链接)绝不覆盖,数据库及其 SQLite sidecar 路径即使不存在也被 预留。不给 --out 时 JSON 走 stdout;shell 重定向不在此保护范围内。

import 同时接受 dsh-ltm-export/1(无 revision 的记录按 1 恢复;带 revision 则严格 校验、绝不忽略)与 /2(revision 必填并保留)。完整校验载荷并恢复 ID、时间戳、规范化 tags、scope、pinned、复核生命周期与 revision。完全一致(含 revision)的重复导入幂等跳过; 不同则整批中止、无部分写入 —— 导入绝不以不同 revision 覆盖既有 id。恢复/导入是管理性 恢复边界:CAS 令牌不跨备份或已删除 id 的重导入存活(阶段一无 tombstone),此类操作后 请静默写入者并重新读取。

只读质量体检(doctor)

dsh-ltm --db /path/to/ltm.db doctor --json
dsh-ltm doctor --config /path/to/ltm-config.json --scope 'git:…' --max-pairs 100000 --json

doctor 以 SQLite readOnly: true 打开既有库,绝不经 MemoryStore:不创建、不改 journal mode、不重建 FTS、不迁移、不确认、不清理。缺失文件/父目录与不兼容 schema 一律 fail loud。读取一致基表快照(含已提交 WAL)。FTS 健康明确不检查不修复。两种输出模式都 不包含记忆正文与 tags;findings 只含 ID、规则名、原因、长度/相似度。规则是建议性的, 不是删除/搬移/缩短任何内容的授权。分析与 scope 分布覆盖整个数据库;prompt 统计单独 按可见 scope 计算。CLI 不加载运行中的 profile;不带 --config 时预算是包默认值。 同 scope 近似重复分析是记录数的二次方(对文本长度也敏感),默认上限 100,000 对比较; 总数/已比较/跳过/是否完整始终显式,不完整的扫描不可能冒充完整覆盖。相似度是词法证据, 不是矛盾检测。

从 dsh-memory 迁移

从已退役的 dsh-memory 插件的一次性导入位于仓库内而非已发布 CLI (scripts/legacy-migration/,见其 README)。dsh-ltm 数据库之间的备份与转迁移请用 export / import:它们保留项目 scope 与复核时间戳,而迁移(旧 schema、全局 scope 映射) 不保留。

开发

pnpm install
pnpm typecheck && pnpm test && pnpm build
  • node:sqlite(Node ^22.19.0 || >=24.0.0);WAL + busy_timeout。
  • 引擎模块:src/store.ts、src/tokenize.ts、src/search.ts、src/dedupe.ts、 src/expire.ts、src/errors.ts、src/schema.ts、src/upgrade.ts;冻结接口在 src/contracts.ts。
  • 面模块:src/config.ts、src/tools.ts、src/prompt.ts、src/cli.ts、src/index.ts。
  • 改插件接线或工具 schema 后必须跑真实 boot 探针:node probe/boot-probe.mjs。

发布凭据

发布经 npm Trusted Publishing(OIDC + provenance)从 .github/workflows/publish.yml 进行,CI 不需要任何存储型 npm token。其它 npm 发布凭据尽量放在仓库之外;如需项目级配置 请使用被忽略的 .npmrc-publish 路径,绝不强制加入 Git。不要把 npm token 放进被跟踪的 .npmrc、源码、示例、测试夹具、shell 记录或 CI 日志。若凭据可能进入过 commit、日志、 产物或共享终端历史,先在 npm 账号立即吊销或轮换,再清理暴露副本;仅改写 Git 历史并不能 使凭据失效。

MIT © tr1v3r