basic-memory 0.7.0__py3-none-any.whl → 0.17.4__py3-none-any.whl

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.

Potentially problematic release.


This version of basic-memory might be problematic. Click here for more details.

Files changed (195) hide show
  1. basic_memory/__init__.py +5 -1
  2. basic_memory/alembic/alembic.ini +119 -0
  3. basic_memory/alembic/env.py +130 -20
  4. basic_memory/alembic/migrations.py +4 -9
  5. basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +131 -0
  6. basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +51 -0
  7. basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +120 -0
  8. basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +112 -0
  9. basic_memory/alembic/versions/6830751f5fb6_merge_multiple_heads.py +24 -0
  10. basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +49 -0
  11. basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +49 -0
  12. basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +56 -0
  13. basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +44 -0
  14. basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +113 -0
  15. basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +37 -0
  16. basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +239 -0
  17. basic_memory/alembic/versions/g9a0b3c4d5e6_add_external_id_to_project_and_entity.py +173 -0
  18. basic_memory/api/app.py +87 -20
  19. basic_memory/api/container.py +133 -0
  20. basic_memory/api/routers/__init__.py +4 -1
  21. basic_memory/api/routers/directory_router.py +84 -0
  22. basic_memory/api/routers/importer_router.py +152 -0
  23. basic_memory/api/routers/knowledge_router.py +180 -23
  24. basic_memory/api/routers/management_router.py +80 -0
  25. basic_memory/api/routers/memory_router.py +9 -64
  26. basic_memory/api/routers/project_router.py +460 -0
  27. basic_memory/api/routers/prompt_router.py +260 -0
  28. basic_memory/api/routers/resource_router.py +136 -11
  29. basic_memory/api/routers/search_router.py +5 -5
  30. basic_memory/api/routers/utils.py +169 -0
  31. basic_memory/api/template_loader.py +292 -0
  32. basic_memory/api/v2/__init__.py +35 -0
  33. basic_memory/api/v2/routers/__init__.py +21 -0
  34. basic_memory/api/v2/routers/directory_router.py +93 -0
  35. basic_memory/api/v2/routers/importer_router.py +181 -0
  36. basic_memory/api/v2/routers/knowledge_router.py +427 -0
  37. basic_memory/api/v2/routers/memory_router.py +130 -0
  38. basic_memory/api/v2/routers/project_router.py +359 -0
  39. basic_memory/api/v2/routers/prompt_router.py +269 -0
  40. basic_memory/api/v2/routers/resource_router.py +286 -0
  41. basic_memory/api/v2/routers/search_router.py +73 -0
  42. basic_memory/cli/app.py +80 -10
  43. basic_memory/cli/auth.py +300 -0
  44. basic_memory/cli/commands/__init__.py +15 -2
  45. basic_memory/cli/commands/cloud/__init__.py +6 -0
  46. basic_memory/cli/commands/cloud/api_client.py +127 -0
  47. basic_memory/cli/commands/cloud/bisync_commands.py +110 -0
  48. basic_memory/cli/commands/cloud/cloud_utils.py +108 -0
  49. basic_memory/cli/commands/cloud/core_commands.py +195 -0
  50. basic_memory/cli/commands/cloud/rclone_commands.py +397 -0
  51. basic_memory/cli/commands/cloud/rclone_config.py +110 -0
  52. basic_memory/cli/commands/cloud/rclone_installer.py +263 -0
  53. basic_memory/cli/commands/cloud/upload.py +240 -0
  54. basic_memory/cli/commands/cloud/upload_command.py +124 -0
  55. basic_memory/cli/commands/command_utils.py +99 -0
  56. basic_memory/cli/commands/db.py +87 -12
  57. basic_memory/cli/commands/format.py +198 -0
  58. basic_memory/cli/commands/import_chatgpt.py +47 -223
  59. basic_memory/cli/commands/import_claude_conversations.py +48 -171
  60. basic_memory/cli/commands/import_claude_projects.py +53 -160
  61. basic_memory/cli/commands/import_memory_json.py +55 -111
  62. basic_memory/cli/commands/mcp.py +67 -11
  63. basic_memory/cli/commands/project.py +889 -0
  64. basic_memory/cli/commands/status.py +52 -34
  65. basic_memory/cli/commands/telemetry.py +81 -0
  66. basic_memory/cli/commands/tool.py +341 -0
  67. basic_memory/cli/container.py +84 -0
  68. basic_memory/cli/main.py +14 -6
  69. basic_memory/config.py +580 -26
  70. basic_memory/db.py +285 -28
  71. basic_memory/deps/__init__.py +293 -0
  72. basic_memory/deps/config.py +26 -0
  73. basic_memory/deps/db.py +56 -0
  74. basic_memory/deps/importers.py +200 -0
  75. basic_memory/deps/projects.py +238 -0
  76. basic_memory/deps/repositories.py +179 -0
  77. basic_memory/deps/services.py +480 -0
  78. basic_memory/deps.py +16 -185
  79. basic_memory/file_utils.py +318 -54
  80. basic_memory/ignore_utils.py +297 -0
  81. basic_memory/importers/__init__.py +27 -0
  82. basic_memory/importers/base.py +100 -0
  83. basic_memory/importers/chatgpt_importer.py +245 -0
  84. basic_memory/importers/claude_conversations_importer.py +192 -0
  85. basic_memory/importers/claude_projects_importer.py +184 -0
  86. basic_memory/importers/memory_json_importer.py +128 -0
  87. basic_memory/importers/utils.py +61 -0
  88. basic_memory/markdown/entity_parser.py +182 -23
  89. basic_memory/markdown/markdown_processor.py +70 -7
  90. basic_memory/markdown/plugins.py +43 -23
  91. basic_memory/markdown/schemas.py +1 -1
  92. basic_memory/markdown/utils.py +38 -14
  93. basic_memory/mcp/async_client.py +135 -4
  94. basic_memory/mcp/clients/__init__.py +28 -0
  95. basic_memory/mcp/clients/directory.py +70 -0
  96. basic_memory/mcp/clients/knowledge.py +176 -0
  97. basic_memory/mcp/clients/memory.py +120 -0
  98. basic_memory/mcp/clients/project.py +89 -0
  99. basic_memory/mcp/clients/resource.py +71 -0
  100. basic_memory/mcp/clients/search.py +65 -0
  101. basic_memory/mcp/container.py +110 -0
  102. basic_memory/mcp/project_context.py +155 -0
  103. basic_memory/mcp/prompts/__init__.py +19 -0
  104. basic_memory/mcp/prompts/ai_assistant_guide.py +70 -0
  105. basic_memory/mcp/prompts/continue_conversation.py +62 -0
  106. basic_memory/mcp/prompts/recent_activity.py +188 -0
  107. basic_memory/mcp/prompts/search.py +57 -0
  108. basic_memory/mcp/prompts/utils.py +162 -0
  109. basic_memory/mcp/resources/ai_assistant_guide.md +283 -0
  110. basic_memory/mcp/resources/project_info.py +71 -0
  111. basic_memory/mcp/server.py +61 -9
  112. basic_memory/mcp/tools/__init__.py +33 -21
  113. basic_memory/mcp/tools/build_context.py +120 -0
  114. basic_memory/mcp/tools/canvas.py +152 -0
  115. basic_memory/mcp/tools/chatgpt_tools.py +190 -0
  116. basic_memory/mcp/tools/delete_note.py +249 -0
  117. basic_memory/mcp/tools/edit_note.py +325 -0
  118. basic_memory/mcp/tools/list_directory.py +157 -0
  119. basic_memory/mcp/tools/move_note.py +549 -0
  120. basic_memory/mcp/tools/project_management.py +204 -0
  121. basic_memory/mcp/tools/read_content.py +281 -0
  122. basic_memory/mcp/tools/read_note.py +265 -0
  123. basic_memory/mcp/tools/recent_activity.py +528 -0
  124. basic_memory/mcp/tools/search.py +377 -24
  125. basic_memory/mcp/tools/utils.py +402 -16
  126. basic_memory/mcp/tools/view_note.py +78 -0
  127. basic_memory/mcp/tools/write_note.py +230 -0
  128. basic_memory/models/__init__.py +3 -2
  129. basic_memory/models/knowledge.py +82 -17
  130. basic_memory/models/project.py +93 -0
  131. basic_memory/models/search.py +68 -8
  132. basic_memory/project_resolver.py +222 -0
  133. basic_memory/repository/__init__.py +2 -0
  134. basic_memory/repository/entity_repository.py +437 -8
  135. basic_memory/repository/observation_repository.py +36 -3
  136. basic_memory/repository/postgres_search_repository.py +451 -0
  137. basic_memory/repository/project_info_repository.py +10 -0
  138. basic_memory/repository/project_repository.py +140 -0
  139. basic_memory/repository/relation_repository.py +79 -4
  140. basic_memory/repository/repository.py +148 -29
  141. basic_memory/repository/search_index_row.py +95 -0
  142. basic_memory/repository/search_repository.py +79 -268
  143. basic_memory/repository/search_repository_base.py +241 -0
  144. basic_memory/repository/sqlite_search_repository.py +437 -0
  145. basic_memory/runtime.py +61 -0
  146. basic_memory/schemas/__init__.py +22 -9
  147. basic_memory/schemas/base.py +131 -12
  148. basic_memory/schemas/cloud.py +50 -0
  149. basic_memory/schemas/directory.py +31 -0
  150. basic_memory/schemas/importer.py +35 -0
  151. basic_memory/schemas/memory.py +194 -25
  152. basic_memory/schemas/project_info.py +213 -0
  153. basic_memory/schemas/prompt.py +90 -0
  154. basic_memory/schemas/request.py +56 -2
  155. basic_memory/schemas/response.py +85 -28
  156. basic_memory/schemas/search.py +36 -35
  157. basic_memory/schemas/sync_report.py +72 -0
  158. basic_memory/schemas/v2/__init__.py +27 -0
  159. basic_memory/schemas/v2/entity.py +133 -0
  160. basic_memory/schemas/v2/resource.py +47 -0
  161. basic_memory/services/__init__.py +2 -1
  162. basic_memory/services/context_service.py +451 -138
  163. basic_memory/services/directory_service.py +310 -0
  164. basic_memory/services/entity_service.py +636 -71
  165. basic_memory/services/exceptions.py +21 -0
  166. basic_memory/services/file_service.py +402 -33
  167. basic_memory/services/initialization.py +216 -0
  168. basic_memory/services/link_resolver.py +50 -56
  169. basic_memory/services/project_service.py +888 -0
  170. basic_memory/services/search_service.py +232 -37
  171. basic_memory/sync/__init__.py +4 -2
  172. basic_memory/sync/background_sync.py +26 -0
  173. basic_memory/sync/coordinator.py +160 -0
  174. basic_memory/sync/sync_service.py +1200 -109
  175. basic_memory/sync/watch_service.py +432 -135
  176. basic_memory/telemetry.py +249 -0
  177. basic_memory/templates/prompts/continue_conversation.hbs +110 -0
  178. basic_memory/templates/prompts/search.hbs +101 -0
  179. basic_memory/utils.py +407 -54
  180. basic_memory-0.17.4.dist-info/METADATA +617 -0
  181. basic_memory-0.17.4.dist-info/RECORD +193 -0
  182. {basic_memory-0.7.0.dist-info → basic_memory-0.17.4.dist-info}/WHEEL +1 -1
  183. {basic_memory-0.7.0.dist-info → basic_memory-0.17.4.dist-info}/entry_points.txt +1 -0
  184. basic_memory/alembic/README +0 -1
  185. basic_memory/cli/commands/sync.py +0 -206
  186. basic_memory/cli/commands/tools.py +0 -157
  187. basic_memory/mcp/tools/knowledge.py +0 -68
  188. basic_memory/mcp/tools/memory.py +0 -170
  189. basic_memory/mcp/tools/notes.py +0 -202
  190. basic_memory/schemas/discovery.py +0 -28
  191. basic_memory/sync/file_change_scanner.py +0 -158
  192. basic_memory/sync/utils.py +0 -31
  193. basic_memory-0.7.0.dist-info/METADATA +0 -378
  194. basic_memory-0.7.0.dist-info/RECORD +0 -82
  195. {basic_memory-0.7.0.dist-info → basic_memory-0.17.4.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,249 @@
1
+ """Anonymous telemetry for Basic Memory (Homebrew-style opt-out).
2
+
3
+ This module implements privacy-respecting usage analytics following the Homebrew model:
4
+ - Telemetry is ON by default
5
+ - Users can easily opt out: `bm telemetry disable`
6
+ - First run shows a one-time notice (not a prompt)
7
+ - Only anonymous data is collected (random UUID, no personal info)
8
+
9
+ What we collect:
10
+ - App version, Python version, OS, architecture
11
+ - Feature usage (which MCP tools and CLI commands are used)
12
+ - Error types (sanitized, no file paths or personal data)
13
+
14
+ What we NEVER collect:
15
+ - Note content, file names, or paths
16
+ - Personal information
17
+ - IP addresses (OpenPanel doesn't store these)
18
+
19
+ Documentation: https://basicmemory.com/telemetry
20
+ """
21
+
22
+ import platform
23
+ import re
24
+ import uuid
25
+ from pathlib import Path
26
+ from typing import Any
27
+
28
+ from loguru import logger
29
+ from openpanel import OpenPanel
30
+
31
+ from basic_memory import __version__
32
+
33
+ # --- Configuration ---
34
+
35
+ # OpenPanel credentials (write-only, safe to embed in client code)
36
+ # These can only send events to our dashboard, not read any data
37
+ OPENPANEL_CLIENT_ID = "2e7b036d-c6e5-40aa-91eb-5c70a8ef21a3"
38
+ OPENPANEL_CLIENT_SECRET = "sec_92f7f8328bd0368ff4c2"
39
+
40
+ TELEMETRY_DOCS_URL = "https://basicmemory.com/telemetry"
41
+
42
+ TELEMETRY_NOTICE = f"""
43
+ Basic Memory collects anonymous usage statistics to help improve the software.
44
+ This includes: version, OS, feature usage, and errors. No personal data or note content.
45
+
46
+ To opt out: bm telemetry disable
47
+ Details: {TELEMETRY_DOCS_URL}
48
+ """
49
+
50
+ # --- Module State ---
51
+
52
+ _client: OpenPanel | None = None
53
+ _initialized: bool = False
54
+
55
+
56
+ # --- Installation ID ---
57
+
58
+
59
+ def get_install_id() -> str:
60
+ """Get or create anonymous installation ID.
61
+
62
+ Creates a random UUID on first run and stores it locally.
63
+ User can delete ~/.basic-memory/.install_id to reset.
64
+ """
65
+ id_file = Path.home() / ".basic-memory" / ".install_id"
66
+
67
+ if id_file.exists():
68
+ return id_file.read_text().strip()
69
+
70
+ install_id = str(uuid.uuid4())
71
+ id_file.parent.mkdir(parents=True, exist_ok=True)
72
+ id_file.write_text(install_id)
73
+ return install_id
74
+
75
+
76
+ # --- Client Management ---
77
+
78
+
79
+ def _get_client() -> OpenPanel:
80
+ """Get or create the OpenPanel client (singleton).
81
+
82
+ Lazily initializes the client with global properties.
83
+ """
84
+ global _client, _initialized
85
+
86
+ if _client is None:
87
+ from basic_memory.config import ConfigManager
88
+
89
+ config = ConfigManager().config
90
+
91
+ # Trigger: first call to track an event
92
+ # Why: lazy init avoids work if telemetry never used; disabled flag
93
+ # tells OpenPanel to skip network calls when user opts out or during tests
94
+ # Outcome: client ready to queue events (or silently discard if disabled)
95
+ is_disabled = not config.telemetry_enabled or config.is_test_env
96
+ _client = OpenPanel(
97
+ client_id=OPENPANEL_CLIENT_ID,
98
+ client_secret=OPENPANEL_CLIENT_SECRET,
99
+ disabled=is_disabled,
100
+ )
101
+
102
+ if config.telemetry_enabled and not config.is_test_env and not _initialized:
103
+ # Set global properties that go with every event
104
+ _client.set_global_properties(
105
+ {
106
+ "app_version": __version__,
107
+ "python_version": platform.python_version(),
108
+ "os": platform.system().lower(),
109
+ "arch": platform.machine(),
110
+ "install_id": get_install_id(),
111
+ "source": "foss",
112
+ }
113
+ )
114
+ _initialized = True
115
+
116
+ return _client
117
+
118
+
119
+ def reset_client() -> None:
120
+ """Reset the telemetry client (for testing or after config changes)."""
121
+ global _client, _initialized
122
+ _client = None
123
+ _initialized = False
124
+
125
+
126
+ # --- Event Tracking ---
127
+
128
+
129
+ def track(event: str, properties: dict[str, Any] | None = None) -> None:
130
+ """Track an event. Fire-and-forget, never raises.
131
+
132
+ Args:
133
+ event: Event name (e.g., "app_started", "mcp_tool_called")
134
+ properties: Optional event properties
135
+ """
136
+ # Constraint: telemetry must never break the application
137
+ # Even if OpenPanel API is down or config is corrupt, user's command must succeed
138
+ try:
139
+ _get_client().track(event, properties or {})
140
+ except Exception as e:
141
+ logger.opt(exception=False).debug(f"Telemetry failed: {e}")
142
+
143
+
144
+ # --- First-Run Notice ---
145
+
146
+
147
+ def show_notice_if_needed() -> None:
148
+ """Show one-time telemetry notice (Homebrew style).
149
+
150
+ Only shows if:
151
+ - Telemetry is enabled
152
+ - Notice hasn't been shown before
153
+
154
+ After showing, marks the notice as shown in config.
155
+ """
156
+ from basic_memory.config import ConfigManager
157
+
158
+ config_manager = ConfigManager()
159
+ config = config_manager.config
160
+
161
+ if config.telemetry_enabled and not config.telemetry_notice_shown:
162
+ from rich.console import Console
163
+ from rich.panel import Panel
164
+
165
+ # Print to stderr so it doesn't interfere with command output
166
+ console = Console(stderr=True)
167
+ console.print(
168
+ Panel(
169
+ TELEMETRY_NOTICE.strip(),
170
+ title="[dim]Telemetry Notice[/dim]",
171
+ border_style="dim",
172
+ expand=False,
173
+ )
174
+ )
175
+
176
+ # Mark as shown so we don't show again
177
+ config.telemetry_notice_shown = True
178
+ config_manager.save_config(config)
179
+
180
+
181
+ # --- Convenience Functions ---
182
+
183
+
184
+ def track_app_started(mode: str) -> None:
185
+ """Track app startup.
186
+
187
+ Args:
188
+ mode: "cli" or "mcp"
189
+ """
190
+ track("app_started", {"mode": mode})
191
+
192
+
193
+ def track_mcp_tool(tool_name: str) -> None:
194
+ """Track MCP tool usage.
195
+
196
+ Args:
197
+ tool_name: Name of the tool (e.g., "write_note", "search_notes")
198
+ """
199
+ track("mcp_tool_called", {"tool": tool_name})
200
+
201
+
202
+ def track_cli_command(command: str) -> None:
203
+ """Track CLI command usage.
204
+
205
+ Args:
206
+ command: Command name (e.g., "sync", "import claude")
207
+ """
208
+ track("cli_command", {"command": command})
209
+
210
+
211
+ def track_sync_completed(entity_count: int, duration_ms: int) -> None:
212
+ """Track sync completion.
213
+
214
+ Args:
215
+ entity_count: Number of entities synced
216
+ duration_ms: Duration in milliseconds
217
+ """
218
+ track("sync_completed", {"entity_count": entity_count, "duration_ms": duration_ms})
219
+
220
+
221
+ def track_import_completed(source: str, count: int) -> None:
222
+ """Track import completion.
223
+
224
+ Args:
225
+ source: Import source (e.g., "claude", "chatgpt")
226
+ count: Number of items imported
227
+ """
228
+ track("import_completed", {"source": source, "count": count})
229
+
230
+
231
+ def track_error(error_type: str, message: str) -> None:
232
+ """Track an error (sanitized).
233
+
234
+ Args:
235
+ error_type: Exception class name
236
+ message: Error message (will be sanitized to remove file paths)
237
+ """
238
+ if not message:
239
+ track("error", {"type": error_type, "message": ""})
240
+ return
241
+
242
+ # Sanitize file paths to prevent leaking user directory structure
243
+ # Unix paths: /Users/name/file.py, /home/user/notes/doc.md
244
+ sanitized = re.sub(r"/[\w/.+-]+\.\w+", "[FILE]", message)
245
+ # Windows paths: C:\Users\name\file.py, D:\projects\doc.md
246
+ sanitized = re.sub(r"[A-Z]:\\[\w\\.+-]+\.\w+", "[FILE]", sanitized, flags=re.IGNORECASE)
247
+
248
+ # Truncate to avoid sending too much data
249
+ track("error", {"type": error_type, "message": sanitized[:200]})
@@ -0,0 +1,110 @@
1
+ # Continuing conversation on: {{ topic }}
2
+
3
+ This is a memory retrieval session.
4
+
5
+ Please use the available basic-memory tools to gather relevant context before responding. Start by executing one of the suggested commands below to retrieve content.
6
+
7
+ > **Knowledge Capture Recommendation:** As you continue this conversation, actively look for opportunities to record new information, decisions, or insights that emerge. Use `write_note()` to document important context.
8
+
9
+ Here's what I found from previous conversations:
10
+
11
+ {{#if has_results}}
12
+ {{#each hierarchical_results}}
13
+ <memory>
14
+ --- memory://{{ primary_result.permalink }}
15
+
16
+ ## {{ primary_result.title }}
17
+ - **Type**: {{ primary_result.type }}
18
+ - **Created**: {{date primary_result.created_at "%Y-%m-%d %H:%M"}}
19
+
20
+ {{#if primary_result.content}}
21
+ **Excerpt**:
22
+ <excerpt>
23
+ {{ primary_result.content }}
24
+ </excerpt>
25
+ {{/if}}
26
+
27
+ {{#if observations}}
28
+ ## Observations
29
+ {{#each observations}}
30
+ <observation>
31
+ - [{{ category }}] {{ content }}
32
+ </observation>
33
+ {{/each}}
34
+ {{/if}}
35
+
36
+ You can read this document with: `read_note("{{ primary_result.permalink }}")`
37
+
38
+ {{#if related_results}}
39
+ ## Related Context
40
+
41
+ {{#each related_results}}
42
+ <related>
43
+ - type: **{{ type }}**
44
+ - title: {{ title }}
45
+
46
+ {{#if permalink}}
47
+ You can view this document with: `read_note("{{ permalink }}")`
48
+ {{else}}
49
+ You can view this file with: `read_file("{{ file_path }}")`
50
+ {{/if}}
51
+ </related>
52
+ {{/each}}
53
+ {{/if}}
54
+
55
+ </memory>
56
+ {{/each}}
57
+ {{else}}
58
+ The supplied query did not return any information specifically on this topic.
59
+
60
+ ## Opportunity to Capture New Knowledge!
61
+
62
+ This is an excellent chance to start documenting this topic:
63
+
64
+ ```python
65
+ await write_note(
66
+ title="{{ topic }}",
67
+ content=f'''
68
+ # {{ topic }}
69
+
70
+ ## Overview
71
+ [Summary of what we know about {{ topic }}]
72
+
73
+ ## Key Points
74
+ [Main aspects or components of {{ topic }}]
75
+
76
+ ## Observations
77
+ - [category] [First important observation about {{ topic }}]
78
+ - [category] [Second observation about {{ topic }}]
79
+
80
+ ## Relations
81
+ - relates_to [[Related Topic]]
82
+ - part_of [[Broader Context]]
83
+ '''
84
+ )
85
+ ```
86
+
87
+ ## Other Options
88
+
89
+ Please use the available basic-memory tools to gather relevant context before responding.
90
+ You can also:
91
+ - Try a different search term
92
+ - Check recent activity with `recent_activity(timeframe="1w")`
93
+ {{/if}}
94
+ ## Next Steps
95
+ <instructions>
96
+ You can:
97
+ - Explore more with: `search_notes("{{ topic }}")`
98
+ - See what's changed: `recent_activity(timeframe="{{default timeframe "7d"}}")`
99
+ - **Record new learnings or decisions from this conversation:** `write_note(folder="[Choose a folder]" title="[Create a meaningful title]", content="[Content with observations and relations]")`
100
+
101
+ ## Knowledge Capture Recommendation
102
+
103
+ As you continue this conversation, **actively look for opportunities to:**
104
+ 1. Record key information, decisions, or insights that emerge
105
+ 2. Link new knowledge to existing topics
106
+ 3. Suggest capturing important context when appropriate
107
+ 4. Create forward references to topics that might be created later
108
+
109
+ Remember that capturing knowledge during conversations is one of the most valuable aspects of Basic Memory.
110
+ </instructions>
@@ -0,0 +1,101 @@
1
+ # Search Results for: "{{ query }}"{{#if timeframe}} (after {{ timeframe }}){{/if}}
2
+
3
+ This is a memory search session.
4
+ Please use the available basic-memory tools to gather relevant context before responding.
5
+ I found {{ result_count }} result(s) that match your query.
6
+
7
+ {{#if has_results}}
8
+ Here are the most relevant results:
9
+
10
+ {{#each results}}
11
+ {{#if_cond (lt @index 5)}}
12
+ {{#dedent}}
13
+ ## {{math @index "+" 1}}. {{ title }}
14
+ - **Type**: {{ type.value }}
15
+ {{#if metadata.created_at}}
16
+ - **Created**: {{date metadata.created_at "%Y-%m-%d %H:%M"}}
17
+ {{/if}}
18
+ - **Relevance Score**: {{round score 2}}
19
+
20
+ {{#if content}}
21
+ - **Excerpt**:
22
+ {{ content }}
23
+ {{/if}}
24
+
25
+ {{#if permalink}}
26
+ You can view this content with: `read_note("{{ permalink }}")`
27
+ Or explore its context with: `build_context("memory://{{ permalink }}")`
28
+ {{else}}
29
+ You can view this file with: `read_file("{{ file_path }}")`
30
+ {{/if}}
31
+ {{/dedent}}
32
+ {{/if_cond}}
33
+ {{/each}}
34
+
35
+ ## Next Steps
36
+
37
+ You can:
38
+ - Refine your search: `search_notes("{{ query }} AND additional_term")`
39
+ - Exclude terms: `search_notes("{{ query }} NOT exclude_term")`
40
+ - View more results: `search_notes("{{ query }}", after_date=None)`
41
+ - Check recent activity: `recent_activity()`
42
+
43
+ ## Synthesize and Capture Knowledge
44
+
45
+ Consider creating a new note that synthesizes what you've learned:
46
+
47
+ ```python
48
+ await write_note(
49
+ title="Synthesis of {{capitalize query}} Information",
50
+ content='''
51
+ # Synthesis of {{capitalize query}} Information
52
+
53
+ ## Overview
54
+ [Synthesis of the search results and your conversation]
55
+
56
+ ## Key Insights
57
+ [Summary of main points learned from these results]
58
+
59
+ ## Observations
60
+ - [insight] [Important observation from search results]
61
+ - [connection] [How this connects to other topics]
62
+
63
+ ## Relations
64
+ - relates_to [[{{#if results.length}}{{#if results.0.title}}{{results.0.title}}{{else}}Related Topic{{/if}}{{else}}Related Topic{{/if}}]]
65
+ - extends [[Another Relevant Topic]]
66
+ '''
67
+ )
68
+ ```
69
+
70
+ Remember that capturing synthesized knowledge is one of the most valuable features of Basic Memory.
71
+ {{else}}
72
+ I couldn't find any results for this query.
73
+
74
+ ## Opportunity to Capture Knowledge!
75
+
76
+ This is an excellent opportunity to create new knowledge on this topic. Consider:
77
+
78
+ ```python
79
+ await write_note(
80
+ title="{{capitalize query}}",
81
+ content='''
82
+ # {{capitalize query}}
83
+
84
+ ## Overview
85
+ [Summary of what we've discussed about {{ query }}]
86
+
87
+ ## Observations
88
+ - [category] [First observation about {{ query }}]
89
+ - [category] [Second observation about {{ query }}]
90
+
91
+ ## Relations
92
+ - relates_to [[Other Relevant Topic]]
93
+ '''
94
+ )
95
+ ```
96
+
97
+ ## Other Suggestions
98
+ - Try a different search term
99
+ - Broaden your search criteria
100
+ - Check recent activity with `recent_activity(timeframe="1w")`
101
+ {{/if}}