recallnest 1.4.1

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 (261) hide show
  1. package/.claude-plugin/CLAUDE.md +29 -0
  2. package/.claude-plugin/marketplace.json +18 -0
  3. package/.env.example +3 -0
  4. package/.github/workflows/ci.yml +28 -0
  5. package/.mcp.json +9 -0
  6. package/CHANGELOG.md +51 -0
  7. package/CLAUDE.md +42 -0
  8. package/DEMO.md +94 -0
  9. package/EVAL.md +89 -0
  10. package/FAILURES.md +75 -0
  11. package/LICENSE +21 -0
  12. package/OPERATIONS.md +59 -0
  13. package/README.md +427 -0
  14. package/README_CN.md +425 -0
  15. package/ROADMAP.md +198 -0
  16. package/assets/recallnest-workbench.png +0 -0
  17. package/assets/ui/app.js +807 -0
  18. package/assets/ui/index.html +154 -0
  19. package/assets/ui/styles.css +605 -0
  20. package/assets/wechat-qr.jpg +0 -0
  21. package/config.json.example +38 -0
  22. package/daily-recall.sh +87 -0
  23. package/daily-reflections/2026-03-05.md +15 -0
  24. package/daily-reflections/2026-03-06.md +15 -0
  25. package/daily-reflections/2026-03-07.md +7 -0
  26. package/daily-reflections/2026-03-08.md +34 -0
  27. package/daily-reflections/2026-03-09.md +35 -0
  28. package/daily-reflections/2026-03-10.md +36 -0
  29. package/daily-reflections/2026-03-11.md +35 -0
  30. package/daily-reflections/2026-03-12.md +36 -0
  31. package/daily-reflections/2026-03-13.md +35 -0
  32. package/daily-reflections/2026-03-14.md +35 -0
  33. package/daily-reflections/2026-03-15.md +35 -0
  34. package/daily-reflections/2026-03-16.md +41 -0
  35. package/daily-reflections/2026-03-17.md +10 -0
  36. package/daily-reflections/2026-03-18.md +10 -0
  37. package/daily-reflections/2026-03-19.md +10 -0
  38. package/daily-reflections/2026-03-20.md +10 -0
  39. package/daily-reflections/2026-03-21.md +10 -0
  40. package/daily-reflections/2026-03-22.md +10 -0
  41. package/daily-reflections/2026-03-23.md +10 -0
  42. package/daily-reflections/2026-03-24.md +10 -0
  43. package/daily-reflections/2026-03-25.md +32 -0
  44. package/daily-reflections/2026-03-26.md +37 -0
  45. package/daily-reflections/2026-03-27.md +35 -0
  46. package/daily-reflections/2026-03-28.md +35 -0
  47. package/daily-reflections/2026-03-29.md +35 -0
  48. package/daily-reflections/2026-03-30.md +36 -0
  49. package/daily-reflections/2026-03-31.md +35 -0
  50. package/daily-reflections/2026-04-01.md +35 -0
  51. package/docs/api-reference.md +1291 -0
  52. package/docs/architecture.md +168 -0
  53. package/docs/memory-boundary-contract.md +226 -0
  54. package/docs/memory-categories.md +119 -0
  55. package/docs/pipeline-audit-ultramemory.md +177 -0
  56. package/docs/plans/2026-03-08-query-expansion.md +270 -0
  57. package/docs/plans/2026-03-16-continuity-layer.md +196 -0
  58. package/docs/plans/mcp-tiering-plan.md +126 -0
  59. package/docs/research/recall-quality-audit-2026-03-22.md +153 -0
  60. package/docs/self-evolution.md +198 -0
  61. package/docs/superpowers/plans/2026-03-19-ingest-pipeline-upgrade.md +782 -0
  62. package/docs/superpowers/specs/2026-03-19-ingest-pipeline-upgrade-design.md +77 -0
  63. package/docs/superpowers/specs/2026-03-23-pull-claude-desktop-design.md +95 -0
  64. package/eval/cases.json +85 -0
  65. package/eval/continuity/case-seeds.json +90 -0
  66. package/eval/continuity/cases.json +302 -0
  67. package/eval/continuity/memory-seeds.json +26 -0
  68. package/eval/continuity/pattern-seeds.json +100 -0
  69. package/eval/continuity/results-2026-03-16.md +117 -0
  70. package/eval/continuity/results-2026-03-19.md +453 -0
  71. package/eval/continuity/runbook.md +110 -0
  72. package/eval/continuity/seed-cases.md +54 -0
  73. package/eval/reports/2026-03-06-abstract-query-baseline.md +96 -0
  74. package/eval/reports/2026-03-06-aws-ssh-baseline.md +82 -0
  75. package/eval/reports/2026-03-06-baseline.md +82 -0
  76. package/eval/reports/query-expansion.md +138 -0
  77. package/integrations/README.md +57 -0
  78. package/integrations/claude-code/README.md +133 -0
  79. package/integrations/claude-code/claude-md-snippet.md +31 -0
  80. package/integrations/claude-code/setup.sh +66 -0
  81. package/integrations/claude-code/smoke-continuity.sh +452 -0
  82. package/integrations/codex/README.md +49 -0
  83. package/integrations/codex/agents-md-snippet.md +31 -0
  84. package/integrations/codex/setup.sh +58 -0
  85. package/integrations/examples/claude-agent-sdk/memory-agent.ts +182 -0
  86. package/integrations/examples/langchain/memory-chain.py +111 -0
  87. package/integrations/examples/openai-agents-sdk/memory-agent.py +109 -0
  88. package/integrations/gemini-cli/README.md +57 -0
  89. package/integrations/gemini-cli/gemini-md-snippet.md +31 -0
  90. package/integrations/gemini-cli/setup.sh +64 -0
  91. package/integrations/shared/install-managed-block.sh +51 -0
  92. package/lm +19 -0
  93. package/package.json +50 -0
  94. package/plan-v1.2-distributable.md +105 -0
  95. package/scripts/archive-distilled-junk.ts +116 -0
  96. package/scripts/backfill-l0l1l2.ts +98 -0
  97. package/scripts/blind-scan.ts +588 -0
  98. package/scripts/cleanup-step1-exact-dups.ts +117 -0
  99. package/scripts/cleanup-step2-template-dups.ts +113 -0
  100. package/scripts/cleanup-step3-stale-content.ts +149 -0
  101. package/scripts/cleanup-step4-orphan-scopes.ts +131 -0
  102. package/scripts/delete-distilled-junk.ts +88 -0
  103. package/scripts/distill-facts.ts +305 -0
  104. package/scripts/health-check.ts +343 -0
  105. package/scripts/incremental-ingest.sh +71 -0
  106. package/scripts/mlp-health-check.ts +382 -0
  107. package/scripts/pull-claude-desktop.ts +515 -0
  108. package/scripts/re-ingest-cc.sh +66 -0
  109. package/scripts/rebalance-memory-health.ts +181 -0
  110. package/scripts/run-desktop-ingest.sh +11 -0
  111. package/scripts/start-server.sh +12 -0
  112. package/scripts/viz-dashboard.html +423 -0
  113. package/scripts/viz-export.ts +703 -0
  114. package/src/__tests__/access-tracker-novelty.test.ts +228 -0
  115. package/src/__tests__/auto-consolidation.test.ts +168 -0
  116. package/src/__tests__/auto-recall.test.ts +131 -0
  117. package/src/__tests__/batch-dedup.test.ts +65 -0
  118. package/src/__tests__/capture-engine.test.ts +1142 -0
  119. package/src/__tests__/capture-heuristic.test.ts +171 -0
  120. package/src/__tests__/cascade-forget.test.ts +210 -0
  121. package/src/__tests__/category-min-scores.test.ts +33 -0
  122. package/src/__tests__/confidence-tracker.test.ts +196 -0
  123. package/src/__tests__/conflict-advisor.test.ts +206 -0
  124. package/src/__tests__/conflict-escalation.test.ts +149 -0
  125. package/src/__tests__/conflict-lifecycle.test.ts +83 -0
  126. package/src/__tests__/conflict-output.test.ts +85 -0
  127. package/src/__tests__/conflict-store.test.ts +374 -0
  128. package/src/__tests__/consolidation-engine.test.ts +181 -0
  129. package/src/__tests__/context-composer-pins.test.ts +64 -0
  130. package/src/__tests__/context-composer-task-selection.test.ts +24 -0
  131. package/src/__tests__/context-renderer.test.ts +91 -0
  132. package/src/__tests__/continuity-eval.test.ts +275 -0
  133. package/src/__tests__/continuity-schema.test.ts +97 -0
  134. package/src/__tests__/core-recall-eval.test.ts +235 -0
  135. package/src/__tests__/core-summary.test.ts +109 -0
  136. package/src/__tests__/dedup-actions.test.ts +58 -0
  137. package/src/__tests__/deterministic-id.test.ts +39 -0
  138. package/src/__tests__/doctor.test.ts +303 -0
  139. package/src/__tests__/drill-down.test.ts +108 -0
  140. package/src/__tests__/embedder.test.ts +122 -0
  141. package/src/__tests__/entity-resolver.test.ts +58 -0
  142. package/src/__tests__/event-segmenter.test.ts +153 -0
  143. package/src/__tests__/hotness-blend.test.ts +76 -0
  144. package/src/__tests__/ingest.test.ts +360 -0
  145. package/src/__tests__/kg-extractor.test.ts +184 -0
  146. package/src/__tests__/kg-store.test.ts +198 -0
  147. package/src/__tests__/llm-consolidation.test.ts +226 -0
  148. package/src/__tests__/memory-boundaries.test.ts +237 -0
  149. package/src/__tests__/memory-health-rebalance.test.ts +144 -0
  150. package/src/__tests__/memory-output.test.ts +215 -0
  151. package/src/__tests__/multi-vector.test.ts +242 -0
  152. package/src/__tests__/ppr-traversal.test.ts +256 -0
  153. package/src/__tests__/preference-guard-smoke.test.ts +211 -0
  154. package/src/__tests__/preference-matcher.test.ts +230 -0
  155. package/src/__tests__/preference-slots.test.ts +106 -0
  156. package/src/__tests__/prospective-memory.test.ts +283 -0
  157. package/src/__tests__/query-entity-detector.test.ts +171 -0
  158. package/src/__tests__/query-expander.test.ts +34 -0
  159. package/src/__tests__/recall-mode.test.ts +64 -0
  160. package/src/__tests__/result-synthesizer.test.ts +198 -0
  161. package/src/__tests__/resume-context.test.ts +4743 -0
  162. package/src/__tests__/retrieval-trace.test.ts +213 -0
  163. package/src/__tests__/retriever-boundary-weight.test.ts +136 -0
  164. package/src/__tests__/retroactive-boost.test.ts +223 -0
  165. package/src/__tests__/scope-inventory.test.ts +200 -0
  166. package/src/__tests__/scope-policy.test.ts +69 -0
  167. package/src/__tests__/session-checkpoint.test.ts +259 -0
  168. package/src/__tests__/session-gc.test.ts +215 -0
  169. package/src/__tests__/store-scope-audit.test.ts +81 -0
  170. package/src/__tests__/temporal-parser.test.ts +241 -0
  171. package/src/__tests__/term-registry.test.ts +121 -0
  172. package/src/__tests__/tool-output-compressor.test.ts +133 -0
  173. package/src/__tests__/version-manager.test.ts +213 -0
  174. package/src/__tests__/workflow-observation.test.ts +400 -0
  175. package/src/access-tracker.ts +316 -0
  176. package/src/adaptive-retrieval.ts +64 -0
  177. package/src/api-server.ts +667 -0
  178. package/src/asset-sync.ts +79 -0
  179. package/src/auto-consolidation.ts +133 -0
  180. package/src/auto-gc.ts +124 -0
  181. package/src/auto-recall.ts +95 -0
  182. package/src/capture-engine.ts +931 -0
  183. package/src/capture-heuristic.ts +177 -0
  184. package/src/cascade-forget.ts +135 -0
  185. package/src/chunker.ts +253 -0
  186. package/src/cli.ts +1917 -0
  187. package/src/confidence-tracker.ts +166 -0
  188. package/src/conflict-advisor.ts +433 -0
  189. package/src/conflict-engine.ts +181 -0
  190. package/src/conflict-escalation.ts +138 -0
  191. package/src/conflict-lifecycle.ts +67 -0
  192. package/src/conflict-output.ts +218 -0
  193. package/src/conflict-schema.ts +130 -0
  194. package/src/conflict-store.ts +127 -0
  195. package/src/consolidation-engine.ts +256 -0
  196. package/src/context-composer-pins.ts +183 -0
  197. package/src/context-composer-queries.ts +121 -0
  198. package/src/context-composer-scope.ts +56 -0
  199. package/src/context-composer-stable-selection.ts +200 -0
  200. package/src/context-composer-stable.ts +217 -0
  201. package/src/context-composer-task-fallbacks.ts +36 -0
  202. package/src/context-composer-task-ranking.ts +197 -0
  203. package/src/context-composer-task-results.ts +137 -0
  204. package/src/context-composer-task-selection.ts +342 -0
  205. package/src/context-composer-text.ts +57 -0
  206. package/src/context-composer.ts +300 -0
  207. package/src/context-renderer.ts +179 -0
  208. package/src/decay-engine.ts +189 -0
  209. package/src/doctor.ts +543 -0
  210. package/src/embedder.ts +557 -0
  211. package/src/entity-resolver.ts +131 -0
  212. package/src/eval.ts +632 -0
  213. package/src/event-segmenter.ts +216 -0
  214. package/src/ingest.ts +1822 -0
  215. package/src/kg-extractor.ts +217 -0
  216. package/src/kg-store.ts +353 -0
  217. package/src/legacy-scope-review.ts +53 -0
  218. package/src/llm-client.ts +629 -0
  219. package/src/llm-consolidation.ts +168 -0
  220. package/src/mcp-server.ts +1337 -0
  221. package/src/memory-assets.ts +475 -0
  222. package/src/memory-boundaries.ts +354 -0
  223. package/src/memory-health-rebalance.ts +220 -0
  224. package/src/memory-output.ts +474 -0
  225. package/src/memory-schema.ts +184 -0
  226. package/src/multi-vector.ts +234 -0
  227. package/src/noise-filter.ts +155 -0
  228. package/src/ppr-traversal.ts +279 -0
  229. package/src/preference-matcher.ts +174 -0
  230. package/src/preference-slots.ts +259 -0
  231. package/src/prospective-memory.ts +198 -0
  232. package/src/query-entity-detector.ts +207 -0
  233. package/src/query-expander.ts +98 -0
  234. package/src/result-synthesizer.ts +114 -0
  235. package/src/retrieval-profiles.ts +101 -0
  236. package/src/retrieval-trace.ts +94 -0
  237. package/src/retriever.ts +1338 -0
  238. package/src/retroactive-boost.ts +154 -0
  239. package/src/rif.ts +73 -0
  240. package/src/runtime-config.ts +172 -0
  241. package/src/schema-utils.ts +56 -0
  242. package/src/scope-inventory.ts +310 -0
  243. package/src/scope-policy.ts +142 -0
  244. package/src/session-engine.ts +168 -0
  245. package/src/session-output.ts +96 -0
  246. package/src/session-schema.ts +60 -0
  247. package/src/session-store.ts +293 -0
  248. package/src/stderr-log.ts +16 -0
  249. package/src/store.ts +903 -0
  250. package/src/temporal-parser.ts +318 -0
  251. package/src/term-registry.ts +791 -0
  252. package/src/tool-output-compressor.ts +115 -0
  253. package/src/tracker.ts +57 -0
  254. package/src/ui-server.ts +430 -0
  255. package/src/version-manager.ts +172 -0
  256. package/src/workflow-observation-engine.ts +316 -0
  257. package/src/workflow-observation-managed.ts +83 -0
  258. package/src/workflow-observation-output.ts +86 -0
  259. package/src/workflow-observation-schema.ts +87 -0
  260. package/src/workflow-observation-scope-review.ts +409 -0
  261. package/src/workflow-observation-store.ts +69 -0
