这是什么
和模型聊出来的东西,两天后基本就找不回来了:翻不到、搜不着、粘出来还丢上下文。
dsh-memo-guojc 是 DeepSeek Harness 的一个单体桌面端插件:
在对话里选中一句话 → 存成「切片」→ 自动记住它来自哪个会话、哪段消息 → 以后按项目/会话/标签浏览、全文检索、一键跳回原文并高亮。
它不是笔记软件,而是贴在对话旁边的记忆层:原文不复制、不搬家,只记位置和索引,需要时回原处取。
收起状态就是右侧那只「蓝色大肥鱼」(DeepSeek 蓝鲸梗的二创)——摆尾、眨眼、吐泡泡,点一下展开面板。
![]() |
![]() |
| 收起态:右侧只留一条「大肥鱼」,不挡输入区 | 切片详情:局部树、标签、回跳原文、提炼经验 |
功能
| 能力 | 说明 |
|---|---|
| 划词建切片 | 选中对话里的文字 → 浮动条「✂ 切片」→ 标题 / 摘要 / 类型 / 标签,自动定位 session_id 与消息区间 |
| 全局树 | 项目 → 会话 → 切片 → 子话题,逐层展开折叠、按关键词裁剪、按标签过滤 |
| 备忘录 | 只列 ★ 重点切片,一键钉重点 / 取消 |
| 经验库 | 切片标为「经验候选」→ 人工确认后落库(结论 / 情境 / 适用性 / 来源切片),支持检索与导出 Markdown |
| 全文检索 | SQLite FTS5,中文按二元组喂索引,两个字的词也能命中;结果带摘要片段 |
| 跳回原文 | 按消息区间定位,或按引用文字在页面上查找并闪烁高亮 |
| AI 协同 | 调 DeepSeek:消息区间 → 切片提议;切片 → 经验提炼。一律先进确认界面,点了才落库 |
| AI 工具 | 8 个工具给对话内直接调用:slice_write slice_search slice_list slice_tree slice_mark_key experience_write experience_search experience_export |
| 斜杠命令 | /slice list|add|search|tree|key、/exp list|add|search|export |
| 数据迁移 | 从 v2 的 entries 表自动迁移:exp → 经验库、memo → 重点切片,不丢数据 |
快速开始
前提:DeepSeek Harness 桌面端 0.2.x,Node ≥ 22.5(用到 node:sqlite)。
方式一:插件面板(推荐)
插件面板 → 安装 → 选 dsh-memo-guojc-0.3.1.tgz → 按提示确认 → 重启一次桌面端。
方式二:一行命令
# 先完全退出 DSH 桌面端(CLI 会在 profile 目录跑 pnpm,占用同一批文件)
dsh plugin --profile desktop add ./dsh-memo-guojc-0.3.1.tgz
这条命令等价于在 profile 目录执行 pnpm add <spec>,成功后会把 dsh-memo-guojc 同时写进 dependencies 与 dsh.profile.bundles。
调试时也可以直接链源码目录:
dsh plugin --profile desktop add link:/absolute/path/to/dsh-memo-guojc
方式三:手工装进 profile(离线 / 面板不可用时)
$profile = "$env:USERPROFILE\.dsh\profiles\desktop"
$tgz = ".\dsh-memo-guojc-0.3.1.tgz"
# 1) 解包到 profile 的 node_modules(发布包含 11 个文件,不含 test)
New-Item -ItemType Directory -Force "$profile\node_modules\dsh-memo-guojc" | Out-Null
tar -xzf $tgz -C "$profile\node_modules\dsh-memo-guojc" --strip-components=1
# 2) tgz 存进 vendor 目录,依赖行引用它(file: 依赖别指向含中文的目录)
New-Item -ItemType Directory -Force "$profile\vendor" | Out-Null
Copy-Item $tgz "$profile\vendor\" -Force
# 3) 写 package.json:dependencies + dsh.profile.bundles(务必 UTF-8 无 BOM)
$pkgPath = "$profile\package.json"
$json = [IO.File]::ReadAllText($pkgPath, [Text.Encoding]::UTF8) | ConvertFrom-Json
$dep = "file:" + ($profile.Replace('\','/')) + "/vendor/dsh-memo-guojc-0.3.1.tgz"
$json.dependencies | Add-Member -NotePropertyName 'dsh-memo-guojc' -NotePropertyValue $dep -Force
if ($json.dsh.profile.bundles -notcontains 'dsh-memo-guojc') { $json.dsh.profile.bundles += 'dsh-memo-guojc' }
[IO.File]::WriteAllText($pkgPath, ($json | ConvertTo-Json -Depth 12), (New-Object Text.UTF8Encoding($false)))
手工装不要再跑
pnpm install:宿主启动只读node_modules与bundles,不校验 lockfile。更详细的安装 / 升级 / 卸载见 docs/install.md。
装完重启一次桌面客户端:宿主只在启动时收集页面注入行,插件模块也在启动时装载。
怎么用
划词
在对话里选中一段文字 → 浮出「✂ 切片」/「✨ AI 切片」→ 填标题(摘要、类型、标签可选)→ 保存。 保存时会自动把这条切片挂到当前会话,并记下原文所在的消息区间。
快捷键
| 键 | 作用 |
|---|---|
Ctrl/Cmd + Shift + M |
展开 / 收起面板 |
Ctrl/Cmd + N |
新建切片(面板内) |
Esc |
关弹窗 → 退出详情 → 清搜索 → 收起面板(逐级) |
面板
- 全局树:点切片行进入详情(局部树 + 动作按钮),点「← 返回全局树」回来。
- 备忘录:只有 ★ 重点切片;★ 可随时点掉。
- 经验库:上半是「经验候选」切片,下半是已确认经验;右上角可导出 Markdown。
- 顶部搜索框:一个框搜标题 / 摘要 / 原文,切 Tab 时保留关键词。
- 标签 chips:点一下只看这个标签,再点取消。
- 置顶:钉住后点面板外部不会自动收起;拖标题栏可以挪位置(记在
localStorage)。
让助手直接记
工具由对话里的助手调用,你只要说人话:
- 「把刚才那段存成切片,标题叫『注入行必须在 apply 最前面注册』」→
slice_write - 「我之前记过关于 FTS5 的切片吗」→
slice_search - 「我有哪些重点切片」→
slice_list//slice list - 「把那条钉成重点」→
slice_mark_key - 「把这条切片提炼成经验存起来」→
experience_write - 「导出经验库」→
experience_export//exp export
斜杠命令
/slice 列出最近切片
/slice add 标题 | 摘要 手动建一条切片
/slice search FTS5 全文检索
/slice tree 打印全局树
/slice key <id 前 8 位> 钉为重点
/exp 列出经验(含候选)
/exp add 结论 | 情境 手动写一条经验
/exp search 中文 检索经验
/exp export 导出 Markdown
HTTP API
全部挂在 /dsh-memo 下,只接受回环 Host(localhost / 127.0.0.0/8 / ::1)与同源请求(校验 Sec-Fetch-Site、Origin),默认拒绝跨站。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/health |
版本、存储类型、计数、AI 是否已配置 |
| GET | /api/stats |
切片 / 重点 / 候选 / 经验 / 项目 / 会话计数 |
| GET/POST | /api/settings |
读写 AI 设置(Key 只回 apiKeySet 布尔,不回声) |
| GET | /api/tree?q=&archived= |
项目 → 会话 → 切片 → 子话题 |
| GET | /api/sessions |
本机会话列表(含切片数) |
| GET | /api/sessions/:id/messages?start=&end=&limit= |
某会话的消息区间(AI 与预览用) |
| GET/POST | /api/slices |
列表 / 新建 |
| POST | /api/slices/from-selection |
按原文引用自动定位并建切片 |
| GET/PATCH/DELETE | /api/slices/:id |
读取 / 修改 / 删除 |
| GET | /api/slices/:id/local-tree |
局部树(祖先 + 子话题 + 同级) |
| GET | /api/slices/:id/jump |
回跳信息(含上下文消息) |
| POST | /api/slices/:id/key |
钉重点 / 取消 |
| POST | /api/slices/:id/candidate |
标记经验候选 / 取消 |
| GET | /api/search?q= |
FTS5 全文检索(带摘要片段) |
| GET/POST | /api/experiences |
经验列表(含候选切片)/ 新建 |
| GET | /api/experiences/export.md |
导出 Markdown(附件下载) |
| DELETE | /api/experiences/:id |
删除经验 |
| POST | /api/ai/slices |
消息区间 → 切片提议(不落库) |
| POST | /api/ai/experience |
切片 → 经验提炼(不落库) |
| GET | /client.js |
悬浮窗脚本(no-store) |
成功响应 { "ok": true, ... },失败 { "ok": false, "error": { "code": "...", "message": "..." } }。
数据与隐私
- 库文件:
$DSH_HOME/memo-guojc/memo.db(WAL 模式;MEMO_GUOJC_DIR可覆盖目录)。 - 表:
projects/sessions/slices/experiences/slices_fts(FTS5)/meta。 - 会话原文不复制:切片只记
session_id+message_start+message_end+quote_text,需要时从$DSH_HOME/sessions/**/session.v4.jsonl.zstd现场解压取回(多帧 zstd,按魔数切帧逐段解压)。 - 中文检索:FTS5 的
unicode61会把无空格中文整段当一个词,所以写入索引前把中文切成二元组、查询也切二元组用 AND 组合;原文另存在slices表,片段由 JS 现场截取。单字查询自动退化为LIKE。 - 不出网:除了你自己配的 DeepSeek API(仅在点「AI 切片 / 提炼经验」时调用),插件不向任何第三方发请求;没有遥测、没有账号体系。
- API Key:写入本机 SQLite 的
meta.settings,接口只回apiKeySet布尔;也可以用环境变量DEEPSEEK_API_KEY/DSH_DEEPSEEK_API_KEY。
目录结构
dsh-memo-guojc/
├─ package.json # dsh.bundle.patch 指向 cordis.patch.yml
├─ cordis.patch.yml # 往 profile 的插件列表里 insert 自己
├─ lib/
│ ├─ index.js # 插件入口:注入行 + 路由 + 工具 + 命令
│ ├─ store.js # SQLite(node:sqlite)+ FTS5 + 迁移
│ ├─ router.js # /dsh-memo HTTP API(含回环/同源栅栏)
│ ├─ transcripts.js # 会话 zstd 多帧解压、引文定位、消息区间
│ ├─ tools.js # 8 个 AI 工具的 schema 与文本渲染
│ └─ ai.js # DeepSeek 调用与 JSON 解析
├─ client/
│ └─ client.js # 悬浮窗(原生 DOM + CSS,零构建)
├─ test/
│ ├─ run.mjs # 54 项自测
│ └─ browser/smoke.html # 31 项浏览器冒烟检查(打开即跑)
└─ docs/ # 安装、架构、FAQ、截图
开发与测试
node --version # 需要 ≥ 22.5(node:sqlite)
npm test # 54 项:存储 / 路由 / 工具 / AI / 插件装配 / 浏览器脚本
npm pack # 打发布包(11 个文件)
浏览器侧另有一份冒烟页 test/browser/smoke.html:用 mock 的接口数据加载真实 client.js,31 项检查入口、开合、三个 Tab、标签过滤、详情、置顶、拖动、新建表单、划词浮条、搜索、快捷键与持久化,结果直接印在页面上。用浏览器打开,或:
msedge --headless=new --dump-dom "file:///absolute/path/test/browser/smoke.html#pill"
兼容性与已知限制
- 面向 DSH 桌面端 0.2.x;宿主接口变化可能导致注入行或路由失效。
- 桌面端需重启一次才生效(宿主启动时一次性收集注入行,没有热刷新路径)。
- 「置顶」是页面内语义(最高层级 + 点外部不收起),不是操作系统级 always-on-top——插件在宿主页面里,拿不到 Electron 窗口 API。
- 悬浮窗默认贴右侧、收起时只露那条大肥鱼;位置记在
localStorage,换机器/清缓存回到默认。 - 「跳回原文」依赖页面上能找到那段文字:跨会话时先切到对应会话(会给出提示)。
- FTS5 是子串式二元组匹配,不做分词与同义词;单字查询走
LIKE全表扫(切片量小,够用)。 - 标签统计不含归档切片;标签是子串匹配(
SQLite instr),不做模糊纠错。
更多见 docs/faq.md。
贡献
欢迎 issue 与 PR,先读 CONTRIBUTING.md。安全相关问题请看 SECURITY.md。
许可
MIT © 2026 dsh-memo-guojc contributors



No comments yet. Be the first to write one.