recallnest 2.2.0 → 2.3.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.
Files changed (249) hide show
  1. package/.env +4 -0
  2. package/CLAUDE.md +1 -1
  3. package/README.md +30 -5
  4. package/README_CN.md +30 -5
  5. package/config.json +55 -0
  6. package/connectors/examples/email-adapter.ts +73 -0
  7. package/connectors/examples/logs-adapter.ts +103 -0
  8. package/connectors/examples/rss-adapter.ts +95 -0
  9. package/logs/daily-recall.error.log +0 -0
  10. package/logs/daily-recall.log +60 -0
  11. package/logs/ingest-2026-04-11.log +110 -0
  12. package/logs/ingest-2026-04-12.log +90 -0
  13. package/logs/ingest-2026-04-13.log +87 -0
  14. package/logs/launchagent-stderr.log +0 -0
  15. package/logs/launchagent-stdout.log +0 -0
  16. package/package.json +1 -1
  17. package/src/cli.ts +30 -0
  18. package/src/connector-types.ts +57 -0
  19. package/src/conversation-importer.ts +25 -1
  20. package/src/data-checkup.ts +31 -1
  21. package/src/doctor.ts +29 -0
  22. package/src/ingest.ts +203 -0
  23. package/src/mcp-server.ts +2 -2
  24. package/src/obsidian-connector.ts +282 -0
  25. package/src/session-schema.ts +2 -2
  26. package/src/source-heartbeat.ts +108 -0
  27. package/.claude-plugin/CLAUDE.md +0 -29
  28. package/.claude-plugin/marketplace.json +0 -18
  29. package/.dockerignore +0 -11
  30. package/.github/workflows/ci.yml +0 -28
  31. package/.mcp.json +0 -9
  32. package/CHANGELOG.md +0 -51
  33. package/DEMO.md +0 -94
  34. package/Dockerfile +0 -20
  35. package/EVAL.md +0 -89
  36. package/FAILURES.md +0 -75
  37. package/OPERATIONS.md +0 -59
  38. package/ROADMAP.md +0 -245
  39. package/SKILL.md +0 -250
  40. package/assets/dashboard.png +0 -0
  41. package/assets/knowledge-graph.png +0 -0
  42. package/assets/recallnest-workbench.png +0 -0
  43. package/assets/screenshots/ui-full.png +0 -0
  44. package/assets/screenshots/ui-overview.png +0 -0
  45. package/assets/screenshots/ui-search.png +0 -0
  46. package/assets/ui/app.js +0 -1031
  47. package/assets/ui/index.html +0 -224
  48. package/assets/ui/styles.css +0 -781
  49. package/assets/wechat-qr.jpg +0 -0
  50. package/bun.lock +0 -337
  51. package/daily-reflections/2026-03-05.md +0 -15
  52. package/daily-reflections/2026-03-06.md +0 -15
  53. package/daily-reflections/2026-03-07.md +0 -7
  54. package/daily-reflections/2026-03-08.md +0 -34
  55. package/daily-reflections/2026-03-09.md +0 -35
  56. package/daily-reflections/2026-03-10.md +0 -36
  57. package/daily-reflections/2026-03-11.md +0 -35
  58. package/daily-reflections/2026-03-12.md +0 -36
  59. package/daily-reflections/2026-03-13.md +0 -35
  60. package/daily-reflections/2026-03-14.md +0 -35
  61. package/daily-reflections/2026-03-15.md +0 -35
  62. package/daily-reflections/2026-03-16.md +0 -41
  63. package/daily-reflections/2026-03-17.md +0 -10
  64. package/daily-reflections/2026-03-18.md +0 -10
  65. package/daily-reflections/2026-03-19.md +0 -10
  66. package/daily-reflections/2026-03-20.md +0 -10
  67. package/daily-reflections/2026-03-21.md +0 -10
  68. package/daily-reflections/2026-03-22.md +0 -10
  69. package/daily-reflections/2026-03-23.md +0 -10
  70. package/daily-reflections/2026-03-24.md +0 -10
  71. package/daily-reflections/2026-03-25.md +0 -32
  72. package/daily-reflections/2026-03-26.md +0 -37
  73. package/daily-reflections/2026-03-27.md +0 -35
  74. package/daily-reflections/2026-03-28.md +0 -35
  75. package/daily-reflections/2026-03-29.md +0 -35
  76. package/daily-reflections/2026-03-30.md +0 -36
  77. package/daily-reflections/2026-03-31.md +0 -35
  78. package/daily-reflections/2026-04-01.md +0 -35
  79. package/daily-reflections/2026-04-02.md +0 -35
  80. package/daily-reflections/2026-04-03.md +0 -37
  81. package/daily-reflections/2026-04-04.md +0 -37
  82. package/daily-reflections/2026-04-05.md +0 -35
  83. package/daily-reflections/2026-04-06.md +0 -36
  84. package/daily-reflections/2026-04-07.md +0 -35
  85. package/daily-reflections/2026-04-08.md +0 -35
  86. package/daily-reflections/2026-04-12.md +0 -35
  87. package/data/alias-map.example.json +0 -22
  88. package/docs/api-reference.md +0 -1291
  89. package/docs/architecture.md +0 -168
  90. package/docs/memory-boundary-contract.md +0 -226
  91. package/docs/memory-categories.md +0 -119
  92. package/docs/pipeline-audit-ultramemory.md +0 -177
  93. package/docs/plans/2026-03-08-query-expansion.md +0 -270
  94. package/docs/plans/2026-03-16-continuity-layer.md +0 -196
  95. package/docs/plans/2026-04-01-recall-boost.md +0 -100
  96. package/docs/plans/mcp-tiering-plan.md +0 -126
  97. package/docs/research/recall-quality-audit-2026-03-22.md +0 -153
  98. package/docs/self-evolution.md +0 -198
  99. package/docs/superpowers/plans/2026-03-19-ingest-pipeline-upgrade.md +0 -782
  100. package/docs/superpowers/plans/2026-04-11-constructive-retrieval-emotion.md +0 -1195
  101. package/docs/superpowers/specs/2026-03-19-ingest-pipeline-upgrade-design.md +0 -77
  102. package/docs/superpowers/specs/2026-03-23-pull-claude-desktop-design.md +0 -95
  103. package/docs/superpowers/specs/2026-04-11-constructive-retrieval-emotion-design.md +0 -398
  104. package/eval/continuity/results-2026-03-16.md +0 -117
  105. package/eval/continuity/results-2026-03-19.md +0 -453
  106. package/eval/continuity/runbook.md +0 -110
  107. package/eval/continuity/seed-cases.md +0 -54
  108. package/eval/reports/2026-03-06-abstract-query-baseline.md +0 -96
  109. package/eval/reports/2026-03-06-aws-ssh-baseline.md +0 -82
  110. package/eval/reports/2026-03-06-baseline.md +0 -82
  111. package/eval/reports/query-expansion.md +0 -138
  112. package/glama.json +0 -6
  113. package/lm +0 -19
  114. package/plan-philosophy-upgrades.md +0 -363
  115. package/plan-product-upgrades.md +0 -155
  116. package/plan-v1.2-distributable.md +0 -105
  117. package/plan.md +0 -140
  118. package/research-memory-evolution.md +0 -440
  119. package/research-rl-agent-memory.md +0 -330
  120. package/scripts/archive-distilled-junk.ts +0 -116
  121. package/scripts/backfill-anchors.ts +0 -130
  122. package/scripts/backfill-l0l1l2.ts +0 -98
  123. package/scripts/blind-scan.ts +0 -588
  124. package/scripts/cleanup-step1-exact-dups.ts +0 -117
  125. package/scripts/cleanup-step2-template-dups.ts +0 -113
  126. package/scripts/cleanup-step3-stale-content.ts +0 -149
  127. package/scripts/cleanup-step4-orphan-scopes.ts +0 -131
  128. package/scripts/delete-distilled-junk.ts +0 -88
  129. package/scripts/diagnose-vector-search.ts +0 -132
  130. package/scripts/distill-facts.ts +0 -305
  131. package/scripts/health-check.ts +0 -343
  132. package/scripts/incremental-ingest.sh +0 -71
  133. package/scripts/migrate-language.ts +0 -75
  134. package/scripts/mlp-health-check.ts +0 -382
  135. package/scripts/pull-claude-desktop.ts +0 -515
  136. package/scripts/re-ingest-cc.sh +0 -66
  137. package/scripts/rebalance-memory-health.ts +0 -181
  138. package/scripts/run-desktop-ingest.sh +0 -11
  139. package/scripts/start-server.sh +0 -12
  140. package/scripts/verify-emotion-decay.ts +0 -148
  141. package/scripts/viz-dashboard.html +0 -423
  142. package/scripts/viz-export.ts +0 -703
  143. package/src/__tests__/access-tracker-novelty.test.ts +0 -228
  144. package/src/__tests__/activity-counter.test.ts +0 -96
  145. package/src/__tests__/admission-control.test.ts +0 -206
  146. package/src/__tests__/anchor-generator.test.ts +0 -67
  147. package/src/__tests__/auto-consolidation.test.ts +0 -168
  148. package/src/__tests__/auto-recall.test.ts +0 -131
  149. package/src/__tests__/babel-integration.test.ts +0 -139
  150. package/src/__tests__/batch-dedup.test.ts +0 -65
  151. package/src/__tests__/capture-engine.test.ts +0 -1144
  152. package/src/__tests__/capture-heuristic.test.ts +0 -171
  153. package/src/__tests__/cascade-forget.test.ts +0 -210
  154. package/src/__tests__/category-min-scores.test.ts +0 -33
  155. package/src/__tests__/cc8-cc1-essential-context.test.ts +0 -298
  156. package/src/__tests__/circuit-breaker.test.ts +0 -99
  157. package/src/__tests__/cluster-consolidation.test.ts +0 -712
  158. package/src/__tests__/confidence-metadata.test.ts +0 -125
  159. package/src/__tests__/confidence-tracker.test.ts +0 -249
  160. package/src/__tests__/conflict-advisor.test.ts +0 -206
  161. package/src/__tests__/conflict-escalation.test.ts +0 -149
  162. package/src/__tests__/conflict-lifecycle.test.ts +0 -83
  163. package/src/__tests__/conflict-output.test.ts +0 -85
  164. package/src/__tests__/conflict-store.test.ts +0 -374
  165. package/src/__tests__/consolidation-engine.test.ts +0 -181
  166. package/src/__tests__/constructive-retrieval.test.ts +0 -509
  167. package/src/__tests__/context-collapse-renderer.test.ts +0 -214
  168. package/src/__tests__/context-composer-pins.test.ts +0 -64
  169. package/src/__tests__/context-composer-task-selection.test.ts +0 -24
  170. package/src/__tests__/context-reconstructor.test.ts +0 -65
  171. package/src/__tests__/context-renderer.test.ts +0 -91
  172. package/src/__tests__/continuity-eval.test.ts +0 -275
  173. package/src/__tests__/continuity-schema.test.ts +0 -97
  174. package/src/__tests__/conversation-importer.test.ts +0 -692
  175. package/src/__tests__/core-recall-eval.test.ts +0 -235
  176. package/src/__tests__/core-summary.test.ts +0 -109
  177. package/src/__tests__/data-checkup.test.ts +0 -225
  178. package/src/__tests__/decay-exemption.test.ts +0 -84
  179. package/src/__tests__/dedup-actions.test.ts +0 -58
  180. package/src/__tests__/dedup-guard.test.ts +0 -39
  181. package/src/__tests__/deterministic-id.test.ts +0 -39
  182. package/src/__tests__/distill-lock.test.ts +0 -176
  183. package/src/__tests__/doctor.test.ts +0 -303
  184. package/src/__tests__/dream-pipeline.test.ts +0 -232
  185. package/src/__tests__/drill-down.test.ts +0 -108
  186. package/src/__tests__/embedder.test.ts +0 -122
  187. package/src/__tests__/emotion-decay.test.ts +0 -46
  188. package/src/__tests__/emotion-detector.test.ts +0 -56
  189. package/src/__tests__/emotion-phase1-integration.test.ts +0 -153
  190. package/src/__tests__/emotion-retrieval.test.ts +0 -56
  191. package/src/__tests__/entity-resolver.test.ts +0 -58
  192. package/src/__tests__/ethics-layer.test.ts +0 -476
  193. package/src/__tests__/event-segmenter.test.ts +0 -153
  194. package/src/__tests__/feature-flags-integration.test.ts +0 -54
  195. package/src/__tests__/frequency-tracker.test.ts +0 -113
  196. package/src/__tests__/graph-export.test.ts +0 -489
  197. package/src/__tests__/hotness-blend.test.ts +0 -76
  198. package/src/__tests__/ingest.test.ts +0 -360
  199. package/src/__tests__/interference-detector.test.ts +0 -203
  200. package/src/__tests__/kg-extractor.test.ts +0 -184
  201. package/src/__tests__/kg-store.test.ts +0 -198
  202. package/src/__tests__/llm-consolidation.test.ts +0 -226
  203. package/src/__tests__/mcp-efficiency.test.ts +0 -288
  204. package/src/__tests__/memory-boundaries.test.ts +0 -237
  205. package/src/__tests__/memory-evolution-b2-b3-e1.test.ts +0 -243
  206. package/src/__tests__/memory-evolution.test.ts +0 -271
  207. package/src/__tests__/memory-health-rebalance.test.ts +0 -144
  208. package/src/__tests__/memory-lint.test.ts +0 -271
  209. package/src/__tests__/memory-output.test.ts +0 -215
  210. package/src/__tests__/multi-vector.test.ts +0 -242
  211. package/src/__tests__/narrative-architecture.test.ts +0 -456
  212. package/src/__tests__/pending-review.test.ts +0 -77
  213. package/src/__tests__/post-retrieval-filter.test.ts +0 -178
  214. package/src/__tests__/ppr-traversal.test.ts +0 -256
  215. package/src/__tests__/prediction-engine.test.ts +0 -349
  216. package/src/__tests__/predictive-prospective-memory.test.ts +0 -416
  217. package/src/__tests__/preference-guard-smoke.test.ts +0 -211
  218. package/src/__tests__/preference-matcher.test.ts +0 -230
  219. package/src/__tests__/preference-slots.test.ts +0 -205
  220. package/src/__tests__/prospective-memory.test.ts +0 -283
  221. package/src/__tests__/query-entity-detector.test.ts +0 -171
  222. package/src/__tests__/query-expander-alias.test.ts +0 -89
  223. package/src/__tests__/query-expander.test.ts +0 -34
  224. package/src/__tests__/recall-governor.test.ts +0 -227
  225. package/src/__tests__/recall-mode.test.ts +0 -64
  226. package/src/__tests__/result-synthesizer.test.ts +0 -198
  227. package/src/__tests__/resume-context.test.ts +0 -4898
  228. package/src/__tests__/retrieval-trace.test.ts +0 -213
  229. package/src/__tests__/retriever-boundary-weight.test.ts +0 -136
  230. package/src/__tests__/retroactive-boost.test.ts +0 -223
  231. package/src/__tests__/salience-scoring.test.ts +0 -106
  232. package/src/__tests__/scope-inventory.test.ts +0 -200
  233. package/src/__tests__/scope-policy.test.ts +0 -69
  234. package/src/__tests__/session-checkpoint.test.ts +0 -259
  235. package/src/__tests__/session-distiller.test.ts +0 -611
  236. package/src/__tests__/session-gc.test.ts +0 -215
  237. package/src/__tests__/skill-engine.test.ts +0 -546
  238. package/src/__tests__/skill-promotion.test.ts +0 -349
  239. package/src/__tests__/store-scope-audit.test.ts +0 -81
  240. package/src/__tests__/supersede-chain.test.ts +0 -154
  241. package/src/__tests__/temporal-parser.test.ts +0 -241
  242. package/src/__tests__/temporal-validity.test.ts +0 -160
  243. package/src/__tests__/term-registry.test.ts +0 -121
  244. package/src/__tests__/tool-output-compressor.test.ts +0 -133
  245. package/src/__tests__/topic-tag.test.ts +0 -113
  246. package/src/__tests__/trusted-memory.test.ts +0 -828
  247. package/src/__tests__/version-manager.test.ts +0 -213
  248. package/src/__tests__/workflow-observation.test.ts +0 -400
  249. package/src/__tests__/write-verifier.test.ts +0 -122
