memory-eternal 0.9.11 → 0.9.12

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "memory-eternal",
4
- "version": "0.9.11",
4
+ "version": "0.9.12",
5
5
  "description": "璁板繂鏍稿績锛圡emory Eternal锛夛細鐭ヨ瘑鍗¤嚜鍔ㄦ矇娣€/鍙洖锛岀粺涓€ ~/.dsh/memory-vault锛屼細璇濈粨鏉熻嚜鍔ㄥ叆搴撹繘寰呭鏍搞€?,
6
6
  "author": {
7
7
  "name": "EternalNight996",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memory-eternal",
3
- "version": "0.9.11",
3
+ "version": "0.9.12",
4
4
  "description": "璁板繂鏍稿績锛圡emory Eternal锛夛細鐭ヨ瘑鍗¤嚜鍔ㄦ矇娣€/鍙洖锛岀粺涓€ ~/.dsh/memory-vault锛屼細璇濈粨鏉熻嚜鍔ㄥ叆搴撹繘寰呭鏍搞€?,
5
5
  "author": {
6
6
  "name": "EternalNight996",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memory-eternal",
3
- "version": "0.9.11",
3
+ "version": "0.9.12",
4
4
  "description": "璁板繂鏍稿績锛圡emory Eternal锛夛細鐭ヨ瘑鍗¤嚜鍔ㄦ矇娣€/鍙洖锛岀粺涓€ ~/.dsh/memory-vault锛屼細璇濈粨鏉熻嚜鍔ㄥ叆搴撹繘寰呭鏍搞€?,
5
5
  "author": {
6
6
  "name": "EternalNight996",
package/README.en.md CHANGED
@@ -277,6 +277,7 @@ npm run build # builds lib/client.js (DSH embed) + web/app.js (standalone web
277
277
 
278
278
  | Version | Date | Highlights |
279
279
  |---|---|---|
280
+ | **v0.9.12** | 2026-09-28 | **New "Report a bug" entry (🐞 in the left rail)**: the dialog takes your description and then either ① **opens a pre-filled GitHub issue** (title, body, diagnostics and the `bug` label already filled — one more click on Submit files it), or ② **copies a ready-made AI prompt** (paste it into your chat and the AI runs `gh issue list` to de-duplicate, files the issue and reports the URL back). **Why not one-click submission?** GitHub forbids anonymous issue creation, a token shipped inside the plugin would be extracted by decompiling, and OAuth/relay needs hosted infrastructure — hence "pre-fill + one click". Diagnostics come from the new `/memory-eternal/api/diagnostics` endpoint and are **auto-redacted** (home directory → `~`; `sk-` / `ghp_` / `github_pat_` / `api_key:` → `***`; truncated to 2400 chars), and the issue URL is truncated by **binary search** so it can never exceed the length limit (`URLSearchParams` inflates CJK by roughly 9x). Adds `lib/feedback.js` (pure functions) and `tests/feedback.test.mjs` (4 checks: redaction, diagnostic fields and length cap, pre-filled URL encoding/truncation, bilingual prompt); `npm test` now runs **103 checks** |
280
281
  | **v0.9.11** | 2026-09-28 | **Fixed `watchdog --reap` killing itself**: when you run `node lib/watchdog.js --reap` directly, the caller's own command line also contains `watchdog.js` on the same port and is not in the lock — so the reaper SIGTERMed **itself**, showing up as "no output at all + exit code 1" (going through `dsh-memory watchdog --reap` was unaffected because its command line lacks `watchdog.js`, which is why it only showed up on the direct path). The protected set now always includes `keepPid`, the current pid and the parent pid, and any other process whose command line carries `--reap` is skipped; output now uses `fs.writeSync(2, …)` so `process.exit` cannot truncate it. Regression test added for "self and parent must never be killed" (using a real idle child process as the target instead of a fake pid). `npm test` runs **98 checks** |
281
282
  | **v0.9.10** | 2026-09-28 | **Multi-vault + watchdog wrap-up, plus graph frame-time work.** ① **Multi-vault (#10)**: `vaultProfiles` / `activeVault` finally have a settings-page form (add/remove vaults, set directories, pick the active one, and see the effective directory / source / workspace); vault resolution moved into `lib/vault-resolve.js` and is **shared by the host and CLI / MCP / hooks / standalone web / sweep**, with new `vaultProfiles[].match.workspace` **auto-selection by project directory** (longest prefix wins, opt-in, still single-vault by default); `memory_recall` gained a `scope` argument (vault name / path prefix / `all` for cross-vault aggregation) and cross-vault results are labelled with their source vault. ② **Watchdog (#11)**: the lock is now **per-port** (several ports/vaults no longer overwrite each other) and `dsh-memory watchdog --reap` collects orphans left by earlier versions (only same-port processes that are not in the lock; the live registered instance and user-started watchdogs are left alone). ③ **Graph frame time**: edges are bucketed by colour + alpha + width and stroked with a single **Path2D** per bucket (2.7k edges: 2.7k draw calls → a handful), and node radial gradients are **cached per colour\|radius and reused via translate** (593/frame → essentially none after the first frame). ④ New `tests/vault-resolve.test.mjs` (7 checks), watchdog tests grown to 7; `npm test` now runs **98 checks** |
282
283
  | **v0.9.9** | 2026-09-28 | **Fixed the sidebar "Memory" entry being pushed out of view (issue #2)**: the slot host comes in two shapes — the shell's own horizontal row (`.footerActions`) and a `div[data-slot="sidebar.footer.action"]` that other plugins (`dsh-diff-approval`, `dsh-footer-order`, …) turn into `flex-direction: column`. The old CSS applied `flex-wrap: wrap` plus `.me-footer { flex: 1 1 100% }` to both: inside a column container `wrap` means "new column" and `basis: 100%` means **100% height**, so the button was pushed into an overflow column and clipped to a sliver. `flex-wrap` is now scoped to the horizontal `.footerActions` only and `.me-footer` uses the direction-agnostic `flex: 0 0 auto`, guarded by a new SSR assertion. Also: bilingual READMEs gained a "Community & Support" section (group QR + WeChat pay/reward codes), plus `SPONSOR.md` and `.github/FUNDING.yml` |
package/README.md CHANGED
@@ -290,6 +290,7 @@ npm run build # 构建 lib/client.js(DSH 内嵌)+ web/app.js(独立 web
290
290
 
291
291
  | 版本 | 日期 | 关键改动 |
292
292
  |---|---|---|
293
+ | **v0.9.12** | 2026-09-28 | **新增「反馈异常」入口(左栏 🐞)**:弹窗里填完问题描述后可 ① **一键打开 GitHub 预填 issue**(标题 / 正文 / 诊断信息 / `bug` 标签都已填好,再点一次 Submit 即提交),或 ② **复制一段给 AI 的提示词**(贴进对话框,让 AI 先用 `gh issue list` 查重、再建 issue 并回报链接)。**为什么不做「点一下直接提交」**:GitHub 不允许匿名创建 issue;插件内置 token 会被反编译提取;OAuth / 中转需要自建服务 —— 所以走「预填 + 一次点击」。诊断信息由新接口 `/memory-eternal/api/diagnostics` 生成并**自动脱敏**(home 目录 → `~`,`sk-` / `ghp_` / `github_pat_` / `api_key:` 等 → `***`,截断到 2400 字符),issue 链接用**二分截断**保证不超长(`URLSearchParams` 会把中文膨胀约 9 倍)。新增 `lib/feedback.js`(纯函数层)与 `tests/feedback.test.mjs`(4 项:脱敏 / 诊断字段与限长 / 预填链接编码与截断 / 中英双语提示词),`npm test` 共 **103 项** |
293
294
  | **v0.9.11** | 2026-09-28 | **修复 `watchdog --reap` 把自己杀掉**:直接运行 `node lib/watchdog.js --reap` 时,调用者自己的命令行同样含 `watchdog.js` + 同端口、且不在锁里 —— reap 于是把**自己** SIGTERM 了,表现为「一条输出都没有 + 退出码 1」(走 `dsh-memory watchdog --reap` 时因命令行不含 `watchdog.js` 而侥幸没事,所以只在直跑时暴露)。现在保护集合固定包含 `keepPid` / 当前 pid / 父进程 pid,并跳过命令行带 `--reap` 的其它进程;输出改成 `fs.writeSync(2, …)` 同步写,不再被 `process.exit` 截断。回归测试补「自己与父进程都不得被杀」(用真实空转子进程当靶子,不再用假 pid)。`npm test` **98 项** |
294
295
  | **v0.9.10** | 2026-09-28 | **多库与看门狗收尾 + 图谱帧优化**。① **多库(#10)**:`vaultProfiles` / `activeVault` 终于有了配置页表单(增删库、填目录、选激活库,并显示当前生效目录 / 来源 / workspace);vault 解析抽成 `lib/vault-resolve.js`,宿主与 CLI / MCP / hooks / 独立 web / sweep **共用同一份**,新增 `vaultProfiles[].match.workspace` **按项目目录自动选库**(最长前缀优先、opt-in,默认仍是单库);`memory_recall` 增加 `scope` 参数(库名 / 路径前缀 / `all` 跨库聚合),跨库结果标注来源库。② **watchdog(#11)**:锁改为**按端口分槽**(多端口 / 多 vault 并存不再互相覆盖),新增 `dsh-memory watchdog --reap` 回收升级前遗留的孤儿进程(只清同端口、且不在锁里的;锁中活跃实例与用户手动起的都不动)。③ **图谱帧时间**:边改为按「颜色 + 透明度 + 线宽」分桶后用 **Path2D 一次描边**(2.7k 条边从 2.7k 次绘制调用降到几个桶),节点径向渐变改为**按 颜色\|半径 缓存 + translate 复用**(593 次/帧 → 首帧之后基本不再创建)。④ 新增 `tests/vault-resolve.test.mjs`(7 项)、看门狗测试扩到 7 项;`npm test` 共 **98 项** |
295
296
  | **v0.9.9** | 2026-09-28 | **修复侧边栏「记忆」入口被挤出可视区(issue #2)**:槽位宿主有两种形态 —— 壳自己的横向行容器 `.footerActions`,以及被其他插件(`dsh-diff-approval` / `dsh-footer-order` 等)改成 `flex-direction: column` 的 `div[data-slot="sidebar.footer.action"]`。旧 CSS 对两者都套了 `flex-wrap: wrap` + `.me-footer { flex: 1 1 100% }`:纵向容器里 wrap 的语义是「换列」、`basis: 100%` 指的是**高度 100%**,叠加后按钮被挤进右侧溢出列、裁切到只剩右边缘一条缝。现在 `flex-wrap` 只留给横向 `.footerActions`,`.me-footer` 改用方向无关的 `flex: 0 0 auto`,并新增 SSR 回归断言。另:README 双语新增「交流群 & 打赏」(群二维码 + 微信收款码 / 赞赏码),新增 `SPONSOR.md` 与 `.github/FUNDING.yml`(FUNDING 只支持文字链接,故 custom 第一项指向 SPONSOR.md 页面直接展示二维码) |
package/lib/api.js CHANGED
@@ -12,8 +12,10 @@
12
12
  // - getCaptureLog() → 自动沉淀运行轨迹(DSH host 注入;独立 web server 无此数据)
13
13
 
14
14
  import { gzipSync, brotliCompressSync, constants as zlibConstants } from 'node:zlib'
15
+ import os from 'node:os'
15
16
  import { listCards, countCards, readCard, search, searchAll, graph, graphAll, overview, exportCards, deleteCard, writeCard, parseCard, stats, optimizeCandidates, optimizeApply, addFeedback, dailyCounts, mergeCards, ensureVault, auditQueue, recycleList, purgeExpired, setCardStatus, restoreCard } from './vault.js'
16
17
  import { compressExcerpt } from './capture.js'
18
+ import { buildDiagnostics } from './feedback.js'
17
19
  import { getSetupStatus, runSetup, mcpAgentAction } from './setup.js'
18
20
  import { backupDb } from './db.js'
19
21
 
@@ -84,6 +86,38 @@ export function createApi(deps = {}) {
84
86
  json(res, 200, { ok: true, hits })
85
87
  return
86
88
  }
89
+ case '/diagnostics': {
90
+ // 「反馈异常」用:返回一段可直接贴进 issue 的**已脱敏**诊断文本。
91
+ // 宿主与独立 web 共用这个实现;home 目录、各类 key/token 全都会被替换掉。
92
+ const cfgD = getSettings() ?? {}
93
+ const dshD = getDshInfo() ?? null
94
+ const envD = typeof process !== 'undefined' ? process.env : {}
95
+ let countsD = null
96
+ try { countsD = await overview(vaultRoot) } catch { countsD = null }
97
+ let healthD = null
98
+ try { healthD = getCaptureHealth() } catch { healthD = null }
99
+ let logD = []
100
+ try {
101
+ const raw = getCaptureLog()
102
+ logD = Array.isArray(raw) ? raw : (raw && Array.isArray(raw.entries) ? raw.entries : [])
103
+ } catch { logD = [] }
104
+ const homeD = (() => { try { return os.homedir() } catch { return '' } })()
105
+ const text = buildDiagnostics({
106
+ version: (dshD && dshD.version) || envD.MEMORY_ETERNAL_VERSION || '',
107
+ dshVersion: (dshD && dshD.version) || '',
108
+ host: dshD ? 'deepseek-harness' : 'standalone web',
109
+ os: process.platform + ' ' + process.arch + ' / node ' + process.version,
110
+ vaultDir: vaultRoot,
111
+ vaultSource: dshD && dshD.vaultSource,
112
+ workspace: dshD && dshD.workspace,
113
+ cards: countsD ? countsD.total : undefined,
114
+ health: healthD,
115
+ captureLog: logD,
116
+ maxTokens: undefined,
117
+ }, homeD)
118
+ json(res, 200, { ok: true, diagnostics: text, repo: 'EternalNight996/memory-eternal', version: (dshD && dshD.version) || envD.MEMORY_ETERNAL_VERSION || '' })
119
+ return
120
+ }
87
121
  case '/graph': {
88
122
  await ensureVault(vaultRoot)
89
123
  const all = query.get('all') === '1'