memory-eternal 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +27 -20
- package/.codex-plugin/plugin.json +24 -24
- package/.cursor-plugin/plugin.json +14 -14
- package/README.md +138 -654
- package/README.zh-CN.md +138 -0
- package/bin/dsh-memory.mjs +33 -3
- package/cursor-extension/package.json +54 -54
- package/dsh-tui-plugin/README.md +63 -3
- package/dsh-tui-plugin/demo.mjs +113 -25
- package/dsh-tui-plugin/dsh-plugin.json +42 -42
- package/dsh-tui-plugin/main.js +65 -31
- package/dsh-tui-plugin/package.json +51 -31
- package/dsh-tui-plugin/scene.js +125 -16
- package/index.js +28 -3
- package/lib/api.js +89 -14
- package/lib/capture-run.js +35 -8
- package/lib/capture.js +25 -2
- package/lib/client.js +116 -20
- package/lib/db.js +19 -0
- package/lib/ledger.js +107 -0
- package/lib/mcp.js +8 -2
- package/lib/setup.js +67 -5
- package/orca-plugin/orca-plugin.json +36 -36
- package/package.json +7 -4
- package/scripts/release.mjs +5 -4
- package/web/app.js +121 -25
- package/web/index.html +14 -0
- package/README.en.md +0 -621
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# 🧠 memory-eternal —— 给 AI 装一个可信的第二大脑
|
|
2
|
+
|
|
3
|
+
[](https://github.com/EternalNight996/memory-eternal/stargazers)
|
|
4
|
+
[](https://www.npmjs.com/package/memory-eternal)
|
|
5
|
+
[](https://github.com/EternalNight996/memory-eternal/releases)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
[English (default)](README.md) · **简体中文(镜像)**
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<a href="https://eternalnight996.github.io/memory-eternal/demo/"><img src="https://raw.githubusercontent.com/EternalNight996/memory-eternal/main/assets/screen/demo.gif" width="900" alt="memory-eternal 20 秒演示:审核队列、记忆账本、知识星图" /></a>
|
|
12
|
+
</p>
|
|
13
|
+
<p align="center"><sub>▲ 20 秒演示 —— 审核队列 · 记忆账本 · 知识星图 · <a href="https://eternalnight996.github.io/memory-eternal/demo/">在线 Demo</a></sub></p>
|
|
14
|
+
|
|
15
|
+
> **你的 AI 每次会话都失忆。给它一个可信的记忆库。**
|
|
16
|
+
>
|
|
17
|
+
> 本地优先、先审后入、可度量 —— 一个 SQLite 库,DSH / Claude Code / Codex / Cursor 与任意 MCP 客户端共享。
|
|
18
|
+
|
|
19
|
+
- 🔍 **先审核,再入库** —— 新卡先进待审队列,Web 或终端里批准/驳回;每次状态变更写入不可篡改的审计日志。
|
|
20
|
+
- 🧾 **记忆账本** —— 召回注入了多少、蒸馏调了几次、召回到底有没有用,全部可查。
|
|
21
|
+
- 🏠 **本地优先,零云端** —— SQLite + Markdown 存在你自己的磁盘上。没有第三方记忆框架、不需要账号、不外发请求。
|
|
22
|
+
|
|
23
|
+
<p align="center"><strong>⭐ 如果它帮你少解释了一遍上下文,点个 Star 就是最大的支持</strong><br/><sub>DSH 一条命令:<code>dsh plugin --profile desktop add memory-eternal</code></sub></p>
|
|
24
|
+
|
|
25
|
+
## ⚡ 快速开始
|
|
26
|
+
|
|
27
|
+
**DeepSeek Harness(桌面版 / Web)**
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
dsh plugin --profile desktop add memory-eternal
|
|
31
|
+
# 重开 DSH → 左栏「记忆」
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Claude Code、Codex 或 Cursor —— 通过 MCP 共享同一个库**
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm i -g memory-eternal
|
|
38
|
+
dsh-memory connect claude # 或:codex / cursor
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**任意 MCP 客户端**
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx -y -p memory-eternal dsh-memory mcp
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**浏览器或终端**
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
dsh-memory open # http://127.0.0.1:7999
|
|
51
|
+
npx -y -p memory-eternal dsh-memory tui # 终端里的实时待审队列
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 🧾 真的省 token 吗?
|
|
55
|
+
|
|
56
|
+
大多数记忆产品都说自己省 token。我们认为你应该自己验证。插件内置**记忆账本**(运行状态 → 记忆账本),记录:
|
|
57
|
+
|
|
58
|
+
| 记录项 | 含义 |
|
|
59
|
+
|---|---|
|
|
60
|
+
| 召回:命中数 + 注入字符 | 到底有多少记忆进入了上下文 |
|
|
61
|
+
| 沉淀:LLM 调用次数 + 输入/输出字符 | 蒸馏花了你多少成本 |
|
|
62
|
+
| 有用率:有用 / 没用 反馈 | 召回的记忆是否真的帮上了忙 |
|
|
63
|
+
|
|
64
|
+
诚实的算式:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
净收益 ≈ 被避免的上下文开销 −(注入字符 + 蒸馏调用 × 单价)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
| 场景 | 你要付 | 你能省 |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| 有决策与踩坑记录的多会话项目 | 每次召回约 0.6–0.9k token | 重新解释上下文(约 1.5–3k)或重读文件(3–6k) |
|
|
73
|
+
| 一次性问题、低命中率 | 召回注入 | 通常什么也省不到 |
|
|
74
|
+
|
|
75
|
+
> 以上是示意数字,不是 benchmark —— 用账本测你自己的。如果召回有用率长期低于约 60%,就调小(更少条数、更短摘要)或直接关掉记忆。
|
|
76
|
+
|
|
77
|
+
## 🛡️ 先审核,再入库
|
|
78
|
+
|
|
79
|
+
一个「什么都自动吞进去」的记忆系统,迟早会把错误事实当成真相召回。memory-eternal 默认**先审后入**:
|
|
80
|
+
|
|
81
|
+
- 新卡先进入**待审队列**,人工批准后才进主库;
|
|
82
|
+
- 在 Web、终端 TUI 或 CLI 里批准 / 驳回 / 批量处理;
|
|
83
|
+
- 每次状态变更追加到**不可篡改的审计日志**(谁 / 什么 / 何时 / 为什么)—— 由 SQLite 层强制,而不是靠约定;
|
|
84
|
+
- Agent 可以读取和提议,但**不能批准自己写的卡**;
|
|
85
|
+
- 删除的卡进回收站(默认保留 30 天)。
|
|
86
|
+
|
|
87
|
+
## 🧩 一个库,所有 Agent
|
|
88
|
+
|
|
89
|
+
| 入口 | 你能得到什么 |
|
|
90
|
+
|---|---|
|
|
91
|
+
| **DSH 桌面版 / Web** | 内嵌记忆界面:审核、图谱、配置、账本 |
|
|
92
|
+
| **Claude Code / Codex / Cursor** | MCP server,同一个本地库,<code>dsh-memory connect</code> |
|
|
93
|
+
| **任意 MCP 客户端** | <code>npx -y -p memory-eternal dsh-memory mcp</code> |
|
|
94
|
+
| **终端** | <code>dsh-memory tui</code> —— 实时队列、全选、批量批/驳、长文读卡 |
|
|
95
|
+
| **浏览器** | <code>dsh-memory open</code> → http://127.0.0.1:7999 |
|
|
96
|
+
|
|
97
|
+
## 📸 截图
|
|
98
|
+
|
|
99
|
+
<p align="center">
|
|
100
|
+
<img src="https://raw.githubusercontent.com/EternalNight996/memory-eternal/main/assets/screen/graph.png" width="32%" alt="知识星图:按类型分簇、标签连边" />
|
|
101
|
+
<img src="https://raw.githubusercontent.com/EternalNight996/memory-eternal/main/assets/screen/audit.png" width="32%" alt="审核中心:类型条、队列与判词栏" />
|
|
102
|
+
<img src="https://raw.githubusercontent.com/EternalNight996/memory-eternal/main/assets/screen/status.png" width="32%" alt="运行状态:库、备份、自动沉淀与版本" />
|
|
103
|
+
</p>
|
|
104
|
+
<p align="center"><sub>▲ 知识星图 · 审核中心 · 运行状态</sub></p>
|
|
105
|
+
|
|
106
|
+
<p align="center">
|
|
107
|
+
<img src="https://raw.githubusercontent.com/EternalNight996/memory-eternal/main/assets/screen/tui-audit.png" width="49%" alt="终端原生审核:全选、批量批准/驳回" />
|
|
108
|
+
<img src="https://raw.githubusercontent.com/EternalNight996/memory-eternal/main/assets/screen/tui-reader.png" width="49%" alt="终端原生长文读卡器" />
|
|
109
|
+
</p>
|
|
110
|
+
<p align="center"><sub>▲ 终端原生审核与长文读卡 —— <code>dsh-memory tui</code></sub></p>
|
|
111
|
+
|
|
112
|
+
## 📚 文档与链接
|
|
113
|
+
|
|
114
|
+
- [英文完整手册](docs/GUIDE.md) · [完整手册(中文)](docs/GUIDE.zh-CN.md)
|
|
115
|
+
- [私有化部署(Docker / systemd)](docs/DEPLOY.md)
|
|
116
|
+
- [更新日志](docs/CHANGELOG.md) · [架构](docs/ARCHITECTURE.md)
|
|
117
|
+
- [终端插件(dsh-tui)](dsh-tui-plugin/README.md) · [Orca 启动器](orca-plugin/README.md) · [Cursor / VS Code 扩展](cursor-extension/README.md)
|
|
118
|
+
- [反馈问题](https://github.com/EternalNight996/memory-eternal/issues)
|
|
119
|
+
|
|
120
|
+
## 💬 交流群
|
|
121
|
+
|
|
122
|
+
**遇到问题、想提需求、或者想聊聊 DSH 插件开发 —— 欢迎进群:**
|
|
123
|
+
|
|
124
|
+
| QQ 交流群 | 微信交流群 |
|
|
125
|
+
|:---:|:---:|
|
|
126
|
+
| <img src="https://raw.githubusercontent.com/EternalNight996/memory-eternal/main/assets/support/group-qr.jpg" width="240" alt="QQ 群二维码" /> | <img src="https://raw.githubusercontent.com/EternalNight996/memory-eternal/main/assets/support/group-wechat.png" width="240" alt="微信群二维码" /> |
|
|
127
|
+
|
|
128
|
+
**如果这个插件帮你省了时间,可以请作者喝杯咖啡(两个码任选其一):**
|
|
129
|
+
|
|
130
|
+
| 微信收款码 | 微信赞赏码 |
|
|
131
|
+
|:---:|:---:|
|
|
132
|
+
| <img src="https://raw.githubusercontent.com/EternalNight996/memory-eternal/main/assets/support/wechat-pay.jpg" width="200" alt="微信收款码" /> | <img src="https://raw.githubusercontent.com/EternalNight996/memory-eternal/main/assets/support/wechat-reward.jpg" width="200" alt="微信赞赏码" /> |
|
|
133
|
+
|
|
134
|
+
> 打赏完全自愿,不影响任何功能;插件本体始终开源免费(MIT)。详见 [SPONSOR.md](SPONSOR.md)。
|
|
135
|
+
|
|
136
|
+
## 📄 License
|
|
137
|
+
|
|
138
|
+
MIT —— 随便用、随便自托管、随便二次开发。
|
package/bin/dsh-memory.mjs
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// 用法:
|
|
5
5
|
// dsh-memory recall <query> [--limit N] [--vault DIR] 检索知识卡
|
|
6
6
|
// dsh-memory capture <text | - > [--source TAG] 手动沉淀(- 读 stdin)
|
|
7
|
-
// dsh-memory serve [--port N] [--vault DIR]
|
|
7
|
+
// dsh-memory serve [--port N] [--host H] [--vault DIR] 启动 Web UI(前台常驻;--host 0.0.0.0 用于容器/内网,需自行加认证)
|
|
8
8
|
// dsh-memory open [--port N] 确保 Web 存活并用浏览器打开
|
|
9
9
|
// dsh-memory tui [--live] [--write] 打开完整终端客户端(无需绝对路径)
|
|
10
10
|
// dsh-memory mcp MCP stdio server(各 agent 挂载)
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
// dsh-memory refine [--vault DIR] [--json] 矛盾扫描候选(不调模型);--apply --a A --b B --action keepA|keepB|merge|keepBoth 落裁决
|
|
19
19
|
// dsh-memory refine --junk [--purge --path P] [--json] 注入垃圾卡(技能目录等注入文本沉淀成的卡):列清单 / 送回收站
|
|
20
20
|
// dsh-memory refine --goals [--keep --path A --path B] 同目标不同做法:聚类需模型(面板里跑);--keep 落"都保留"
|
|
21
|
+
// dsh-memory ledger [--days N] [--json] 记忆账本:召回注入 / 蒸馏调用 / 召回有用率
|
|
21
22
|
//
|
|
22
23
|
// 环境变量:
|
|
23
24
|
// MEMORY_VAULT_DIR vault 目录(默认 ~/.dsh/memory-vault)
|
|
@@ -105,8 +106,10 @@ async function main() {
|
|
|
105
106
|
const { startWebServer, DEFAULT_WEB_PORT } = await import('../lib/web.js')
|
|
106
107
|
const { defaultVaultDir } = await import('../lib/capture-run.js')
|
|
107
108
|
const port = Number(argOf('--port')) || DEFAULT_WEB_PORT
|
|
109
|
+
// 默认只监听本机:私有化/容器部署时显式 --host 0.0.0.0,并在前面加 TLS + 认证的反向代理
|
|
110
|
+
const host = argOf('--host') || process.env.MEMORY_WEB_HOST || '127.0.0.1'
|
|
108
111
|
const vault = path.resolve(argOf('--vault') || defaultVaultDir())
|
|
109
|
-
await startWebServer({ port, vaultRoot: vault })
|
|
112
|
+
await startWebServer({ port, vaultRoot: vault, host })
|
|
110
113
|
process.on('SIGINT', () => process.exit(0))
|
|
111
114
|
process.on('SIGTERM', () => process.exit(0))
|
|
112
115
|
return
|
|
@@ -148,6 +151,32 @@ async function main() {
|
|
|
148
151
|
startMcpServer()
|
|
149
152
|
return
|
|
150
153
|
}
|
|
154
|
+
case 'ledger': {
|
|
155
|
+
const { ledgerSummary } = await import('../lib/ledger.js')
|
|
156
|
+
const { defaultVaultDir } = await import('../lib/capture-run.js')
|
|
157
|
+
const root = path.resolve(argOf('--vault') || defaultVaultDir())
|
|
158
|
+
const days = Math.min(Math.max(Math.floor(Number(argOf('--days')) || 7), 1), 90)
|
|
159
|
+
let s
|
|
160
|
+
try { s = ledgerSummary(root, { days }) } catch (e) {
|
|
161
|
+
console.error('读取记忆账本失败:' + (e?.message || e))
|
|
162
|
+
process.exitCode = 1
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
if (has('--json')) { console.log(JSON.stringify(s, null, 2)); return }
|
|
166
|
+
const fmt = (n) => Number(n || 0).toLocaleString('en-US')
|
|
167
|
+
console.log('记忆账本(最近 ' + s.days + ' 天)\n')
|
|
168
|
+
console.log('召回 ' + fmt(s.totals.recalls) + ' 次 · 注入 ' + fmt(s.totals.injectedChars) + ' 字符')
|
|
169
|
+
console.log('沉淀 ' + fmt(s.totals.captures) + ' 次 · LLM ' + fmt(s.totals.llmCalls) + ' 次 · 输入 ' + fmt(s.totals.captureInChars) + ' / 输出 ' + fmt(s.totals.captureOutChars) + ' 字符')
|
|
170
|
+
console.log('估算 ≈ ' + fmt(s.totals.estTokens) + ' tokens(中英混排按 2 字符 ≈ 1 token,仅看量级)')
|
|
171
|
+
console.log('')
|
|
172
|
+
console.log(s.feedback.rate === null
|
|
173
|
+
? '召回有用率 暂无反馈(Agent 回传 useful 后才有数据)'
|
|
174
|
+
: '召回有用率 ' + Math.round(s.feedback.rate * 100) + '%(有用 ' + fmt(s.feedback.useful) + ' / 无用 ' + fmt(s.feedback.useless) + ')')
|
|
175
|
+
console.log('\n最近 ' + s.days + ' 天:')
|
|
176
|
+
for (const d of s.byDay) console.log(' ' + d.date + ' 召回 ' + fmt(d.recalls) + ' · 注入 ' + fmt(d.injectedChars) + ' 字符 · 沉淀 ' + fmt(d.captures))
|
|
177
|
+
console.log('\n提示:--json 输出原始数据;Web 面板「运行状态 → 记忆账本」可看趋势。')
|
|
178
|
+
return
|
|
179
|
+
}
|
|
151
180
|
case 'status': {
|
|
152
181
|
const { watchdogStatus, probeServedVersion, findPortListener, looksLikeOurWeb } = await import('../lib/watchdog.js')
|
|
153
182
|
const port = argOf('--port')
|
|
@@ -590,7 +619,7 @@ MCP 侧只提供只读的 memory_audit_list —— 批准/驳回必须由人显
|
|
|
590
619
|
用法:
|
|
591
620
|
dsh-memory recall <query> [--limit N] 检索知识卡
|
|
592
621
|
dsh-memory capture <text | -> [--source T] 手动沉淀(- 读 stdin)
|
|
593
|
-
dsh-memory serve [--port N]
|
|
622
|
+
dsh-memory serve [--port N] [--host H] Web UI(前台;私有化部署见 docs/DEPLOY.md)
|
|
594
623
|
dsh-memory open 确保 Web 存活并打开浏览器
|
|
595
624
|
dsh-memory mcp MCP stdio server
|
|
596
625
|
dsh-memory setup [--dry-run] ... 自动挂载 MCP 到已装 agent
|
|
@@ -601,6 +630,7 @@ MCP 侧只提供只读的 memory_audit_list —— 批准/驳回必须由人显
|
|
|
601
630
|
dsh-memory status [--port N] [--json] 查看常驻看门狗(pid/端口/版本/存活)
|
|
602
631
|
dsh-memory stop [--port N] [--json] 停止常驻看门狗(显式命令,配置变更不会自动停)
|
|
603
632
|
dsh-memory restart [--port N] [--vault DIR] 停止并重新拉起看门狗(应用新版本)
|
|
633
|
+
dsh-memory ledger [--days N] [--json] 记忆账本:召回注入 / 蒸馏调用 / 有用率
|
|
604
634
|
dsh-memory audit list [--status pending] [--kind K] [--json] 列出待审/驳回卡片
|
|
605
635
|
dsh-memory audit approve <path...> | reject <path...> [--reason "原因"] 人工批量审批
|
|
606
636
|
|
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "memory-eternal",
|
|
3
|
-
"displayName": "Memory Atlas",
|
|
4
|
-
"description": "Memory-eternal: open the local Memory Atlas library, review queue and knowledge graph in a Cursor/VS Code webview.",
|
|
5
|
-
"version": "0.
|
|
6
|
-
"publisher": "EternalNight996",
|
|
7
|
-
"license": "MIT",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "https://github.com/EternalNight996/memory-eternal"
|
|
11
|
-
},
|
|
12
|
-
"engines": {
|
|
13
|
-
"vscode": "^1.80.0"
|
|
14
|
-
},
|
|
15
|
-
"categories": [
|
|
16
|
-
"Other"
|
|
17
|
-
],
|
|
18
|
-
"activationEvents": [
|
|
19
|
-
"onView:memory-eternal.view",
|
|
20
|
-
"onCommand:memory-eternal.open"
|
|
21
|
-
],
|
|
22
|
-
"main": "./extension.js",
|
|
23
|
-
"contributes": {
|
|
24
|
-
"viewsContainers": {
|
|
25
|
-
"activitybar": [
|
|
26
|
-
{
|
|
27
|
-
"id": "memory-eternal",
|
|
28
|
-
"title": "Memory Atlas",
|
|
29
|
-
"icon": "icon.png"
|
|
30
|
-
}
|
|
31
|
-
]
|
|
32
|
-
},
|
|
33
|
-
"views": {
|
|
34
|
-
"memory-eternal": [
|
|
35
|
-
{
|
|
36
|
-
"id": "memory-eternal.view",
|
|
37
|
-
"name": "记忆",
|
|
38
|
-
"type": "webview"
|
|
39
|
-
}
|
|
40
|
-
]
|
|
41
|
-
},
|
|
42
|
-
"commands": [
|
|
43
|
-
{
|
|
44
|
-
"command": "memory-eternal.open",
|
|
45
|
-
"title": "Memory Atlas: Open"
|
|
46
|
-
}
|
|
47
|
-
]
|
|
48
|
-
},
|
|
49
|
-
"files": [
|
|
50
|
-
"extension.js",
|
|
51
|
-
"icon.png",
|
|
52
|
-
"README.md"
|
|
53
|
-
]
|
|
54
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "memory-eternal",
|
|
3
|
+
"displayName": "Memory Atlas",
|
|
4
|
+
"description": "Memory-eternal: open the local Memory Atlas library, review queue and knowledge graph in a Cursor/VS Code webview.",
|
|
5
|
+
"version": "0.17.0",
|
|
6
|
+
"publisher": "EternalNight996",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/EternalNight996/memory-eternal"
|
|
11
|
+
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"vscode": "^1.80.0"
|
|
14
|
+
},
|
|
15
|
+
"categories": [
|
|
16
|
+
"Other"
|
|
17
|
+
],
|
|
18
|
+
"activationEvents": [
|
|
19
|
+
"onView:memory-eternal.view",
|
|
20
|
+
"onCommand:memory-eternal.open"
|
|
21
|
+
],
|
|
22
|
+
"main": "./extension.js",
|
|
23
|
+
"contributes": {
|
|
24
|
+
"viewsContainers": {
|
|
25
|
+
"activitybar": [
|
|
26
|
+
{
|
|
27
|
+
"id": "memory-eternal",
|
|
28
|
+
"title": "Memory Atlas",
|
|
29
|
+
"icon": "icon.png"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"views": {
|
|
34
|
+
"memory-eternal": [
|
|
35
|
+
{
|
|
36
|
+
"id": "memory-eternal.view",
|
|
37
|
+
"name": "记忆",
|
|
38
|
+
"type": "webview"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
"commands": [
|
|
43
|
+
{
|
|
44
|
+
"command": "memory-eternal.open",
|
|
45
|
+
"title": "Memory Atlas: Open"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"extension.js",
|
|
51
|
+
"icon.png",
|
|
52
|
+
"README.md"
|
|
53
|
+
]
|
|
54
|
+
}
|
package/dsh-tui-plugin/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# dsh-TUI plugin — `/memory`
|
|
1
|
+
# dsh-TUI plugin — `/memory` 与 `/audit`
|
|
2
2
|
|
|
3
3
|
在 dsh-TUI 里增加一个用户命令:
|
|
4
4
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
/audit
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
在 dsh-tui
|
|
17
|
+
在 dsh-tui 内直接打开**原生审核场景**:读取真实待审队列,判词面板显示卡片来源与 `reason`(区分「蒸馏兜底原文卡」和真正值得审的内容)、`severity`;`s` 全选、`a` 批准、`r` 驳回(批准/驳回都先进入二次确认,驳回可顺手填理由),`Esc` 取消/退出。它不打开浏览器,也不复制 Web UI。详见下文 [「`/audit` 审核闭环」](#audit-审核闭环issue-50)。
|
|
18
18
|
|
|
19
19
|
## 先看效果(不需要 dsh-tui)
|
|
20
20
|
|
|
@@ -70,7 +70,7 @@ node dsh-tui-plugin/demo.mjs --live --write
|
|
|
70
70
|
`MEMORY_ETERNAL_API` 覆盖。API 不可用时自动回退到示例数据。
|
|
71
71
|
- `Space` 多选 / 切换设置
|
|
72
72
|
- `s` 或 `Ctrl+A` 全选 / 反选
|
|
73
|
-
- `a` 批准,`r`
|
|
73
|
+
- `a` 批准,`r` 驳回(都先进入二次确认:`Enter` 才提交,`Esc` 取消;驳回确认态里可直接输入理由)
|
|
74
74
|
- 回收站:`r` 恢复,`d` 彻底删除
|
|
75
75
|
- `/` 搜索,`Esc` 返回 / 清空
|
|
76
76
|
- `?` 帮助,`q` 退出
|
|
@@ -112,6 +112,66 @@ dsh plugin --profile dsh-tui add ./dsh-tui-plugin
|
|
|
112
112
|
- 不会在 TUI 内嵌 WebView,也不复制第二套 UI
|
|
113
113
|
- 审批仍在 Web 里由人完成,不新增 agent 工具
|
|
114
114
|
|
|
115
|
+
## `/audit` 审核闭环(issue #50)
|
|
116
|
+
|
|
117
|
+
装到 dsh-tui 之后,输入 `/audit` 打开原生审核场景(或 `/memory` 打开 Web 版)。
|
|
118
|
+
两者用的是**同一份数据**:待审队列来自 `GET /cards?status=pending&limit=300`,批准/驳回走
|
|
119
|
+
`POST /audit/approve`、`POST /audit/reject`,最终都落到 `setCardStatus()` + `audit_log`,
|
|
120
|
+
不新增 agent 工具、不绕过审核守卫。
|
|
121
|
+
|
|
122
|
+
### 判词面板:先看 `reason`
|
|
123
|
+
|
|
124
|
+
右侧面板按顺序显示:`kind · 时间 · 来源 · 严重度` → `依据:<reason>` → 兜底标记 → 标题/摘要。
|
|
125
|
+
`reason` 由卡片 DB 的 `reason` 字段带出(`/cards` 已返回),常见值:
|
|
126
|
+
|
|
127
|
+
| reason | 含义 | 审核建议 |
|
|
128
|
+
| --- | --- | --- |
|
|
129
|
+
| `AI 自动沉淀(蒸馏卡)` | LLM 蒸馏出的知识卡 | 正常审 |
|
|
130
|
+
| `AI 自动沉淀(原文卡)` | **蒸馏失败/不可用时的降级原文卡** | 优先复核,多数可驳回 |
|
|
131
|
+
| `手动创建` | `/write` 手动写入 | 正常审 |
|
|
132
|
+
| `多卡合并` | 优化合并产生 | 正常审 |
|
|
133
|
+
|
|
134
|
+
- 兜底原文卡额外显示 `⚠ 蒸馏兜底原文卡(无 LLM 精炼,优先复核)`;
|
|
135
|
+
- 没有 `reason` 的卡片不显示该行(不留空行);
|
|
136
|
+
- `severity` 为默认值 `info` 时不显示,非默认值(如 `warning`)才出现在第一行。
|
|
137
|
+
|
|
138
|
+
### 键位
|
|
139
|
+
|
|
140
|
+
| 键 | 作用 |
|
|
141
|
+
| --- | --- |
|
|
142
|
+
| `↑` / `↓` | 移动选中项(列表窗口跟着走,标题显示当前屏 `起-止/总数`) |
|
|
143
|
+
| `Space` | 多选 / 取消选中当前卡 |
|
|
144
|
+
| `s` / `Ctrl+A` | 全选 / 全不选 |
|
|
145
|
+
| `a` | 进入**批准确认态**(底栏:`确认批准 N 张?Enter 确认 / Esc 取消`) |
|
|
146
|
+
| `r` | 进入**驳回确认态**并输入理由(底栏:`驳回 N 张 · 理由(可空):… Enter 确认 / Esc 取消`) |
|
|
147
|
+
| `Enter` | 确认态下提交(驳回时把输入的理由一起提交,批量驳回共用同一理由) |
|
|
148
|
+
| `Esc` | 确认态:取消回列表;列表:退出场景 |
|
|
149
|
+
| 其他可见字符 | 仅驳回确认态:拼进理由(可空;上限 120 字) |
|
|
150
|
+
|
|
151
|
+
确认目标在进入确认态时**冻结**:确认期间列表/选择变化不会改变这次提交的对象;
|
|
152
|
+
提交失败会留在确认态,排好网络/权限后可直接 `Enter` 重试。
|
|
153
|
+
|
|
154
|
+
### 驳回理由写到哪
|
|
155
|
+
|
|
156
|
+
`POST /audit/reject` 现在接受可选 `reason`(JSON body 或 query):
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
// body: { path, reason? } 或 GET /audit/reject?path=...&reason=...
|
|
160
|
+
await setCardStatus(vaultRoot, rel, 'rejected', { changedBy: 'user', reason })
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
- 有理由 → 写进 `audit_log.reason`(`changed_by='user'`);
|
|
164
|
+
- 不传理由 → `reason` 仍是空串,状态流转与以前一致(唯一区别是 `changed_by` 从默认
|
|
165
|
+
`'system'` 变成 `'user'`,因为这是人点的);
|
|
166
|
+
- 响应里回显 `reason`,方便调用方自检。
|
|
167
|
+
|
|
168
|
+
### 本机没有 dsh-tui 宿主时
|
|
169
|
+
|
|
170
|
+
本插件只做 dsh-tui 宿主注册(`tuiPluginHost` / `tuiScenes`)。没有宿主时 `/audit` 不会被加载,
|
|
171
|
+
能用的是仓库里的 TUI 原型(`node dsh-tui-plugin/demo.mjs --live`)。
|
|
172
|
+
纯函数(`cardMeta` / `reasonLine` / `reasonFlag` / `positionLabel` / `confirmLabel` / `auditPayload`)
|
|
173
|
+
可以在没有宿主的环境里直接被 `tests/tui-audit-scene.test.mjs` 验证。
|
|
174
|
+
|
|
115
175
|
## 要求
|
|
116
176
|
|
|
117
177
|
- `memory-eternal` 已安装在当前机器
|