package/.env ADDED
@@ -0,0 +1,4 @@
1
+ JINA_API_KEY=jina_a953576fa7b746019e57d1370122fb8aNQLVOjq95WHeDBKlBr3JeCj0K5SL
2
+ QWEN_API_KEY=sk-8b8f215de882422a991653d5fc3cc275
3
+ RECALLNEST_EMOTION_SCORING=true
4
+ RECALLNEST_CONSTRUCTIVE_RETRIEVAL=true
package/CLAUDE.md CHANGED
@@ -42,5 +42,5 @@
42
42
  ## 6. 测试基线
43
43
 
44
44
  - 改完代码必须跑 `bun test`,全量通过才能 commit
45
- - 当前基线:1428 tests / 0 fail
45
+ - 当前基线:1486 tests / 0 fail
46
46
  - 新增功能必须配套测试,基线只能涨不能降
package/README.md CHANGED
@@ -10,10 +10,10 @@ A local-first memory system backed by LanceDB that turns scattered conversation
10
10
 
11
11
  [![GitHub](https://img.shields.io/github/stars/AliceLJY/recallnest?style=social)](https://github.com/AliceLJY/recallnest)
12
12
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
13
- [![Bun](https://img.shields.io/badge/Runtime-Bun-f9f1e1?logo=bun)](https://bun.sh)
13
+ [![Runtime](https://img.shields.io/badge/Runtime-Bun_|_Node.js_18+-f9f1e1?logo=bun)](https://bun.sh)
14
14
  [![LanceDB](https://img.shields.io/badge/LanceDB-Vector+FTS-orange)](https://lancedb.com)
15
15
  [![MCP](https://img.shields.io/badge/MCP-41_tools-blue)](https://modelcontextprotocol.io)
16
- [![Tests](https://img.shields.io/badge/Tests-1428_pass-brightgreen)](https://github.com/AliceLJY/recallnest)
16
+ [![Tests](https://img.shields.io/badge/Tests-1486_pass-brightgreen)](https://github.com/AliceLJY/recallnest)
17
17
  [![CC Plugin](https://img.shields.io/badge/Claude_Code-Plugin-blueviolet)](https://github.com/AliceLJY/recallnest)
18
18
 
19
19
  **English** | [简体中文](README_CN.md) | [Roadmap](ROADMAP.md)
@@ -54,9 +54,20 @@ Wins or ties in **all 6 categories**, with no regression. The hybrid retrieval p
54
54
 
55
55
  RecallNest starts automatically with Claude Code. No manual MCP config needed.
56
56
 
57
- > **Requires:** [Bun](https://bun.sh) runtime. Dependencies install on first start.
57
+ > **Requires:** [Bun](https://bun.sh) (recommended) or Node.js 18+. Dependencies install on first start.
58
58
 
59
- ### Option B: Manual setup
59
+ ### Option B: npm install
60
+
61
+ ```bash
62
+ npx recallnest --help # run directly
63
+ # or
64
+ npm install -g recallnest # install globally
65
+ recallnest doctor
66
+ ```
67
+
68
+ Works with Node.js 18+ (via tsx) or Bun. No git clone needed.
69
+
70
+ ### Option C: Manual setup
60
71
 
61
72
  ```bash
62
73
  git clone https://github.com/AliceLJY/recallnest.git
@@ -186,9 +197,11 @@ bun run src/ui-server.ts
186
197
  | **Dashboard** | Web UI with stats, category distribution, growth trends, and health |
187
198
  | **Workflow Observation** | Dedicated append-only workflow health records, outside regular memory |
188
199
  | **Structured Assets** | Pins, briefs, and distilled summaries — not just raw logs |
189
- | **Data Checkup** | Data quality health checks on the memory store |
200
+ | **Data Checkup** | Data quality health checks on the memory store (including source health) |
201
+ | **Source Heartbeats** | Automatic ingest health tracking per data source with staleness alerts |
190
202
  | **Export Graph** | Export interactive HTML knowledge graph visualization |
191
203
  | **Batch Operations** | Store up to 20 memories in a single call with dedup |
204
+ | **Connector Framework** | Standard connector-v1 format for external data sources with example adapters |
192
205
 
193
206
  ---
194
207
 
@@ -222,6 +235,18 @@ v2.1 added philosophy-informed behavior; v2.2 closes the last three engine-layer
222
235
 
223
236
  ---
224
237
 
238
+ ## New in v2.3: Connector Ecosystem + Source Health
239
+
240
+ v2.2 hardened retrieval quality; v2.3 opens RecallNest to external data sources with a standard connector framework and operational health monitoring.
241
+
242
+ - **Connector-v1 Standard** *(GB-2)* — A JSON format (`ConnectorOutputV1`) that any external script can produce. Obsidian vaults, emails, RSS feeds, log files — normalize once, ingest through the full dedup/embed/extract pipeline. See [`docs/connector-spec.md`](docs/connector-spec.md) for the specification and [`connectors/examples/`](connectors/examples/) for adapter skeletons (email, logs, RSS).
243
+
244
+ - **Obsidian Vault Ingestion** *(GB-1)* — First-party Obsidian connector: scans `.md` files, extracts frontmatter + wikilinks, maps folder structure to tags. One command: `lm ingest --obsidian /path/to/vault`.
245
+
246
+ - **Source Health Monitoring** *(GB-3)* — Every connector ingest writes a heartbeat to `data/source-heartbeat.json`. `data_checkup` flags stale sources (>7d warning, >30d error). `doctor --ci` shows a per-source heartbeat summary with human-readable age.
247
+
248
+ ---
249
+
225
250
  ## Architecture
226
251
 
227
252
  ```
package/README_CN.md CHANGED
@@ -10,10 +10,10 @@
10
10
 
11
11
  [![GitHub](https://img.shields.io/github/stars/AliceLJY/recallnest?style=social)](https://github.com/AliceLJY/recallnest)
12
12
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
13
- [![Bun](https://img.shields.io/badge/Runtime-Bun-f9f1e1?logo=bun)](https://bun.sh)
13
+ [![Runtime](https://img.shields.io/badge/Runtime-Bun_|_Node.js_18+-f9f1e1?logo=bun)](https://bun.sh)
14
14
  [![LanceDB](https://img.shields.io/badge/LanceDB-Vector+FTS-orange)](https://lancedb.com)
15
15
  [![MCP](https://img.shields.io/badge/MCP-41_tools-blue)](https://modelcontextprotocol.io)
16
- [![Tests](https://img.shields.io/badge/Tests-1428_pass-brightgreen)](https://github.com/AliceLJY/recallnest)
16
+ [![Tests](https://img.shields.io/badge/Tests-1486_pass-brightgreen)](https://github.com/AliceLJY/recallnest)
17
17
  [![CC Plugin](https://img.shields.io/badge/Claude_Code-Plugin-blueviolet)](https://github.com/AliceLJY/recallnest)
18
18
 
19
19
  [English](README.md) | **简体中文** | [Roadmap](ROADMAP.md)
@@ -54,9 +54,20 @@ RecallNest 的解法:**一个 LanceDB 驱动的记忆层,三个终端共读
54
54
 
55
55
  RecallNest 随 Claude Code 自动启动,无需手动配置 MCP。
56
56
 
57
- > **前置要求:** 安装 [Bun](https://bun.sh) 运行时。首次启动自动安装依赖。
57
+ > **前置要求:** [Bun](https://bun.sh)(推荐)或 Node.js 18+。首次启动自动安装依赖。
58
58
 
59
- ### 方式 B:手动安装
59
+ ### 方式 B:npm 安装
60
+
61
+ ```bash
62
+ npx recallnest --help # 直接运行
63
+ # 或
64
+ npm install -g recallnest # 全局安装
65
+ recallnest doctor
66
+ ```
67
+
68
+ 支持 Node.js 18+(通过 tsx)或 Bun,无需 clone 仓库。
69
+
70
+ ### 方式 C:手动安装
60
71
 
61
72
  ```bash
62
73
  git clone https://github.com/AliceLJY/recallnest.git
@@ -186,9 +197,11 @@ bun run src/ui-server.ts
186
197
  | **Dashboard** | Web UI 首页:统计卡片、类别分布、增长趋势、健康概览 |
187
198
  | **Workflow Observation** | 专门的 append-only 工作流观测层,不混入普通 memory |
188
199
  | **结构化资产** | Pin、Brief、Distill —— 不只是原始日志 |
189
- | **Data Checkup** | 记忆存储数据质量健康检查 |
200
+ | **Data Checkup** | 记忆存储数据质量健康检查(含数据源健康) |
201
+ | **数据源心跳** | 按数据源自动追踪 ingest 健康状态,过期告警 |
190
202
  | **导出图谱** | 导出交互式 HTML 知识图谱可视化 |
191
203
  | **批量操作** | 单次调用存储最多 20 条记忆,自带去重 |
204
+ | **Connector 框架** | 标准 connector-v1 格式接入外部数据源,附带适配器示例 |
192
205
 
193
206
  ---
194
207
 
@@ -222,6 +235,18 @@ v2.1 加入了哲学记忆行为;v2.2 补齐前沿扫描(ACC、PI-LLM、TSM
222
235
 
223
236
  ---
224
237
 
238
+ ## v2.3 新增:Connector 生态 + 数据源健康
239
+
240
+ v2.2 强化了检索质量;v2.3 通过标准 Connector 框架和运维健康监控,把 RecallNest 开放给外部数据源。
241
+
242
+ - **Connector-v1 标准** *(GB-2)* —— 一套 JSON 格式(`ConnectorOutputV1`),任何外部脚本都可以输出。Obsidian 笔记、邮件、RSS、日志文件——标准化一次,走完整的 dedup/embed/extract 管线入库。规范见 [`docs/connector-spec.md`](docs/connector-spec.md),适配器骨架见 [`connectors/examples/`](connectors/examples/)(email、logs、RSS)。
243
+
244
+ - **Obsidian Vault 接入** *(GB-1)* —— 官方 Obsidian 连接器:扫描 `.md` 文件,提取 frontmatter + wikilink,文件夹结构映射为 tag。一条命令:`lm ingest --obsidian /path/to/vault`。
245
+
246
+ - **数据源健康监控** *(GB-3)* —— 每次 connector ingest 写心跳到 `data/source-heartbeat.json`。`data_checkup` 标记过期数据源(>7 天 warning,>30 天 error)。`doctor --ci` 按数据源展示心跳摘要(如"obsidian: 2h ago")。
247
+
248
+ ---
249
+
225
250
  ## 架构
226
251
 
227
252
  ```
package/config.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "dbPath": "./data/lancedb",
3
+ "recallMode": "full",
4
+ "embedding": {
5
+ "provider": "jina",
6
+ "apiKey": "${JINA_API_KEY}",
7
+ "model": "jina-embeddings-v5-text-small",
8
+ "baseURL": "https://api.jina.ai/v1",
9
+ "dimensions": 1024,
10
+ "taskQuery": "retrieval.query",
11
+ "taskPassage": "retrieval.passage"
12
+ },
13
+ "llm": {
14
+ "apiKey": "${QWEN_API_KEY}",
15
+ "model": "qwen-turbo",
16
+ "baseURL": "https://dashscope.aliyuncs.com/compatible-mode/v1"
17
+ },
18
+ "sources": {
19
+ "cc": {
20
+ "path": "auto",
21
+ "glob": "*.jsonl",
22
+ "description": "Claude Code transcripts"
23
+ },
24
+ "codex": {
25
+ "path": "~/.codex/sessions",
26
+ "glob": "*.jsonl",
27
+ "description": "Codex sessions"
28
+ },
29
+ "memory": {
30
+ "path": "auto",
31
+ "glob": "*.md",
32
+ "description": "Claude Code memory files"
33
+ },
34
+ "gemini": {
35
+ "path": "~/.gemini/tmp",
36
+ "glob": "session-*.json",
37
+ "description": "Gemini CLI sessions"
38
+ },
39
+ "desktop": {
40
+ "path": "./data/desktop-import",
41
+ "glob": "*.jsonl",
42
+ "description": "Claude Desktop / claude.ai web conversations"
43
+ }
44
+ },
45
+ "retrieval": {
46
+ "mode": "hybrid",
47
+ "vectorWeight": 0.6,
48
+ "bm25Weight": 0.4,
49
+ "recencyHalfLifeDays": 30,
50
+ "timeDecayHalfLifeDays": 60,
51
+ "hardMinScore": 0.38,
52
+ "hotnessWeight": 0.15
53
+ },
54
+ "recallDepthDefault": "l1"
55
+ }
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Email Connector Adapter (skeleton)
4
+ *
5
+ * Demonstrates how to produce a ConnectorOutputV1 JSON file from an email
6
+ * source (IMAP, Gmail API, local mbox, etc.) for RecallNest ingestion.
7
+ *
8
+ * Usage:
9
+ * bun run connectors/examples/email-adapter.ts > email-output.json
10
+ * lm ingest --connector email-output.json
11
+ *
12
+ * Customize:
13
+ * 1. Replace the fetchEmails() stub with your IMAP/API client
14
+ * 2. Adjust scope to match your project naming
15
+ * 3. Set categoryHint based on email type (meeting invite → "events", etc.)
16
+ */
17
+
18
+ import type { ConnectorOutputV1 } from "../../src/connector-types.js";
19
+ import { createHash } from "node:crypto";
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // TODO: Replace with real email fetching logic
23
+ // ---------------------------------------------------------------------------
24
+
25
+ interface RawEmail {
26
+ messageId: string;
27
+ subject: string;
28
+ body: string;
29
+ from: string;
30
+ date: string; // ISO 8601
31
+ }
32
+
33
+ async function fetchEmails(_since: Date): Promise<RawEmail[]> {
34
+ // Example: use imapflow, googleapis, or read from .mbox
35
+ // const client = new ImapFlow({ host: 'imap.example.com', ... });
36
+ // await client.connect();
37
+ // const messages = await client.fetch(...);
38
+ return []; // Replace with real implementation
39
+ }
40
+
41
+ // ---------------------------------------------------------------------------
42
+ // Transform → ConnectorOutputV1
43
+ // ---------------------------------------------------------------------------
44
+
45
+ async function main() {
46
+ const since = new Date(Date.now() - 7 * 86_400_000); // last 7 days
47
+ const emails = await fetchEmails(since);
48
+
49
+ const output: ConnectorOutputV1 = {
50
+ version: "connector-v1",
51
+ source: "email",
52
+ scope: "inbox:personal", // Customize: "inbox:work", "project:xyz"
53
+ producedAt: new Date().toISOString(),
54
+ records: emails.map((email) => ({
55
+ id: `email:${email.messageId}`,
56
+ text: email.body,
57
+ title: email.subject,
58
+ categoryHint: "events", // Customize per email type
59
+ importanceHint: 0.6, // Customize: 0.9 for flagged/starred
60
+ tags: ["email", `from:${email.from}`],
61
+ timestamp: email.date,
62
+ contentHash: createHash("sha256").update(email.body).digest("hex"),
63
+ sourceMetadata: {
64
+ from: email.from,
65
+ messageId: email.messageId,
66
+ },
67
+ })),
68
+ };
69
+
70
+ console.log(JSON.stringify(output, null, 2));
71
+ }
72
+
73
+ main().catch(console.error);
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Log File Connector Adapter (skeleton)
4
+ *
5
+ * Demonstrates how to produce a ConnectorOutputV1 JSON file from application
6
+ * log files for RecallNest ingestion. Useful for tracking deploy events,
7
+ * error patterns, and operational decisions.
8
+ *
9
+ * Usage:
10
+ * bun run connectors/examples/logs-adapter.ts /var/log/myapp/*.log > logs-output.json
11
+ * lm ingest --connector logs-output.json
12
+ *
13
+ * Customize:
14
+ * 1. Replace parseLogLine() with your log format parser
15
+ * 2. Adjust the importance/category logic for your use case
16
+ * 3. Set scope to match your project
17
+ */
18
+
19
+ import type { ConnectorOutputV1 } from "../../src/connector-types.js";
20
+ import { readFileSync } from "node:fs";
21
+ import { createHash } from "node:crypto";
22
+
23
+ // ---------------------------------------------------------------------------
24
+ // TODO: Replace with your log format parser
25
+ // ---------------------------------------------------------------------------
26
+
27
+ interface ParsedLogEntry {
28
+ timestamp: string; // ISO 8601
29
+ level: "info" | "warn" | "error" | "debug";
30
+ message: string;
31
+ source?: string; // e.g. module name, service
32
+ }
33
+
34
+ function parseLogLine(line: string): ParsedLogEntry | null {
35
+ // Example: "2026-04-14T10:00:00Z [ERROR] auth: login failed for user@example.com"
36
+ const match = line.match(
37
+ /^(\d{4}-\d{2}-\d{2}T[\d:.]+Z?)\s+\[(\w+)]\s+(?:(\w+):\s+)?(.+)$/,
38
+ );
39
+ if (!match) return null;
40
+ return {
41
+ timestamp: match[1],
42
+ level: match[2].toLowerCase() as ParsedLogEntry["level"],
43
+ source: match[3],
44
+ message: match[4],
45
+ };
46
+ }
47
+
48
+ function levelToImportance(level: string): number {
49
+ switch (level) {
50
+ case "error": return 0.9;
51
+ case "warn": return 0.7;
52
+ case "info": return 0.5;
53
+ default: return 0.3;
54
+ }
55
+ }
56
+
57
+ // ---------------------------------------------------------------------------
58
+ // Transform → ConnectorOutputV1
59
+ // ---------------------------------------------------------------------------
60
+
61
+ function main() {
62
+ const files = process.argv.slice(2);
63
+ if (files.length === 0) {
64
+ console.error("Usage: logs-adapter.ts <logfile> [logfile...]");
65
+ process.exit(1);
66
+ }
67
+
68
+ const records: ConnectorOutputV1["records"] = [];
69
+
70
+ for (const file of files) {
71
+ const lines = readFileSync(file, "utf-8").split("\n").filter(Boolean);
72
+ for (const line of lines) {
73
+ const entry = parseLogLine(line);
74
+ if (!entry) continue;
75
+
76
+ // Skip debug-level by default — too noisy for memory storage
77
+ if (entry.level === "debug") continue;
78
+
79
+ records.push({
80
+ id: `log:${createHash("md5").update(line).digest("hex")}`,
81
+ text: entry.message,
82
+ title: entry.source ? `[${entry.level.toUpperCase()}] ${entry.source}` : undefined,
83
+ categoryHint: entry.level === "error" ? "cases" : "events",
84
+ importanceHint: levelToImportance(entry.level),
85
+ tags: ["log", entry.level, ...(entry.source ? [`module:${entry.source}`] : [])],
86
+ timestamp: entry.timestamp,
87
+ contentHash: createHash("sha256").update(line).digest("hex"),
88
+ });
89
+ }
90
+ }
91
+
92
+ const output: ConnectorOutputV1 = {
93
+ version: "connector-v1",
94
+ source: "logs",
95
+ scope: "ops:myapp", // Customize: "project:xyz", "ops:production"
96
+ producedAt: new Date().toISOString(),
97
+ records,
98
+ };
99
+
100
+ console.log(JSON.stringify(output, null, 2));
101
+ }
102
+
103
+ main();
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * RSS Feed Connector Adapter (skeleton)
4
+ *
5
+ * Demonstrates how to produce a ConnectorOutputV1 JSON file from RSS/Atom
6
+ * feeds for RecallNest ingestion. Useful for tracking industry news,
7
+ * blog posts, and research updates.
8
+ *
9
+ * Usage:
10
+ * bun run connectors/examples/rss-adapter.ts > rss-output.json
11
+ * lm ingest --connector rss-output.json
12
+ *
13
+ * Customize:
14
+ * 1. Replace fetchFeed() with your RSS parsing library (e.g. rss-parser)
15
+ * 2. Adjust feed URLs and scope
16
+ * 3. Set categoryHint / importanceHint based on feed type
17
+ */
18
+
19
+ import type { ConnectorOutputV1 } from "../../src/connector-types.js";
20
+ import { createHash } from "node:crypto";
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // TODO: Replace with real RSS/Atom parsing
24
+ // ---------------------------------------------------------------------------
25
+
26
+ interface FeedItem {
27
+ guid: string;
28
+ title: string;
29
+ content: string; // HTML stripped to plain text
30
+ link: string;
31
+ pubDate: string; // ISO 8601
32
+ categories?: string[];
33
+ }
34
+
35
+ interface FeedConfig {
36
+ url: string;
37
+ scope: string; // e.g. "feeds:ai-news"
38
+ categoryHint?: string;
39
+ importanceHint?: number;
40
+ }
41
+
42
+ const FEEDS: FeedConfig[] = [
43
+ // Add your feeds here:
44
+ // { url: "https://example.com/feed.xml", scope: "feeds:example" },
45
+ ];
46
+
47
+ async function fetchFeed(_url: string): Promise<FeedItem[]> {
48
+ // Example with rss-parser:
49
+ // import Parser from "rss-parser";
50
+ // const parser = new Parser();
51
+ // const feed = await parser.parseURL(url);
52
+ // return feed.items.map(item => ({ ... }));
53
+ return []; // Replace with real implementation
54
+ }
55
+
56
+ // ---------------------------------------------------------------------------
57
+ // Transform → ConnectorOutputV1
58
+ // ---------------------------------------------------------------------------
59
+
60
+ async function main() {
61
+ for (const feed of FEEDS) {
62
+ const items = await fetchFeed(feed.url);
63
+
64
+ const output: ConnectorOutputV1 = {
65
+ version: "connector-v1",
66
+ source: "rss",
67
+ scope: feed.scope,
68
+ producedAt: new Date().toISOString(),
69
+ records: items.map((item) => ({
70
+ id: `rss:${createHash("md5").update(item.guid || item.link).digest("hex")}`,
71
+ text: item.content,
72
+ title: item.title,
73
+ categoryHint: feed.categoryHint ?? "knowledge",
74
+ importanceHint: feed.importanceHint ?? 0.6,
75
+ tags: [
76
+ "rss",
77
+ ...(item.categories ?? []),
78
+ `link:${item.link}`,
79
+ ],
80
+ timestamp: item.pubDate,
81
+ contentHash: createHash("sha256").update(item.content).digest("hex"),
82
+ sourceMetadata: {
83
+ feedUrl: feed.url,
84
+ link: item.link,
85
+ guid: item.guid,
86
+ },
87
+ })),
88
+ };
89
+
90
+ // Each feed outputs one JSON — pipe to separate files if needed
91
+ console.log(JSON.stringify(output, null, 2));
92
+ }
93
+ }
94
+
95
+ main().catch(console.error);
File without changes
@@ -0,0 +1,60 @@
1
+ === 2026-04-12 08:00:01 daily-recall 开始 ===
2
+ === 2026-04-12 08:00:01 daily-recall 开始 ===
3
+ 今日主题 (#7): 踩坑 修复 经验总结
4
+ 今日主题 (#7): 踩坑 修复 经验总结
5
+ 检查 distill gate...
6
+ 检查 distill gate...
7
+ distill gate:
8
+ distill gate:
9
+ 执行 distill...
10
+ 执行 distill...
11
+ distill 完成,27 行
12
+ distill 完成,27 行
13
+ [完成] 回顾已写入: /Users/anxianjingya/recallnest/daily-reflections/2026-04-12.md
14
+ [完成] 回顾已写入: /Users/anxianjingya/recallnest/daily-reflections/2026-04-12.md
15
+ 执行 checkpoint-gc...
16
+ 执行 checkpoint-gc...
17
+ checkpoint-gc: === Checkpoint GC ===
18
+
19
+ Kept : 217
20
+ Archived : 0
21
+ Deleted : 0
22
+ Errors : 0
23
+ checkpoint-gc: === Checkpoint GC ===
24
+
25
+ Kept : 217
26
+ Archived : 0
27
+ Deleted : 0
28
+ Errors : 0
29
+ === 2026-04-12 08:00:13 daily-recall 结束 ===
30
+ === 2026-04-12 08:00:13 daily-recall 结束 ===
31
+ === 2026-04-13 08:00:01 daily-recall 开始 ===
32
+ === 2026-04-13 08:00:01 daily-recall 开始 ===
33
+ 今日主题 (#1): 成长 经历 改变了什么
34
+ 今日主题 (#1): 成长 经历 改变了什么
35
+ 检查 distill gate...
36
+ 检查 distill gate...
37
+ distill gate:
38
+ distill gate:
39
+ 执行 distill...
40
+ 执行 distill...
41
+ distill 完成,31 行
42
+ distill 完成,31 行
43
+ [完成] 回顾已写入: /Users/anxianjingya/recallnest/daily-reflections/2026-04-13.md
44
+ [完成] 回顾已写入: /Users/anxianjingya/recallnest/daily-reflections/2026-04-13.md
45
+ 执行 checkpoint-gc...
46
+ 执行 checkpoint-gc...
47
+ checkpoint-gc: === Checkpoint GC ===
48
+
49
+ Kept : 218
50
+ Archived : 0
51
+ Deleted : 0
52
+ Errors : 0
53
+ checkpoint-gc: === Checkpoint GC ===
54
+
55
+ Kept : 218
56
+ Archived : 0
57
+ Deleted : 0
58
+ Errors : 0
59
+ === 2026-04-13 08:00:22 daily-recall 结束 ===
60
+ === 2026-04-13 08:00:22 daily-recall 结束 ===
@@ -0,0 +1,110 @@
1
+ === 2026-04-11 19:22:04 增量更新开始 ===
2
+ [INFO] LLM client initialized: qwen-turbo @ https://dashscope.aliyuncs.com/compatible-mode/v1
3
+
4
+ 🔑 验证 Embedding API...
5
+ ✅ jina-embeddings-v5-text-small (1024d)
6
+ ✅ LLM: qwen-turbo (L0 摘要 + 语义去重)
7
+ ✅ 两阶段去重: vector + LLM 语义判断
8
+
9
+ 🔄 开始导入记忆 (source: all)...
10
+
11
+ 📝 导入 Claude Code 对话...
12
+ CC: 230/962 files, 120 chunks ingested
13
+ CC: 470/962 files, 186 chunks ingested
14
+ [INFO] noise-filter: denial pattern matched: "**Phase 5: Predictive Prospective Memory — DONE** ✅
15
+
16
+ 总结一下做了什..."
17
+ ✅ CC: 24 files, 528 ingested, 474 deduped (hard:17, exact:160, llm-skip:150, llm-merge:147), 0 errors
18
+ 🤖 导入 Codex 对话...
19
+ [INFO] noise-filter: meta-question filtered: "# AGENTS.md instructions for /Users/anxianjingya/Projects/re..."
20
+ [INFO] noise-filter: meta-question filtered: "# AGENTS.md instructions for /Users/anxianjingya
21
+
22
+ <INSTRUCTI..."
23
+ Codex: 294/294 files, 39 chunks ingested
24
+ ✅ Codex: 2 files, 39 ingested, 22 deduped (hard:6, exact:0, llm-skip:8, llm-merge:8), 0 errors
25
+ 💎 导入 Gemini 对话...
26
+ ✅ Gemini: 0 files, 0 ingested, 0 deduped (hard:0, exact:0, llm-skip:0, llm-merge:0), 0 errors
27
+ 🖥️ 导入 Claude Desktop 对话...
28
+ CC: 10/349 files, 43 chunks ingested
29
+ [INFO] noise-filter: denial pattern matched: "好的!我来手把手教你!别担心,超简单! 😊
30
+
31
+ ---
32
+
33
+ ## 📍 **Step 1: 找到文件在哪**
34
+
35
+ 我刚才给你..."
36
+ CC: 20/349 files, 70 chunks ingested
37
+ CC: 30/349 files, 73 chunks ingested
38
+ [INFO] noise-filter: short boilerplate filtered: "好的,我来帮你截图。"
39
+ CC: 40/349 files, 160 chunks ingested
40
+ CC: 50/349 files, 180 chunks ingested
41
+ CC: 60/349 files, 226 chunks ingested
42
+ CC: 70/349 files, 256 chunks ingested
43
+ [INFO] noise-filter: meta-question filtered: "你记不记得我让你帮我弄孩子们的简历..."
44
+ [INFO] noise-filter: denial pattern matched: "我查找一下我们之前关于孩子们简历的对话...
45
+
46
+ 让我搜索一下相关内容。
47
+
48
+ 我没有找到我们之前讨论过帮孩子们制作简历的记录..."
49
+ CC: 80/349 files, 316 chunks ingested
50
+ CC: 90/349 files, 335 chunks ingested
51
+ CC: 100/349 files, 412 chunks ingested
52
+ CC: 110/349 files, 501 chunks ingested
53
+ CC: 120/349 files, 520 chunks ingested
54
+ [INFO] noise-filter: boilerplate filtered: "Hello! How can I help you today?..."
55
+ [INFO] noise-filter: denial pattern matched: "不能。我无法访问你本地电脑上的文件或 Claude Code 的 session 记录。
56
+
57
+ 我能访问的是:
58
+ 1. **我..."
59
+ [INFO] noise-filter: denial pattern matched: "这个我不太确定,因为 Claude Desktop 的会话索引存在 `~/Library/Application Sup..."
60
+ [INFO] noise-filter: boilerplate filtered: "Hi Alice,
61
+ I understand you're looking for a way to rebuild t..."
62
+ CC: 130/349 files, 547 chunks ingested
63
+ CC: 140/349 files, 585 chunks ingested
64
+ [INFO] noise-filter: denial pattern matched: "啊,你说得对!我理解错了。
65
+
66
+ 让我重新想想这个问题...
67
+
68
+ Antigravity 确实也是通过 Claude in C..."
69
+ CC: 150/349 files, 618 chunks ingested
70
+ [INFO] noise-filter: denial pattern matched: "我来帮你查看workspace里的PPT相关文件,分析其逻辑是否与截图中描述的一致。
71
+
72
+ 让我先看看目录结构:
73
+ 我看到wo..."
74
+ CC: 160/349 files, 659 chunks ingested
75
+ CC: 170/349 files, 681 chunks ingested
76
+ [INFO] noise-filter: denial pattern matched: "我不确定Claude Opus 4.5的具体知识截止日期是否与我的相同。
77
+
78
+ 让我搜索一下Anthropic官方文档来确认..."
79
+ CC: 180/349 files, 685 chunks ingested
80
+ CC: 190/349 files, 694 chunks ingested
81
+ CC: 210/349 files, 919 chunks ingested
82
+ CC: 220/349 files, 927 chunks ingested
83
+ CC: 230/349 files, 956 chunks ingested
84
+ CC: 240/349 files, 977 chunks ingested
85
+ CC: 250/349 files, 1018 chunks ingested
86
+ CC: 260/349 files, 1030 chunks ingested
87
+ CC: 270/349 files, 1048 chunks ingested
88
+ CC: 280/349 files, 1185 chunks ingested
89
+ CC: 290/349 files, 1196 chunks ingested
90
+ [INFO] noise-filter: boilerplate filtered: "Hi Alice! Here's what I've learned about you from our past c..."
91
+ CC: 300/349 files, 1211 chunks ingested
92
+ CC: 310/349 files, 1243 chunks ingested
93
+ CC: 320/349 files, 1276 chunks ingested
94
+ [INFO] noise-filter: denial pattern matched: "我想不起来给你的这些提示词和视觉skill是哪里来的..."
95
+ [INFO] noise-filter: denial pattern matched: "* 全网AI集体翻车?为了读一篇公众号文章,我扒开了Grok的“谎言”
96
+ * Gemini、Claude、元宝全试了,竟..."
97
+ [INFO] noise-filter: denial pattern matched: "让我先查看歌舞剧院的总结,提取人才相关数据:
98
+ 好的,我现在已经了解了录音中领导的修改意见和两家院团的总结内容。根据领导的..."
99
+ CC: 330/349 files, 1331 chunks ingested
100
+ CC: 340/349 files, 1348 chunks ingested
101
+ CC: 349/349 files, 1372 chunks ingested
102
+ ✅ Desktop: 343 files, 1372 ingested, 3805 deduped (hard:440, exact:1721, llm-skip:1045, llm-merge:599), 0 errors
103
+ 📚 导入记忆文件...
104
+ ✅ Memory: 8 files, 11 ingested, 279 deduped (hard:0, exact:257, llm-skip:15, llm-merge:7), 0 errors
105
+
106
+ 📊 导入汇总:
107
+ 总计: 1950 chunks 已索引, 4580 chunks 去重 (hard:463, exact:2138, llm-skip:1218, llm-merge:761), 0 errors
108
+
109
+ === 2026-04-11 20:37:10 增量更新完成 ===
110
+