🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

智能体持久记忆 fengruizhi619-cmd/DSH_liubian_memory

DeepSeek Harness
fengruizhi619-cmd12 天前有提交已提供中文文档扫描:含敏感能力

把每轮对话沉淀成日记,让多个智能体互相留言协作

30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/1 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add fengruizhi619-cmd/DSH_liubian_memory
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · chat
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 12 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/10/19) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

仓库 package.json 标记 private,未发布到 npm,需从源码安装;安装清单取自 dsh-liubian-notes/package.json

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包dsh-liubian-notes(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/11 22:26:06

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 143 处,展示前 102 条)
  • 读取本地文件
    dsh-liubian-notes/lib/impl.mjs:96
    if (!existsSync(file)) return null
  • 读取本地文件
    dsh-liubian-notes/lib/impl.mjs:98
    return JSON.parse(readFileSync(file, 'utf8').replace(/^ FEFF/, ''))
  • 读取本地文件
    dsh-liubian-notes/lib/impl.mjs:181
    if (!existsSync(src)) return ''
  • 写入本地文件
    dsh-liubian-notes/lib/impl.mjs:183
    try { renameSync(src, dst); return dst } catch { return '' }
  • 读取本地文件
    dsh-liubian-notes/lib/impl.mjs:196
    if (existsSync(file)) {
  • 读取本地文件
    dsh-liubian-notes/lib/impl.mjs:197
    const text = readFileSync(file, 'utf8').replace(/^ FEFF/, '')
  • 写入本地文件
    dsh-liubian-notes/lib/impl.mjs:232
    mkdirSync(notesDir(), { recursive: true })
  • 写入本地文件
    dsh-liubian-notes/lib/impl.mjs:235
    writeFileSync(tmp, JSON.stringify(pool), 'utf8')
  • 写入本地文件
    dsh-liubian-notes/lib/impl.mjs:236
    renameSync(tmp, file)
  • 读取本地文件
    dsh-liubian-notes/lib/impl.mjs:247
    if (!existsSync(file)) return []
  • 写入本地文件
    dsh-liubian-notes/lib/impl.mjs:257
    mkdirSync(notesDir(), { recursive: true })
  • 写入本地文件
    dsh-liubian-notes/lib/impl.mjs:262
    writeFileSync(tmp, list.map(n => JSON.stringify(n)).join('\n') + (list.length ? '\n' : ''), 'utf8')
  • 发起网络请求
    dsh-liubian-notes/lib/impl.mjs:288
    const res = await fetch(cfg.embedUrl, {
  • 发起网络请求
    dsh-liubian-notes/lib/impl.mjs:460
    const res = await fetch(useUrl, {
  • 发起网络请求
    dsh-liubian-notes/lib/impl.mjs:559
    const res = await fetch(useUrl, {
  • 发起网络请求
    dsh-liubian-notes/lib/impl.mjs:1466
    const res = await fetch(useUrl, {
  • 执行外部命令固定命令
    dsh-plugin/_dev/probe_cwd_enoent.cjs:8
    const child = execFile('E:/python/python.exe', ['-c', 'print("ok")'], { cwd, windowsHide: true },
  • 读取本地文件
    dsh-plugin/_dev/probe_helper_chain.cjs:10
    const cfg = JSON.parse(fs.readFileSync(CFG, 'utf8'));
  • 读取本地文件
    dsh-plugin/_dev/probe_helper_chain.cjs:16
    console.log('配置:python=' + cfg.python + ' | liubianRoot=' + cfg.liubianRoot + '(存在=' + fs.existsSync(cfg.liubianRoot) + ')');
  • 读取本地文件
    dsh-plugin/_dev/probe_helper_chain.cjs:17
    console.log('脚本:' + script + '(存在=' + fs.existsSync(script) + ')');
  • 读取本地文件
    dsh-plugin/_dev/probe_helper_chain.cjs:18
    console.log('LU_DB:' + LU_DB + '(存在=' + fs.existsSync(LU_DB) + ')');
  • 执行外部命令来自配置/变量
    dsh-plugin/_dev/probe_helper_chain.cjs:20
    const child = execFile(cfg.python, [script], {
  • 读取本地文件
    dsh-plugin/_dev/stub_test.mjs:438
    const SRC = readFileSync(new URL('../lib/impl.mjs', import.meta.url), 'utf8')
  • 读取本地文件
    dsh-plugin/lib/impl.mjs:158
    const raw = readFileSync(file, 'utf8').replace(/^ FEFF/, '')
  • 读取本地文件
    dsh-plugin/lib/impl.mjs:209
    if (existsSync(dir)) return dir
  • 读取本地文件
    dsh-plugin/lib/impl.mjs:261
    if (existsSync(cwd)) return cwd
  • 执行外部命令来自配置/变量
    dsh-plugin/lib/impl.mjs:278
    const out = execFileSync(cfg.python, [script, ...args], {
  • 执行外部命令来自配置/变量
    dsh-plugin/lib/impl.mjs:299
    const child = execFile(cfg.python, [script, ...args], {
  • 执行外部命令来自配置/变量
    dsh-plugin/lib/impl.mjs:373
    const child = spawn(cmd, args, {
  • 读取本地文件
    dsh-plugin/lib/impl.mjs:374
    cwd: cwd && existsSync(cwd) ? cwd : undefined,
  • 写入本地文件
    dsh-plugin/lib/impl.mjs:394
    writeFileSync(file, text, 'utf8')
  • 删除本地文件递归
    dsh-plugin/lib/impl.mjs:398
    rmSync(dir, { recursive: true, force: true })
  • 读取本地文件
    dsh-plugin/lib/impl.mjs:745
    if (existsSync(cfg.panelExe)) return `${launchDetached(cfg.panelExe, [])}:流变系统管理面板`
  • 读取本地文件
    dsh-plugin/lib/impl.mjs:746
    if (existsSync(cfg.panelPy)) return `${launchDetached(cfg.python, [cfg.panelPy])}:流变系统管理面板(PyQt)`
  • 写入本地文件
    dsh-plugin/lib/impl.mjs:1096
    mkdirSync(dirname(file), { recursive: true })
  • 写入本地文件
    dsh-plugin/lib/impl.mjs:1097
    writeFileSync(file, JSON.stringify({ updatedAt: new Date().toISOString(), lessons: list }, null, 2), 'utf8')
  • 写入本地文件
    dsh-plugin/lib/impl.mjs:1637
    try { renameSync(file, file + '.corrupt-' + Date.now()) } catch { }
  • 写入本地文件
    dsh-plugin/lib/impl.mjs:1646
    mkdirSync(injectPoolDir(), { recursive: true })
  • 写入本地文件
    dsh-plugin/lib/impl.mjs:1649
    writeFileSync(tmp, JSON.stringify(pool))
  • 发起网络请求
    dsh-plugin/lib/impl.mjs:2755
    const res = await fetch(cfg.diaryTagEmbedUrl, {
  • 发起网络请求
    dsh-plugin/lib/impl.mjs:3041
    const res = await fetch(dc.url, {
  • 删除本地文件
    dsh-plugin/lib/impl.mjs:3170
    if (tmp) { try { rmSync(tmp, { force: true }) } catch { } }
  • 读取本地文件
    embed-plugin/lib/impl.mjs:73
    return JSON.parse(readFileSync(file, 'utf8').replace(/^ FEFF/, '')) || {}
  • 写入本地文件
    embed-plugin/lib/impl.mjs:100
    mkdirSync(dirname(file), { recursive: true })
  • 写入本地文件
    embed-plugin/lib/impl.mjs:101
    writeFileSync(file, JSON.stringify(next, null, 2), 'utf8')
  • 发起网络请求
    embed-plugin/lib/impl.mjs:114
    const res = await fetch(new URL('/health', cfg.embedUrl), { signal: controller.signal })
  • 读取本地文件
    embed-plugin/lib/impl.mjs:135
    if (!existsSync(cfg.embedCmd)) return `[错误] 未找到启动脚本:${cfg.embedCmd}`
  • 执行外部命令固定命令
    embed-plugin/lib/impl.mjs:136
    const child = spawn('cmd.exe', ['/c', cfg.embedCmd], { detached: true, stdio: 'ignore', windowsHide: true })
  • 读取本地文件
    embed-plugin/lib/impl.mjs:141
    if (!exe || !existsSync(exe)) return `[错误] 未找到 llama-server:${exe}`
  • 执行外部命令来自配置/变量
    embed-plugin/lib/impl.mjs:145
    const child = spawn(exe, args, {
  • 读取本地文件
    embed-plugin/lib/impl.mjs:146
    cwd: existsSync(String(cfg.serverCwd || '')) ? cfg.serverCwd : undefined,
  • 执行外部命令固定命令
    embed-plugin/lib/impl.mjs:178
    const out = execFileSync('netstat', ['-ano', '-p', 'TCP'], {
  • 执行外部命令固定命令
    embed-plugin/lib/impl.mjs:200
    execFileSync('taskkill', ['/PID', String(pid), '/T', '/F'], { windowsHide: true, timeout: 20000 })
  • 执行外部命令来自配置/变量
    embed-plugin/lib/impl.mjs:215
    const out = execFileSync(POWER_SHELL, [
  • 读取本地文件
    embed-plugin/lib/impl.mjs:317
    `[配置文件] ${configFile()}${existsSync(configFile()) ? '' : '(尚未创建,用默认值)'}`,
  • 读取本地文件
    infra-plugin/_dev/heal-links.mjs:37
    return JSON.parse(readFileSync(file, 'utf8').replace(/^ FEFF/, ''))
  • 读取本地文件
    infra-plugin/_dev/heal-links.mjs:80
    if (!existsSync(target)) {
  • 读取本地文件
    infra-plugin/_dev/heal-links.mjs:84
    try { st = lstatSync(link) } catch { st = null }
  • 读取本地文件
    infra-plugin/_dev/heal-links.mjs:97
    if (existsSync(link)) rmSync(link, { recursive: true, force: true })
  • 删除本地文件递归
    infra-plugin/_dev/heal-links.mjs:97
    if (existsSync(link)) rmSync(link, { recursive: true, force: true })
  • 写入本地文件
    infra-plugin/_dev/heal-links.mjs:98
    mkdirSync(dirname(link), { recursive: true })
  • 读取本地文件
    infra-plugin/_dev/heal-links.mjs:130
    console.log(` ${name.padEnd(w)} ${existsSync(p) ? '在' : '缺失'}`)
  • 读取本地文件
    infra-plugin/_dev/rename_drill.mjs:29
    const sha = f => createHash('sha256').update(readFileSync(f)).digest('hex')
  • 写入本地文件
    infra-plugin/_dev/rename_drill.mjs:36
    if (existsSync(src)) copyFileSync(src, dbPath + suffix)
  • 读取本地文件
    infra-plugin/_dev/rename_drill.mjs:36
    if (existsSync(src)) copyFileSync(src, dbPath + suffix)
  • 删除本地文件递归
    infra-plugin/_dev/rename_drill.mjs:118
    try { rmSync(dir, { recursive: true, force: true }) } catch {}
  • 删除本地文件递归
    infra-plugin/_dev/stub_test.mjs:542
    try { rmSync(dir, { recursive: true, force: true }) } catch {}
  • 读取本地文件
    infra-plugin/_dev/svc_contract_probe.mjs:22
    const sha = f => createHash('sha256').update(readFileSync(f)).digest('hex')
  • 写入本地文件
    infra-plugin/_dev/svc_contract_probe.mjs:29
    if (existsSync(src)) copyFileSync(src, dbPath + suffix)
  • 读取本地文件
    infra-plugin/_dev/svc_contract_probe.mjs:29
    if (existsSync(src)) copyFileSync(src, dbPath + suffix)
  • 删除本地文件递归
    infra-plugin/_dev/svc_contract_probe.mjs:107
    try { rmSync(dir, { recursive: true, force: true }) } catch {}
  • 读取本地文件
    infra-plugin/lib/impl.mjs:88
    return JSON.parse(readFileSync(file, 'utf8').replace(/^ FEFF/, '')) || {}
  • 写入本地文件
    infra-plugin/lib/impl.mjs:227
    mkdirSync(dirname(dbPath), { recursive: true })
  • 发起网络请求
    infra-plugin/lib/impl.mjs:681
    const res = await fetch(new URL('/health', cfg.embedUrl), { signal: controller.signal })
  • 发起网络请求
    infra-plugin/lib/impl.mjs:704
    const res = await fetch(new URL('/v1/embeddings', cfg.embedUrl), {
  • 读取本地文件
    infra-plugin/lib/impl.mjs:726
    if (!exe || !existsSync(exe)) return `[错误] 未找到 llama-server:${exe}`
  • 写入本地文件
    infra-plugin/lib/impl.mjs:736
    mkdirSync(dirname(logFile), { recursive: true })
  • 写入本地文件
    infra-plugin/lib/impl.mjs:737
    appendFileSync(logFile, `\n===== launch @ ${new Date().toISOString()} =====\n`)
  • 执行外部命令来自配置/变量
    infra-plugin/lib/impl.mjs:743
    const child = spawn(exe, args, {
  • 读取本地文件
    infra-plugin/lib/impl.mjs:744
    cwd: existsSync(String(cfg.serverCwd || '')) ? cfg.serverCwd : undefined,
  • 执行外部命令固定命令
    infra-plugin/lib/impl.mjs:774
    const out = execFileSync('netstat', ['-ano', '-p', 'TCP'], {
  • 执行外部命令固定命令
    infra-plugin/lib/impl.mjs:791
    const out = execFileSync('netstat', ['-ano', '-p', 'TCP'], {
  • 执行外部命令固定命令
    infra-plugin/lib/impl.mjs:807
    const out = execFileSync('tasklist', ['/FI', `IMAGENAME eq ${image}`, '/FO', 'CSV', '/NH'], {
  • 执行外部命令固定命令
    infra-plugin/lib/impl.mjs:825
    execFileSync('taskkill', ['/PID', String(pid), '/T', '/F'], { windowsHide: true, timeout: 20000 })
  • 执行外部命令来自配置/变量
    infra-plugin/lib/impl.mjs:840
    const out = execFileSync(POWER_SHELL, [
  • 读取本地文件
    infra-plugin/lib/impl.mjs:1025
    if (base && root && existsSync(join(root, base))) return base
  • 写入本地文件
    liubian-kit/_dev/stub_test.mjs:167
    writeFileSync(join(dir, 'legacy.jsonl'), '{"id":"old-1"}\n', 'utf8')
  • 写入本地文件
    liubian-kit/_dev/stub_test.mjs:181
    writeFileSync(f, readFileSync(f, 'utf8') + '这不是JSON\n' + '{"id":"b","extra":1}\n', 'utf8')
  • 读取本地文件
    liubian-kit/_dev/stub_test.mjs:181
    writeFileSync(f, readFileSync(f, 'utf8') + '这不是JSON\n' + '{"id":"b","extra":1}\n', 'utf8')
  • 写入本地文件
    liubian-kit/_dev/stub_test.mjs:199
    writeFileSync(f4.file, readFileSync(f4.file, 'utf8') + '坏行\n', 'utf8')
  • 读取本地文件
    liubian-kit/_dev/stub_test.mjs:199
    writeFileSync(f4.file, readFileSync(f4.file, 'utf8') + '坏行\n', 'utf8')
  • 写入本地文件
    liubian-kit/_dev/stub_test.mjs:210
    writeFileSync(join(dir, 'legacy2.jsonl'), '{"id":"keep-me"}\n{"id":"drop-me"}\n', 'utf8')
  • 读取本地文件
    liubian-kit/_dev/stub_test.mjs:219
    const s = readFileSync(f4.file, 'utf8')
  • 删除本地文件递归
    liubian-kit/_dev/stub_test.mjs:225
    try { rmSync(dir, { recursive: true, force: true }) } catch {}
  • 读取本地文件
    liubian-kit/lib/base-jsonl-file.mjs:51
    if (!existsSync(this.file)) return false
  • 写入本地文件
    liubian-kit/lib/base-jsonl-file.mjs:64
    mkdirSync(dirname(this.file), { recursive: true })
  • 写入本地文件
    liubian-kit/lib/base-jsonl-file.mjs:65
    writeFileSync(this.file, lines.join('\n') + '\n', 'utf8')
  • 读取本地文件
    liubian-kit/lib/base-jsonl-file.mjs:87
    try { return readFileSync(this.file, 'utf8').split('\n').filter(l => l.trim()) } catch { return [] }
  • 写入本地文件
    liubian-kit/lib/base-jsonl-file.mjs:93
    mkdirSync(dirname(this.file), { recursive: true })
  • 写入本地文件
    liubian-kit/lib/base-jsonl-file.mjs:97
    writeFileSync(this.file, lines.join('\n') + '\n', 'utf8')
  • 写入本地文件
    liubian-kit/lib/base-jsonl-file.mjs:128
    writeFileSync(tmp, keep.join('\n') + '\n', 'utf8')
  • 写入本地文件
    liubian-kit/lib/base-jsonl-file.mjs:129
    renameSync(tmp, this.file)
扫描于 2026/11/4(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 对话沉淀为日记
  • 多智能体互相留言协作
  • 持久记忆与协作底座

流变系统(Liubian)—— 给 AI 智能体用的持久记忆与协作底座:记忆/被炉/更新/通路四子系统,含 DSH 原生插件、MCP 服务器与本地管理面板

README

由 DeepSeek 最新模型翻译生成
[!IMPORTANT] 本仓库已由世界树(DSH_worldtree)接替。 世界树是记忆系统 v2:向量主题树自动生长 + P3 蒸馏管线 + 注入池两级赛马 + 三通道检索,独立分支(不属于流变系列)。 本仓转为档案仓:保留 v1 全部历史、设计文档与决策记录,不再新增功能开发。数据已完整迁移至世界树。 流变系统 · Liubian 给 AI 智能体用的持久记忆与协作底座:把每一轮对话沉淀成可检索的日记,让多个智能体互相留言、实时会诊,并让技能在它们之间自动分发与同步。 流变系统(Liubian)统合四个子系统: | 子系统 | 作用 | 主要文件 | | 流变·记忆 memory | 日记写入、标签索引、跨会话检索、语义向量召回 | memory/scripts/memory.py、memory_db.py、semantic_search.py | | 流变·被炉 kotatsu | 多智能体实时房间:收发、待办、挂机监听(已从 DSH 插件卸下,待独立插件) | memory/mcp/mcp_kotatsu.py、memory/scripts/kotatsu_ui.py |
展开完整文档(README 剩余 1 节)
[!IMPORTANT]
本仓库已由世界树(DSH_worldtree)接替。
世界树是记忆系统 v2:向量主题树自动生长 + P3 蒸馏管线 + 注入池两级赛马 + 三通道检索,独立分支(不属于流变系列)。
本仓转为档案仓:保留 v1 全部历史、设计文档与决策记录,不再新增功能开发。数据已完整迁移至世界树。

流变系统 · Liubian

给 AI 智能体用的持久记忆与协作底座:把每一轮对话沉淀成可检索的日记,让多个智能体互相留言、实时会诊,并让技能在它们之间自动分发与同步。

流变系统(Liubian)统合四个子系统:

| 子系统 | 作用 | 主要文件 |
| 流变·记忆 memory | 日记写入、标签索引、跨会话检索、语义向量召回 | memory/scripts/memory.py、memory_db.py、semantic_search.py |
| 流变·被炉 kotatsu | 多智能体实时房间:收发、待办、挂机监听(已从 DSH 插件卸下,待独立插件) | memory/mcp/mcp_kotatsu.py、memory/scripts/kotatsu_ui.py |
| 流变·更新 update | 技能装载 / 快照 / 哈希同步 / 订阅广播 | memory/mcp/mcp_update.py、liubian/scripts/liubian.py |
| 流变·通路 path | 无上下文双 API 交叉校验(生成 → 五维度挑错) | liubian/scripts/通路2/liubian_path2.py |

本仓库同时提供两套接入方式:

- memory/ + liubian/ —— 原始的 Codex / MCP 接入:9 个 MCP 服务器 + 一个统一 CLI + 本地管理面板(PyQt / Web)。
- dsh-plugin/ —— DeepSeek Harness (DSH) 原生插件,把同一套后端以原生工具形式接进 DSH,并额外实现:
- 自动日记:每轮对话结束后,由外部 API 把「上一轮完整对话」写成日记(标签候选用本地向量模型选前 100 个),下一轮自动落库;
- 联合检索注入:查询 = 上一轮回答 + 本轮问题 → ①嵌入成向量与全库日记算余弦 ②同一段文本 + 标签候选送外部 API 挑 5 个标签做字面检索 ③两路融合取前 10 篇全文注入上下文。

设计要点

1. 记忆的粒度是"日记",不是"消息"。 不把原始对话灌进索引(那只会污染检索),而是每轮沉淀一条带细小标签的摘要式日记。检索靠标签命中 + 语义向量双路。

2. 标签是检索的主键。 标签必须"细、具体、可复用"(例如 注入消息缺id 而不是 bug)。系统会维护一张全局标签字典,写日记时优先复用已有标签。

3. 检索是双路的。 字面(标签)与语义(向量)各有盲区:前者漏同义表达,后者被泛化词淹没。两路融合后取交集附近的结果最稳。

4. 多智能体靠"被炉"协作。 被炉(Kotatsu)是给智能体用的群聊房间:留言、待办、挂机监听。不同会话/不同机器的智能体通过它交接任务。

5. 技能即资产,可分发。 技能(SKILL.md)有独立版本与哈希快照,update 子系统负责装载、比对、同步与广播。

快速开始

A. 作为 DSH 插件(推荐)

1) 放到 DSH 插件目录
git clone https://github.com/<you>/liubian.git
把 dsh-plugin/ 链接或复制到你的插件目录,例如 ~/.dsh/plugins/dsh-liubian

2) 配置(可选,默认值见插件内 DEFAULTS) ~/.dsh/liubian/config.json —— 后端路径、默认工作区等 ~/.dsh/liubian/diary.json —— 自动日记的开关与 API key(写日记用)

3) 注入 DSH 里用插件加载器加载该目录,或使用 super-injector: dev_inject_plugin <插件目录>

插件会自动注册 16 个工具(写日记 / 检索 / 读日记 / 标签 / 留言板 / 被炉 / 更新 / 通路二 / 面板 / 自动日记运维 …),并在每轮对话前把最相关的 10 篇记忆全文注入上下文。

自动日记需要一个 OpenAI 兼容的 chat completions 端点(默认 DeepSeek):

// ~/.dsh/liubian/diary.json
{
"enabled": true,
"url": "https://api.deepseek.com/chat/completions",
"apiKey": "sk-...",
"model": "deepseek-chat"
}

语义检索 / 语义选标签需要一个本地嵌入服务(llama.cpp + 任意 1024 维嵌入模型,默认 Qwen3-Embedding-0.6B,端口 8082)。服务不可用时全部功能自动退化为纯标签检索,不会报错。

B. 作为 MCP 服务(Codex / Claude Code 等)

memory/mcp/ 下有 9 个 MCP 服务器,逐个接进你的 MCP 客户端即可:

mcp_memory.py 写日记 / 读日记 mcp_search.py 标签 + 语义检索 mcp_write.py 写入 mcp_kotatsu.py 被炉房间 mcp_update.py 技能装载 / 快照 / 同步 mcp_skill_index.py 技能文档语义索引 mcp_validate.py 通路二校验 mcp_panel.py 打开本地管理面板 mcp_embed.py 本地嵌入服务生命周期 mcp_guard.py 身份 / 权限守卫

C. 只用 CLI

记忆:写日记 / 检索 / 标签 / 留言板
python memory/scripts/memory.py write -t "标签1,标签2,标签3,标签4,标签5" -s "摘要" --content "正文"bash
python memory/scripts/memory.py search --tags "标签1,标签2,标签3,标签4"
python memory/scripts/memory.py tags
python memory/scripts/memory.py info

流变总纲:状态 / 面板 / 通路二

python liubian/scripts/liubian.py status
python liubian/scripts/liubian_panel_qt.py # PyQt 管理面板
python liubian/scripts/通路2/liubian_path2.py "你的问题"

数据与存储

所有数据默认落在单个 SQLite 库里(liubian.db,路径由 LU_DB 环境变量指定):

| 表 / 文档键 | 内容 |
| docs(键值) | 用户、工作区标签索引 index:<工作区>、留言板 board、被炉房间、技能快照 …… |
| diary_content | 日记正文 |
| embeddings | 每篇日记的 1024 维向量(float32 BLOB) |
| skill_docs | 技能文档的向量索引 |

注意:日志、向量、个人记忆内容不在本仓库内。仓库只含代码、技能定义与设计文档。

目录结构

liubian/
├── memory/ 流变·记忆(Codex/MCP 侧) │ ├── SKILL.md 技能说明书(给智能体读的协议) │ ├── scripts/ │ │ ├── memory.py 统一 CLI(日记 / 检索 / 用户 / 被炉 / 更新) │ │ ├── memory_db.py SQLite 访问层 │ │ ├── semantic_search.py 语义向量检索(llama.cpp 嵌入服务) │ │ └── kotatsu_ui.py 被炉房间 UI │ ├── mcp/ 9 个 MCP 服务器 │ └── agents/ 智能体侧配置 ├── liubian/ 流变总纲(CLI + 面板 + 通路二) │ ├── SKILL.md │ ├── scripts/ │ │ ├── liubian.py 四子系统统一入口 │ │ ├── liubian_panel.py 本地 Web 管理面板 │ │ ├── liubian_panel_qt.py PyQt 管理面板 │ │ └── 通路2/ 双 API 交叉校验 │ ├── icons/ │ └── 设计/ 设计文档 ├── dsh-plugin/ DeepSeek Harness 原生插件 │ ├── lib/main.mjs 入口壳(带缓存击穿的动态 import) │ ├── lib/impl.mjs 单文件实现(工具面 + 上下文注入 + 自动日记 + 联合检索) │ ├── helper/ 检索 / 统计 helper(Python) │ │ └── reserved/ 已卸下子系统的 helper(被炉 room_read.py,留给未来插件) │ └── skills/ 随插件分发的技能 ├── embed-plugin/ 向量服务插件(独立):llama.cpp 嵌入服务生命周期 │ ├── lib/impl.mjs 探活 / 拉起 / 关停 / 重启(直起 exe,无窗) │ └── README.md 含"为什么不能用 cmd/start 拉起"的实测记录 └── docs/

环境要求

- Python 3.10+(标准库为主;语义检索有 numpy 更快,缺了会自动退化为纯 Python 余弦)
- 可选:本地嵌入服务(llama.cpp --embeddings,默认 http://127.0.0.1:8082,1024 维)
- 可选:任意 OpenAI 兼容 API(自动日记 / 通路二校验)
- DSH 插件部分:DeepSeek Harness,Node 20+

版本

首次开源发布的版本记作 v1.0.0。版本号策略:主版本.次版本.修订号,每次对外发布打附注标签(annotated tag)并建 Release。

| 版本 | 日期 | 内容 |
| v1.0.0 | 2026-09-12 | 首次开源发布:流变系统四子系统(记忆 / 被炉 / 更新 / 通路)完整开源;Codex-MCP 侧 9 个 MCP 服务器 + 统一 CLI + 本地管理面板;DSH 原生插件(16 个工具 + 每轮自动日记 + 联合检索全文注入);含总体设计文档 v1。 |

后续版本在同一仓库打标签并建 Release。

许可

MIT,见 LICENSE。
预览分享卡片长什么样 ↓fengruizhi619-cmd/DSH_liubian_memory
分享 · DeepSeek Harness Hub
fengruizhi619-cmd/DSH_liubian_memory

把每轮对话沉淀成日记,让多个智能体互相留言协作

这是你的仓库?认领条目

回到顶部