@@ -0,0 +1,182 @@
1
+ /**
2
+ * RecallNest + Claude Agent SDK — Minimal Example
3
+ *
4
+ * A Claude agent with persistent memory powered by RecallNest HTTP API.
5
+ *
6
+ * Prerequisites:
7
+ * 1. RecallNest API server running: bun run api (port 4318)
8
+ * 2. ANTHROPIC_API_KEY set in environment
9
+ * 3. Install deps: bun add @anthropic-ai/sdk
10
+ *
11
+ * Run: bun run integrations/examples/claude-agent-sdk/memory-agent.ts
12
+ */
13
+
14
+ import Anthropic from "@anthropic-ai/sdk";
15
+
16
+ const client = new Anthropic();
17
+ const RECALLNEST = "http://localhost:4318";
18
+
19
+ function buildRecallContext() {
20
+ const sessionId = process.env.RECALLNEST_SESSION_ID;
21
+ const scope = process.env.RECALLNEST_SCOPE;
22
+ const resolvedScope = scope || (sessionId ? `session:${sessionId}` : undefined);
23
+ return {
24
+ ...(sessionId ? { sessionId } : {}),
25
+ ...(resolvedScope ? { scope: resolvedScope } : {}),
26
+ };
27
+ }
28
+
29
+ // --- Tool definitions for Claude ---
30
+
31
+ const tools: Anthropic.Tool[] = [
32
+ {
33
+ name: "recall_memory",
34
+ description:
35
+ "Recall relevant memories from past conversations. Use at the start of every task.",
36
+ input_schema: {
37
+ type: "object" as const,
38
+ properties: {
39
+ query: {
40
+ type: "string",
41
+ description: "Search query — use 2-3 key nouns",
42
+ },
43
+ },
44
+ required: ["query"],
45
+ },
46
+ },
47
+ {
48
+ name: "store_memory",
49
+ description:
50
+ "Store an important fact, decision, or preference for future recall.",
51
+ input_schema: {
52
+ type: "object" as const,
53
+ properties: {
54
+ text: {
55
+ type: "string",
56
+ description: "The memory content to store",
57
+ },
58
+ category: {
59
+ type: "string",
60
+ enum: [
61
+ "profile",
62
+ "preferences",
63
+ "entities",
64
+ "events",
65
+ "cases",
66
+ "patterns",
67
+ ],
68
+ description: "Memory category",
69
+ },
70
+ },
71
+ required: ["text"],
72
+ },
73
+ },
74
+ ];
75
+
76
+ // --- Tool handler: calls RecallNest HTTP API ---
77
+
78
+ async function handleTool(
79
+ name: string,
80
+ input: Record<string, unknown>
81
+ ): Promise<string> {
82
+ if (name === "recall_memory") {
83
+ const res = await fetch(`${RECALLNEST}/v1/auto-recall`, {
84
+ method: "POST",
85
+ headers: { "Content-Type": "application/json" },
86
+ body: JSON.stringify({ message: input.query, limit: 5, ...buildRecallContext() }),
87
+ });
88
+ if (!res.ok) return `Error: ${res.status} ${await res.text()}`;
89
+ const data = await res.json();
90
+ return JSON.stringify({
91
+ mode: data.mode,
92
+ resolvedScope: data.resolvedScope,
93
+ summary: data.resume?.summary,
94
+ stableContext: data.resume?.stableContext || [],
95
+ results: data.results || [],
96
+ searchSkippedReason: data.searchSkippedReason,
97
+ }, null, 2);
98
+ }
99
+
100
+ if (name === "store_memory") {
101
+ const recallContext = buildRecallContext();
102
+ if (!("scope" in recallContext)) {
103
+ return "Set RECALLNEST_SCOPE or RECALLNEST_SESSION_ID before storing durable memory.";
104
+ }
105
+ const res = await fetch(`${RECALLNEST}/v1/store`, {
106
+ method: "POST",
107
+ headers: { "Content-Type": "application/json" },
108
+ body: JSON.stringify({
109
+ text: input.text,
110
+ category: input.category || "events",
111
+ scope: recallContext.scope,
112
+ source: "claude-agent-sdk-example",
113
+ }),
114
+ });
115
+ if (!res.ok) return `Error: ${res.status} ${await res.text()}`;
116
+ return "Memory stored successfully.";
117
+ }
118
+
119
+ return `Unknown tool: ${name}`;
120
+ }
121
+
122
+ // --- Agent loop ---
123
+
124
+ async function runAgent(userMessage: string) {
125
+ console.log(`\nUser: ${userMessage}\n`);
126
+
127
+ const messages: Anthropic.MessageParam[] = [
128
+ { role: "user", content: userMessage },
129
+ ];
130
+
131
+ // Agentic loop: keep going until no more tool calls
132
+ while (true) {
133
+ const response = await client.messages.create({
134
+ model: "claude-sonnet-4-20250514",
135
+ max_tokens: 1024,
136
+ system:
137
+ "You are a helpful assistant with persistent memory. " +
138
+ "Always use recall_memory at the start of a task or project pivot to recover relevant context. " +
139
+ "Store important facts with store_memory.",
140
+ tools,
141
+ messages,
142
+ });
143
+
144
+ // Collect text output
145
+ for (const block of response.content) {
146
+ if (block.type === "text") {
147
+ console.log(`Assistant: ${block.text}`);
148
+ }
149
+ }
150
+
151
+ // If no tool use, we're done
152
+ if (response.stop_reason !== "tool_use") break;
153
+
154
+ // Handle tool calls
155
+ const toolUseBlocks = response.content.filter(
156
+ (b): b is Anthropic.ContentBlockParam & { type: "tool_use"; id: string; name: string; input: Record<string, unknown> } =>
157
+ b.type === "tool_use"
158
+ );
159
+
160
+ // Add assistant response to history
161
+ messages.push({ role: "assistant", content: response.content });
162
+
163
+ // Process each tool call and add results
164
+ const toolResults: Anthropic.ToolResultBlockParam[] = [];
165
+ for (const toolUse of toolUseBlocks) {
166
+ console.log(` [Tool] ${toolUse.name}(${JSON.stringify(toolUse.input)})`);
167
+ const result = await handleTool(toolUse.name, toolUse.input);
168
+ toolResults.push({
169
+ type: "tool_result",
170
+ tool_use_id: toolUse.id,
171
+ content: result,
172
+ });
173
+ }
174
+
175
+ messages.push({ role: "user", content: toolResults });
176
+ }
177
+ }
178
+
179
+ // --- Main ---
180
+
181
+ const query = process.argv[2] || "What do you remember about my Docker setup?";
182
+ runAgent(query);
@@ -0,0 +1,111 @@
1
+ """
2
+ RecallNest + LangChain — Minimal Example
3
+
4
+ A LangChain agent with persistent memory powered by RecallNest HTTP API.
5
+
6
+ Prerequisites:
7
+ 1. RecallNest API server running: bun run api (port 4318)
8
+ 2. OPENAI_API_KEY set in environment (or use any LangChain-supported LLM)
9
+ 3. Install deps: pip install langchain langchain-openai httpx
10
+
11
+ Run: python integrations/examples/langchain/memory-chain.py
12
+ """
13
+
14
+ import json
15
+ import os
16
+ import httpx
17
+ from langchain_core.tools import tool
18
+ from langchain_openai import ChatOpenAI
19
+ from langgraph.prebuilt import create_react_agent
20
+
21
+ RECALLNEST = "http://localhost:4318"
22
+
23
+
24
+ def build_recall_context() -> dict:
25
+ session_id = os.getenv("RECALLNEST_SESSION_ID")
26
+ scope = os.getenv("RECALLNEST_SCOPE")
27
+ resolved_scope = scope or (f"session:{session_id}" if session_id else None)
28
+ payload = {}
29
+ if session_id:
30
+ payload["sessionId"] = session_id
31
+ if resolved_scope:
32
+ payload["scope"] = resolved_scope
33
+ return payload
34
+
35
+
36
+ @tool
37
+ def recall_memory(query: str) -> str:
38
+ """Recall relevant memories from past conversations.
39
+ Use at the start of every task with 2-3 key nouns."""
40
+ r = httpx.post(
41
+ f"{RECALLNEST}/v1/auto-recall",
42
+ json={"message": query, "limit": 5, **build_recall_context()},
43
+ )
44
+ r.raise_for_status()
45
+ payload = r.json()
46
+ return json.dumps(
47
+ {
48
+ "mode": payload.get("mode"),
49
+ "resolvedScope": payload.get("resolvedScope"),
50
+ "summary": payload.get("resume", {}).get("summary"),
51
+ "stableContext": payload.get("resume", {}).get("stableContext", []),
52
+ "results": payload.get("results", []),
53
+ "searchSkippedReason": payload.get("searchSkippedReason"),
54
+ },
55
+ indent=2,
56
+ ensure_ascii=False,
57
+ )
58
+
59
+
60
+ @tool
61
+ def store_memory(text: str, category: str = "events") -> str:
62
+ """Store an important fact, decision, or preference for future recall.
63
+
64
+ Args:
65
+ text: The memory content to store.
66
+ category: One of: profile, preferences, entities, events, cases, patterns.
67
+ """
68
+ scope_context = build_recall_context()
69
+ if "scope" not in scope_context:
70
+ return "Set RECALLNEST_SCOPE or RECALLNEST_SESSION_ID before storing durable memory."
71
+ r = httpx.post(
72
+ f"{RECALLNEST}/v1/store",
73
+ json={
74
+ "text": text,
75
+ "category": category,
76
+ "scope": scope_context["scope"],
77
+ "source": "langchain-example",
78
+ },
79
+ )
80
+ r.raise_for_status()
81
+ return "Memory stored successfully."
82
+
83
+
84
+ # --- Build the agent ---
85
+
86
+ llm = ChatOpenAI(model="gpt-4o")
87
+ tools = [recall_memory, store_memory]
88
+
89
+ agent = create_react_agent(llm, tools)
90
+
91
+
92
+ # --- Main ---
93
+
94
+ def main():
95
+ import sys
96
+ query = sys.argv[1] if len(sys.argv) > 1 else "What do you remember about my project?"
97
+ print(f"\nUser: {query}\n")
98
+
99
+ result = agent.invoke(
100
+ {"messages": [{"role": "user", "content": query}]}
101
+ )
102
+
103
+ # Print the last assistant message
104
+ for msg in reversed(result["messages"]):
105
+ if msg.type == "ai" and msg.content:
106
+ print(f"Assistant: {msg.content}")
107
+ break
108
+
109
+
110
+ if __name__ == "__main__":
111
+ main()
@@ -0,0 +1,109 @@
1
+ """
2
+ RecallNest + OpenAI Agents SDK — Minimal Example
3
+
4
+ A Python agent with persistent memory powered by RecallNest HTTP API.
5
+
6
+ Prerequisites:
7
+ 1. RecallNest API server running: bun run api (port 4318)
8
+ 2. OPENAI_API_KEY set in environment
9
+ 3. Install deps: pip install openai-agents httpx
10
+
11
+ Run: python integrations/examples/openai-agents-sdk/memory-agent.py
12
+ """
13
+
14
+ import asyncio
15
+ import json
16
+ import os
17
+ import httpx
18
+ from agents import Agent, Runner, function_tool
19
+
20
+ RECALLNEST = "http://localhost:4318"
21
+
22
+
23
+ def build_recall_context() -> dict:
24
+ session_id = os.getenv("RECALLNEST_SESSION_ID")
25
+ scope = os.getenv("RECALLNEST_SCOPE")
26
+ resolved_scope = scope or (f"session:{session_id}" if session_id else None)
27
+ payload = {}
28
+ if session_id:
29
+ payload["sessionId"] = session_id
30
+ if resolved_scope:
31
+ payload["scope"] = resolved_scope
32
+ return payload
33
+
34
+
35
+ @function_tool
36
+ async def recall_memory(query: str) -> str:
37
+ """Recall relevant memories from past conversations.
38
+ Use at the start of every task with 2-3 key nouns."""
39
+ async with httpx.AsyncClient() as client:
40
+ r = await client.post(
41
+ f"{RECALLNEST}/v1/auto-recall",
42
+ json={"message": query, "limit": 5, **build_recall_context()},
43
+ )
44
+ r.raise_for_status()
45
+ payload = r.json()
46
+ return json.dumps(
47
+ {
48
+ "mode": payload.get("mode"),
49
+ "resolvedScope": payload.get("resolvedScope"),
50
+ "summary": payload.get("resume", {}).get("summary"),
51
+ "stableContext": payload.get("resume", {}).get("stableContext", []),
52
+ "results": payload.get("results", []),
53
+ "searchSkippedReason": payload.get("searchSkippedReason"),
54
+ },
55
+ indent=2,
56
+ ensure_ascii=False,
57
+ )
58
+
59
+
60
+ @function_tool
61
+ async def store_memory(text: str, category: str = "events") -> str:
62
+ """Store an important fact, decision, or preference for future recall.
63
+
64
+ Args:
65
+ text: The memory content to store.
66
+ category: One of: profile, preferences, entities, events, cases, patterns.
67
+ """
68
+ scope_context = build_recall_context()
69
+ if "scope" not in scope_context:
70
+ return "Set RECALLNEST_SCOPE or RECALLNEST_SESSION_ID before storing durable memory."
71
+ async with httpx.AsyncClient() as client:
72
+ r = await client.post(
73
+ f"{RECALLNEST}/v1/store",
74
+ json={
75
+ "text": text,
76
+ "category": category,
77
+ "scope": scope_context["scope"],
78
+ "source": "openai-agents-sdk-example",
79
+ },
80
+ )
81
+ r.raise_for_status()
82
+ return "Memory stored successfully."
83
+
84
+
85
+ # --- Agent definition ---
86
+
87
+ agent = Agent(
88
+ name="Memory Agent",
89
+ instructions=(
90
+ "You are a helpful assistant with persistent memory. "
91
+ "Always use recall_memory at the start of a task or project pivot to recover relevant context. "
92
+ "Store important facts with store_memory."
93
+ ),
94
+ tools=[recall_memory, store_memory],
95
+ )
96
+
97
+
98
+ # --- Main ---
99
+
100
+ async def main():
101
+ import sys
102
+ query = sys.argv[1] if len(sys.argv) > 1 else "What do you remember about my project?"
103
+ print(f"\nUser: {query}\n")
104
+ result = await Runner.run(agent, query)
105
+ print(f"Assistant: {result.final_output}")
106
+
107
+
108
+ if __name__ == "__main__":
109
+ asyncio.run(main())
@@ -0,0 +1,57 @@
1
+ # Gemini CLI Integration
2
+
3
+ > Gemini CLI 接入指南:一键配 MCP + continuity 规则,让 Gemini CLI 在新窗口里主动恢复稳定上下文。
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ bash integrations/gemini-cli/setup.sh
9
+ ```
10
+
11
+ ## What It Does
12
+
13
+ - Adds RecallNest as an MCP server in `~/.gemini/settings.json` with `trust: true`
14
+ - Installs a managed RecallNest block in `~/.gemini/GEMINI.md`
15
+
16
+ ## Continuity Rules
17
+
18
+ The managed block comes from [gemini-md-snippet.md](gemini-md-snippet.md) and tells Gemini CLI to:
19
+
20
+ - call `resume_context` at the start of fresh windows or continuity-sensitive tasks
21
+ - run lightweight `search_memory` on task pivots inside the same project before repo exploration drifts
22
+ - reuse known `scope` / `sessionId` and the resolved scope returned by `resume_context` in follow-up recall calls
23
+ - treat recalled or startup-hook repo state as unverified until this window explicitly checks the repo
24
+ - save `checkpoint_session` before leaving resumable work
25
+ - do not inspect repo state just to enrich a close-window checkpoint unless the user explicitly asked for repo state
26
+ - do not write unverified repo-state claims into `checkpoint_session`
27
+ - capture durable facts with `store_memory` and reusable workflows with `store_workflow_pattern`
28
+
29
+ ## Shared Index
30
+
31
+ Gemini CLI shares the same LanceDB index as Claude Code and Codex. Memories ingested from any source are searchable by all three.
32
+
33
+ ## Manual Setup
34
+
35
+ Add to `~/.gemini/settings.json`:
36
+
37
+ ```json
38
+ {
39
+ "mcpServers": {
40
+ "recallnest": {
41
+ "command": "bun",
42
+ "args": ["run", "RECALLNEST_PATH/src/mcp-server.ts"],
43
+ "trust": true
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ Replace `RECALLNEST_PATH` with your actual path.
50
+
51
+ Then copy [gemini-md-snippet.md](gemini-md-snippet.md) into `~/.gemini/GEMINI.md` if you are not using `setup.sh`.
52
+
53
+ ## Verify
54
+
55
+ Start Gemini CLI and ask: "resume my context for RecallNest continuity work"
56
+
57
+ If `resume_context` or `search_memory` is called, you're set.
@@ -0,0 +1,31 @@
1
+ ## RecallNest Continuity
2
+
3
+ - These continuity rules override later generic writing, skill, and local-memory instructions whenever the user's intent is continuity recovery or memory recall.
4
+ - If the user says `continue`, `继续`, `接着`, `刚才`, `上个窗口`, `不要让我重复前情`, `之前讨论过`, or asks what the project is solving / where it stopped / what to do next, call `resume_context` before any Bash, Read, or repo exploration.
5
+ - If the user starts a concrete task in an active project, shifts back to a named project, or asks for prior implementation detail, do lightweight RecallNest recovery before repo exploration even without an explicit `continue`: call `resume_context` for broad continuity or `search_memory` for focused fact/pattern recall.
6
+ - Do not substitute `git status`, `git log`, or reading local docs for `resume_context`. Local inspection can validate current code state only after continuity has been recovered.
7
+ - Use `resume_context` to recover stable background such as active projects, durable preferences, recent cases, reusable patterns, and the latest checkpoint.
8
+ - When `scope`, shared project scope, or `sessionId` is known, pass it into `resume_context` / `search_memory` / related recall tools instead of relying on global recall.
9
+ - If `resume_context` returns a resolved scope or latest checkpoint scope, reuse that same scope in follow-up `search_memory`, `brief_memory`, `pin_memory`, and other recall calls.
10
+ - If `resume_context` or a recalled checkpoint mentions repo state such as `git status`, modified files, untracked files, commits, or pending push, treat that as handoff context only. Do not restate it as the current repo state unless you verify it in this window with repo tools.
11
+ - If current repo state has not been verified in this window, say it is unknown or omit it. Do not infer dirty/clean state, staged files, commit readiness, or specific modified files from recalled context alone.
12
+ - In recall-only continuity recovery, do not mention `git status`, modified/untracked filenames, or repo cleanliness just to sound specific. If the next step would need repo inspection, say you would inspect the repo after the user asks you to proceed.
13
+ - Treat startup hooks, restored checkpoints, and recalled notes the same way: unless this window explicitly inspected the repo, they are not evidence for current file lists or worktree state.
14
+ - If the user is asking what you remember about preferences, style, tone, identity, or current project background, answer from `resume_context` and recalled memory first. Do not read repo files or local docs unless the user explicitly asks for file inspection or the recovered context is insufficient.
15
+ - If the message mentions writing, articles, or the public account but the actual intent is recall-only (for example: "what style do you remember", "哪些表达方式要避免", "回忆偏好"), do not activate article-writing workflows, writing-persona files, or content-alchemy style skills. Treat it as a memory recall question unless the user explicitly asks you to draft, edit, or research.
16
+ - Normal writing requests are unchanged: if the user explicitly asks you to draft an article, revise copy, research a topic, or continue the writing pipeline, you should use the existing writing workflows and skills as usual.
17
+ - For recall-only writing/style questions, do not supplement the answer with local memory indexes, quick-reference blocks, `writing-persona.md`, `writing-rules.md`, or similar local style docs. If RecallNest recalled only one preference, answer from that one preference.
18
+ - For recall-only preference questions, prefer a plain `resume_context` call over writing-specific profiles or broader rulesets unless the user explicitly asks for the full writing system.
19
+ - If `resume_context` returns `Response mode: recall-only` or a recall-only guidance line, follow it literally. Restate the recalled stable context briefly and do not add extra examples, banned words, or inferred style rules unless they were also recalled.
20
+ - If `resume_context` already returns a relevant durable preference for the current task, keep the answer narrow. Do not pad it with older pins, briefs, or local rule files unless the user asks for a broader ruleset.
21
+ - For recall-only questions, stay constrained to the recalled items. Do not expand one recalled preference into a full doctrine, banned-word list, or writing system unless those details were also recalled or the user explicitly asks for expansion.
22
+ - If recalled context is sparse, say what you do remember and what is still uncertain. Do not invent extra rules to sound complete.
23
+ - For task pivots or fresh implementation work inside the same project, run a lightweight `search_memory` using 2-3 key nouns or verbs from the user's request before repo exploration drifts.
24
+ - If `resume_context` is not enough and you need a specific fact, follow up with `search_memory` using 2-3 key nouns or verbs instead of full sentences.
25
+ - If the user explicitly corrects a continuity miss, such as saying you should have resumed context first or should have saved a checkpoint before stopping, fix the workflow first and then call `workflow_observe` with outcome `corrected` so the miss is tracked outside durable memory.
26
+ - Before leaving a window with unfinished or resumable work, call `checkpoint_session` and capture the current summary, decisions, open loops, next actions, and relevant entities.
27
+ - Do not inspect repo state just to make `checkpoint_session` more complete unless the user explicitly asked for repo state in this window. A close-window handoff should prefer an incomplete but verified checkpoint over speculative or freshly-probed repo details.
28
+ - Do not write repo-state claims into `checkpoint_session` unless you actually inspected the repo in this window. A recalled checkpoint mentioning dirty files or pending push is not enough evidence to repeat or persist it.
29
+ - Do not copy or paraphrase unverified repo-state text into `checkpoint_session`, even with caveats like `未在本窗口验证`, `上次看到`, or `according to the earlier checkpoint`. If this window never inspected the repo, omit repo state entirely from the checkpoint.
30
+ - Use `store_memory` when you learn durable profile, preference, entity, or case knowledge that should survive across future windows.
31
+ - Use `store_workflow_pattern` when you discover a reusable multi-step workflow that should become durable `patterns` memory.
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env bash
2
+ # RecallNest — Gemini CLI MCP setup (idempotent)
3
+ # Usage: bash integrations/gemini-cli/setup.sh
4
+
5
+ set -euo pipefail
6
+
7
+ GEMINI_SETTINGS="$HOME/.gemini/settings.json"
8
+ GEMINI_MD="$HOME/.gemini/GEMINI.md"
9
+ GEMINI_DIR="$HOME/.gemini"
10
+ RECALLNEST_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
11
+ MCP_ENTRY="$RECALLNEST_DIR/src/mcp-server.ts"
12
+ RULES_SNIPPET="$RECALLNEST_DIR/integrations/gemini-cli/gemini-md-snippet.md"
13
+ RULES_HELPER="$RECALLNEST_DIR/integrations/shared/install-managed-block.sh"
14
+
15
+ if [[ ! -f "$MCP_ENTRY" ]]; then
16
+ echo "ERROR: $MCP_ENTRY not found. Run this from the recallnest repo root."
17
+ exit 1
18
+ fi
19
+
20
+ if [[ ! -f "$RULES_HELPER" ]]; then
21
+ echo "ERROR: $RULES_HELPER not found."
22
+ exit 1
23
+ fi
24
+
25
+ # Create ~/.gemini/ and settings.json if missing
26
+ mkdir -p "$GEMINI_DIR"
27
+ if [[ ! -f "$GEMINI_SETTINGS" ]]; then
28
+ echo '{}' > "$GEMINI_SETTINGS"
29
+ echo "Created $GEMINI_SETTINGS"
30
+ fi
31
+
32
+ # Check if already configured
33
+ if bun -e "
34
+ const c = JSON.parse(require('fs').readFileSync('$GEMINI_SETTINGS','utf8'));
35
+ process.exit(c.mcpServers?.recallnest ? 0 : 1);
36
+ " 2>/dev/null; then
37
+ echo "RecallNest MCP already configured in $GEMINI_SETTINGS — skipping."
38
+ else
39
+ bun -e "
40
+ const fs = require('fs');
41
+ const c = JSON.parse(fs.readFileSync('$GEMINI_SETTINGS','utf8'));
42
+ if (!c.mcpServers) c.mcpServers = {};
43
+ c.mcpServers.recallnest = {
44
+ command: 'bun',
45
+ args: ['run', '$MCP_ENTRY'],
46
+ trust: true
47
+ };
48
+ fs.writeFileSync('$GEMINI_SETTINGS', JSON.stringify(c, null, 2) + '\n');
49
+ "
50
+ echo "Added RecallNest MCP to $GEMINI_SETTINGS"
51
+ fi
52
+
53
+ . "$RULES_HELPER"
54
+ install_managed_markdown_block "$RULES_SNIPPET" "$GEMINI_MD" "recallnest-continuity"
55
+ echo "Installed RecallNest continuity rules in $GEMINI_MD"
56
+
57
+ echo ""
58
+ echo "Setup complete. Restart Gemini CLI to activate."
59
+ echo ""
60
+ echo "Continuity baseline seed:"
61
+ echo " (cd \"$RECALLNEST_DIR\" && bun run seed:continuity)"
62
+ echo ""
63
+ echo "Managed snippet source:"
64
+ echo " $RULES_SNIPPET"
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env bash
2
+
3
+ install_managed_markdown_block() {
4
+ local snippet_path="$1"
5
+ local target_path="$2"
6
+ local marker_name="$3"
7
+
8
+ if [[ ! -f "$snippet_path" ]]; then
9
+ echo "ERROR: snippet not found: $snippet_path" >&2
10
+ return 1
11
+ fi
12
+
13
+ mkdir -p "$(dirname "$target_path")"
14
+ touch "$target_path"
15
+
16
+ local start_marker="<!-- ${marker_name}:start -->"
17
+ local end_marker="<!-- ${marker_name}:end -->"
18
+ local tmp_file
19
+ tmp_file="$(mktemp)"
20
+ local tmp_body
21
+ tmp_body="$(mktemp)"
22
+
23
+ awk -v start="$start_marker" -v end="$end_marker" '
24
+ BEGIN {
25
+ in_block = 0
26
+ }
27
+ $0 == start {
28
+ in_block = 1
29
+ next
30
+ }
31
+ $0 == end {
32
+ in_block = 0
33
+ next
34
+ }
35
+ !in_block {
36
+ print
37
+ }
38
+ ' "$target_path" > "$tmp_body"
39
+
40
+ printf '%s\n' "$start_marker" > "$tmp_file"
41
+ awk '1' "$snippet_path" >> "$tmp_file"
42
+ printf '%s\n' "$end_marker" >> "$tmp_file"
43
+
44
+ if [[ -s "$tmp_body" ]]; then
45
+ printf '\n' >> "$tmp_file"
46
+ cat "$tmp_body" >> "$tmp_file"
47
+ fi
48
+
49
+ mv "$tmp_file" "$target_path"
50
+ rm -f "$tmp_body"
51
+ }
package/lm ADDED
@@ -0,0 +1,19 @@
1
+ #!/bin/bash
2
+ # RecallNest CLI shortcut
3
+ # Usage:
4
+ # lm search "keywords" — search memory
5
+ # lm ingest — ingest all sources
6
+ # lm ingest --source cc — ingest Claude Code only
7
+ # lm stats — show stats
8
+ # lm reset --yes — reset index
9
+
10
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
11
+
12
+ # Load .env if present (CLI also loads it, this is for standalone use)
13
+ if [ -f "$SCRIPT_DIR/.env" ]; then
14
+ set -a
15
+ source "$SCRIPT_DIR/.env"
16
+ set +a
17
+ fi
18
+
19
+ cd "$SCRIPT_DIR" && bun run src/cli.ts "$@"
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "recallnest",
3
+ "version": "1.4.1",
4
+ "description": "RecallNest \u2014 MCP-native, local-first memory search and distillation for AI conversations",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "recallnest": "src/cli.ts",
9
+ "local-memory": "src/cli.ts"
10
+ },
11
+ "scripts": {
12
+ "search": "bun run src/cli.ts search",
13
+ "ingest": "bun run src/cli.ts ingest",
14
+ "stats": "bun run src/cli.ts stats",
15
+ "scope-inventory": "bun run src/cli.ts scope-inventory",
16
+ "workflow-scope-review": "bun run src/cli.ts workflow-scope-review",
17
+ "mcp": "bun run src/mcp-server.ts",
18
+ "explain": "bun run src/cli.ts explain",
19
+ "distill": "bun run src/cli.ts distill",
20
+ "brief": "bun run src/cli.ts brief",
21
+ "assets": "bun run src/cli.ts assets",
22
+ "clean-briefs": "bun run src/cli.ts clean-briefs --apply",
23
+ "test": "bun test",
24
+ "test:core": "bun test src/__tests__/scope-policy.test.ts src/__tests__/core-recall-eval.test.ts src/__tests__/capture-engine.test.ts src/__tests__/store-scope-audit.test.ts src/__tests__/scope-inventory.test.ts src/__tests__/workflow-observation.test.ts src/__tests__/resume-context.test.ts src/__tests__/term-registry.test.ts",
25
+ "eval": "bun run src/eval.ts",
26
+ "eval:continuity": "bun run src/eval.ts --mode continuity --cases eval/continuity/cases.json",
27
+ "profiles": "bun run src/cli.ts profiles",
28
+ "doctor": "bun run src/cli.ts doctor",
29
+ "demo": "bun run src/cli.ts demo",
30
+ "seed:patterns": "bun run src/cli.ts seed-patterns",
31
+ "seed:cases": "bun run src/cli.ts seed-cases",
32
+ "seed:memories": "bun run src/cli.ts seed-memories",
33
+ "seed:continuity": "bun run seed:patterns && bun run seed:cases && bun run seed:memories",
34
+ "smoke:claude-continuity": "bash integrations/claude-code/smoke-continuity.sh",
35
+ "ui": "bun run src/ui-server.ts",
36
+ "api": "bun run src/api-server.ts"
37
+ },
38
+ "dependencies": {
39
+ "@lancedb/lancedb": "^0.26.0",
40
+ "@modelcontextprotocol/sdk": "^1.27.1",
41
+ "commander": "^12.0.0",
42
+ "openai": "^4.0.0",
43
+ "zod": "^3.25.76"
44
+ },
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "git+https://github.com/AliceLJY/recallnest.git"
48
+ },
49
+ "homepage": "https://github.com/AliceLJY/recallnest"
50
+ }