basic-memory 0.17.1__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.
- basic_memory/__init__.py +7 -0
- basic_memory/alembic/alembic.ini +119 -0
- basic_memory/alembic/env.py +185 -0
- basic_memory/alembic/migrations.py +24 -0
- basic_memory/alembic/script.py.mako +26 -0
- basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +131 -0
- basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +93 -0
- basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +51 -0
- basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +120 -0
- basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +112 -0
- basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +49 -0
- basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +49 -0
- basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +56 -0
- basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +44 -0
- basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +113 -0
- basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +37 -0
- basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +239 -0
- basic_memory/api/__init__.py +5 -0
- basic_memory/api/app.py +131 -0
- basic_memory/api/routers/__init__.py +11 -0
- basic_memory/api/routers/directory_router.py +84 -0
- basic_memory/api/routers/importer_router.py +152 -0
- basic_memory/api/routers/knowledge_router.py +318 -0
- basic_memory/api/routers/management_router.py +80 -0
- basic_memory/api/routers/memory_router.py +90 -0
- basic_memory/api/routers/project_router.py +448 -0
- basic_memory/api/routers/prompt_router.py +260 -0
- basic_memory/api/routers/resource_router.py +249 -0
- basic_memory/api/routers/search_router.py +36 -0
- basic_memory/api/routers/utils.py +169 -0
- basic_memory/api/template_loader.py +292 -0
- basic_memory/api/v2/__init__.py +35 -0
- basic_memory/api/v2/routers/__init__.py +21 -0
- basic_memory/api/v2/routers/directory_router.py +93 -0
- basic_memory/api/v2/routers/importer_router.py +182 -0
- basic_memory/api/v2/routers/knowledge_router.py +413 -0
- basic_memory/api/v2/routers/memory_router.py +130 -0
- basic_memory/api/v2/routers/project_router.py +342 -0
- basic_memory/api/v2/routers/prompt_router.py +270 -0
- basic_memory/api/v2/routers/resource_router.py +286 -0
- basic_memory/api/v2/routers/search_router.py +73 -0
- basic_memory/cli/__init__.py +1 -0
- basic_memory/cli/app.py +84 -0
- basic_memory/cli/auth.py +277 -0
- basic_memory/cli/commands/__init__.py +18 -0
- basic_memory/cli/commands/cloud/__init__.py +6 -0
- basic_memory/cli/commands/cloud/api_client.py +112 -0
- basic_memory/cli/commands/cloud/bisync_commands.py +110 -0
- basic_memory/cli/commands/cloud/cloud_utils.py +101 -0
- basic_memory/cli/commands/cloud/core_commands.py +195 -0
- basic_memory/cli/commands/cloud/rclone_commands.py +371 -0
- basic_memory/cli/commands/cloud/rclone_config.py +110 -0
- basic_memory/cli/commands/cloud/rclone_installer.py +263 -0
- basic_memory/cli/commands/cloud/upload.py +233 -0
- basic_memory/cli/commands/cloud/upload_command.py +124 -0
- basic_memory/cli/commands/command_utils.py +77 -0
- basic_memory/cli/commands/db.py +44 -0
- basic_memory/cli/commands/format.py +198 -0
- basic_memory/cli/commands/import_chatgpt.py +84 -0
- basic_memory/cli/commands/import_claude_conversations.py +87 -0
- basic_memory/cli/commands/import_claude_projects.py +86 -0
- basic_memory/cli/commands/import_memory_json.py +87 -0
- basic_memory/cli/commands/mcp.py +76 -0
- basic_memory/cli/commands/project.py +889 -0
- basic_memory/cli/commands/status.py +174 -0
- basic_memory/cli/commands/telemetry.py +81 -0
- basic_memory/cli/commands/tool.py +341 -0
- basic_memory/cli/main.py +28 -0
- basic_memory/config.py +616 -0
- basic_memory/db.py +394 -0
- basic_memory/deps.py +705 -0
- basic_memory/file_utils.py +478 -0
- basic_memory/ignore_utils.py +297 -0
- basic_memory/importers/__init__.py +27 -0
- basic_memory/importers/base.py +79 -0
- basic_memory/importers/chatgpt_importer.py +232 -0
- basic_memory/importers/claude_conversations_importer.py +180 -0
- basic_memory/importers/claude_projects_importer.py +148 -0
- basic_memory/importers/memory_json_importer.py +108 -0
- basic_memory/importers/utils.py +61 -0
- basic_memory/markdown/__init__.py +21 -0
- basic_memory/markdown/entity_parser.py +279 -0
- basic_memory/markdown/markdown_processor.py +160 -0
- basic_memory/markdown/plugins.py +242 -0
- basic_memory/markdown/schemas.py +70 -0
- basic_memory/markdown/utils.py +117 -0
- basic_memory/mcp/__init__.py +1 -0
- basic_memory/mcp/async_client.py +139 -0
- basic_memory/mcp/project_context.py +141 -0
- basic_memory/mcp/prompts/__init__.py +19 -0
- basic_memory/mcp/prompts/ai_assistant_guide.py +70 -0
- basic_memory/mcp/prompts/continue_conversation.py +62 -0
- basic_memory/mcp/prompts/recent_activity.py +188 -0
- basic_memory/mcp/prompts/search.py +57 -0
- basic_memory/mcp/prompts/utils.py +162 -0
- basic_memory/mcp/resources/ai_assistant_guide.md +283 -0
- basic_memory/mcp/resources/project_info.py +71 -0
- basic_memory/mcp/server.py +81 -0
- basic_memory/mcp/tools/__init__.py +48 -0
- basic_memory/mcp/tools/build_context.py +120 -0
- basic_memory/mcp/tools/canvas.py +152 -0
- basic_memory/mcp/tools/chatgpt_tools.py +190 -0
- basic_memory/mcp/tools/delete_note.py +242 -0
- basic_memory/mcp/tools/edit_note.py +324 -0
- basic_memory/mcp/tools/list_directory.py +168 -0
- basic_memory/mcp/tools/move_note.py +551 -0
- basic_memory/mcp/tools/project_management.py +201 -0
- basic_memory/mcp/tools/read_content.py +281 -0
- basic_memory/mcp/tools/read_note.py +267 -0
- basic_memory/mcp/tools/recent_activity.py +534 -0
- basic_memory/mcp/tools/search.py +385 -0
- basic_memory/mcp/tools/utils.py +540 -0
- basic_memory/mcp/tools/view_note.py +78 -0
- basic_memory/mcp/tools/write_note.py +230 -0
- basic_memory/models/__init__.py +15 -0
- basic_memory/models/base.py +10 -0
- basic_memory/models/knowledge.py +226 -0
- basic_memory/models/project.py +87 -0
- basic_memory/models/search.py +85 -0
- basic_memory/repository/__init__.py +11 -0
- basic_memory/repository/entity_repository.py +503 -0
- basic_memory/repository/observation_repository.py +73 -0
- basic_memory/repository/postgres_search_repository.py +379 -0
- basic_memory/repository/project_info_repository.py +10 -0
- basic_memory/repository/project_repository.py +128 -0
- basic_memory/repository/relation_repository.py +146 -0
- basic_memory/repository/repository.py +385 -0
- basic_memory/repository/search_index_row.py +95 -0
- basic_memory/repository/search_repository.py +94 -0
- basic_memory/repository/search_repository_base.py +241 -0
- basic_memory/repository/sqlite_search_repository.py +439 -0
- basic_memory/schemas/__init__.py +86 -0
- basic_memory/schemas/base.py +297 -0
- basic_memory/schemas/cloud.py +50 -0
- basic_memory/schemas/delete.py +37 -0
- basic_memory/schemas/directory.py +30 -0
- basic_memory/schemas/importer.py +35 -0
- basic_memory/schemas/memory.py +285 -0
- basic_memory/schemas/project_info.py +212 -0
- basic_memory/schemas/prompt.py +90 -0
- basic_memory/schemas/request.py +112 -0
- basic_memory/schemas/response.py +229 -0
- basic_memory/schemas/search.py +117 -0
- basic_memory/schemas/sync_report.py +72 -0
- basic_memory/schemas/v2/__init__.py +27 -0
- basic_memory/schemas/v2/entity.py +129 -0
- basic_memory/schemas/v2/resource.py +46 -0
- basic_memory/services/__init__.py +8 -0
- basic_memory/services/context_service.py +601 -0
- basic_memory/services/directory_service.py +308 -0
- basic_memory/services/entity_service.py +864 -0
- basic_memory/services/exceptions.py +37 -0
- basic_memory/services/file_service.py +541 -0
- basic_memory/services/initialization.py +216 -0
- basic_memory/services/link_resolver.py +121 -0
- basic_memory/services/project_service.py +880 -0
- basic_memory/services/search_service.py +404 -0
- basic_memory/services/service.py +15 -0
- basic_memory/sync/__init__.py +6 -0
- basic_memory/sync/background_sync.py +26 -0
- basic_memory/sync/sync_service.py +1259 -0
- basic_memory/sync/watch_service.py +510 -0
- basic_memory/telemetry.py +249 -0
- basic_memory/templates/prompts/continue_conversation.hbs +110 -0
- basic_memory/templates/prompts/search.hbs +101 -0
- basic_memory/utils.py +468 -0
- basic_memory-0.17.1.dist-info/METADATA +617 -0
- basic_memory-0.17.1.dist-info/RECORD +171 -0
- basic_memory-0.17.1.dist-info/WHEEL +4 -0
- basic_memory-0.17.1.dist-info/entry_points.txt +3 -0
- basic_memory-0.17.1.dist-info/licenses/LICENSE +661 -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}}
|