basic-memory 0.14.4__py3-none-any.whl → 0.15.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.
Potentially problematic release.
This version of basic-memory might be problematic. Click here for more details.
- basic_memory/__init__.py +1 -1
- basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +5 -9
- basic_memory/api/app.py +10 -4
- basic_memory/api/routers/directory_router.py +23 -2
- basic_memory/api/routers/knowledge_router.py +25 -8
- basic_memory/api/routers/project_router.py +100 -4
- basic_memory/cli/app.py +9 -28
- basic_memory/cli/auth.py +277 -0
- basic_memory/cli/commands/cloud/__init__.py +5 -0
- basic_memory/cli/commands/cloud/api_client.py +112 -0
- basic_memory/cli/commands/cloud/bisync_commands.py +818 -0
- basic_memory/cli/commands/cloud/core_commands.py +288 -0
- basic_memory/cli/commands/cloud/mount_commands.py +295 -0
- basic_memory/cli/commands/cloud/rclone_config.py +288 -0
- basic_memory/cli/commands/cloud/rclone_installer.py +198 -0
- basic_memory/cli/commands/command_utils.py +43 -0
- basic_memory/cli/commands/import_memory_json.py +0 -4
- basic_memory/cli/commands/mcp.py +77 -60
- basic_memory/cli/commands/project.py +154 -152
- basic_memory/cli/commands/status.py +25 -22
- basic_memory/cli/commands/sync.py +45 -228
- basic_memory/cli/commands/tool.py +87 -16
- basic_memory/cli/main.py +1 -0
- basic_memory/config.py +131 -21
- basic_memory/db.py +104 -3
- basic_memory/deps.py +27 -8
- basic_memory/file_utils.py +37 -13
- basic_memory/ignore_utils.py +295 -0
- basic_memory/markdown/plugins.py +9 -7
- basic_memory/mcp/async_client.py +124 -14
- basic_memory/mcp/project_context.py +141 -0
- basic_memory/mcp/prompts/ai_assistant_guide.py +49 -4
- basic_memory/mcp/prompts/continue_conversation.py +17 -16
- basic_memory/mcp/prompts/recent_activity.py +116 -32
- basic_memory/mcp/prompts/search.py +13 -12
- basic_memory/mcp/prompts/utils.py +11 -4
- basic_memory/mcp/resources/ai_assistant_guide.md +211 -341
- basic_memory/mcp/resources/project_info.py +27 -11
- basic_memory/mcp/server.py +0 -37
- basic_memory/mcp/tools/__init__.py +5 -6
- basic_memory/mcp/tools/build_context.py +67 -56
- basic_memory/mcp/tools/canvas.py +38 -26
- basic_memory/mcp/tools/chatgpt_tools.py +187 -0
- basic_memory/mcp/tools/delete_note.py +81 -47
- basic_memory/mcp/tools/edit_note.py +155 -138
- basic_memory/mcp/tools/list_directory.py +112 -99
- basic_memory/mcp/tools/move_note.py +181 -101
- basic_memory/mcp/tools/project_management.py +113 -277
- basic_memory/mcp/tools/read_content.py +91 -74
- basic_memory/mcp/tools/read_note.py +152 -115
- basic_memory/mcp/tools/recent_activity.py +471 -68
- basic_memory/mcp/tools/search.py +105 -92
- basic_memory/mcp/tools/sync_status.py +136 -130
- basic_memory/mcp/tools/utils.py +4 -0
- basic_memory/mcp/tools/view_note.py +44 -33
- basic_memory/mcp/tools/write_note.py +151 -90
- basic_memory/models/knowledge.py +12 -6
- basic_memory/models/project.py +6 -2
- basic_memory/repository/entity_repository.py +89 -82
- basic_memory/repository/relation_repository.py +13 -0
- basic_memory/repository/repository.py +18 -5
- basic_memory/repository/search_repository.py +46 -2
- basic_memory/schemas/__init__.py +6 -0
- basic_memory/schemas/base.py +39 -11
- basic_memory/schemas/cloud.py +46 -0
- basic_memory/schemas/memory.py +90 -21
- basic_memory/schemas/project_info.py +9 -10
- basic_memory/schemas/sync_report.py +48 -0
- basic_memory/services/context_service.py +25 -11
- basic_memory/services/directory_service.py +124 -3
- basic_memory/services/entity_service.py +100 -48
- basic_memory/services/initialization.py +30 -11
- basic_memory/services/project_service.py +101 -24
- basic_memory/services/search_service.py +16 -8
- basic_memory/sync/sync_service.py +173 -34
- basic_memory/sync/watch_service.py +101 -40
- basic_memory/utils.py +14 -4
- {basic_memory-0.14.4.dist-info → basic_memory-0.15.1.dist-info}/METADATA +57 -9
- basic_memory-0.15.1.dist-info/RECORD +146 -0
- basic_memory/mcp/project_session.py +0 -120
- basic_memory-0.14.4.dist-info/RECORD +0 -133
- {basic_memory-0.14.4.dist-info → basic_memory-0.15.1.dist-info}/WHEEL +0 -0
- {basic_memory-0.14.4.dist-info → basic_memory-0.15.1.dist-info}/entry_points.txt +0 -0
- {basic_memory-0.14.4.dist-info → basic_memory-0.15.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,15 +2,16 @@ from textwrap import dedent
|
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
4
|
from loguru import logger
|
|
5
|
+
from fastmcp import Context
|
|
5
6
|
|
|
7
|
+
from basic_memory.mcp.project_context import get_active_project
|
|
6
8
|
from basic_memory.mcp.tools.utils import call_delete
|
|
7
9
|
from basic_memory.mcp.server import mcp
|
|
8
|
-
from basic_memory.mcp.async_client import
|
|
9
|
-
from basic_memory.mcp.project_session import get_active_project
|
|
10
|
+
from basic_memory.mcp.async_client import get_client
|
|
10
11
|
from basic_memory.schemas import DeleteEntitiesResponse
|
|
11
12
|
|
|
12
13
|
|
|
13
|
-
def _format_delete_error_response(error_message: str, identifier: str) -> str:
|
|
14
|
+
def _format_delete_error_response(project: str, error_message: str, identifier: str) -> str:
|
|
14
15
|
"""Format helpful error responses for delete failures that guide users to successful deletions."""
|
|
15
16
|
|
|
16
17
|
# Note not found errors
|
|
@@ -24,7 +25,7 @@ def _format_delete_error_response(error_message: str, identifier: str) -> str:
|
|
|
24
25
|
return dedent(f"""
|
|
25
26
|
# Delete Failed - Note Not Found
|
|
26
27
|
|
|
27
|
-
The note '{identifier}' could not be found for deletion.
|
|
28
|
+
The note '{identifier}' could not be found for deletion in {project}.
|
|
28
29
|
|
|
29
30
|
## This might mean:
|
|
30
31
|
1. **Already deleted**: The note may have been deleted previously
|
|
@@ -32,21 +33,21 @@ def _format_delete_error_response(error_message: str, identifier: str) -> str:
|
|
|
32
33
|
3. **Different project**: The note might be in a different project
|
|
33
34
|
|
|
34
35
|
## How to verify:
|
|
35
|
-
1. **Search for the note**: Use `search_notes("{search_term}")` to find it
|
|
36
|
+
1. **Search for the note**: Use `search_notes("{project}", "{search_term}")` to find it
|
|
36
37
|
2. **Try different formats**:
|
|
37
38
|
- If you used a permalink like "folder/note-title", try just the title: "{title_format}"
|
|
38
39
|
- If you used a title, try the permalink format: "{permalink_format}"
|
|
39
40
|
|
|
40
41
|
3. **Check if already deleted**: Use `list_directory("/")` to see what notes exist
|
|
41
|
-
4. **
|
|
42
|
+
4. **List notes in project**: Use `list_directory("/")` to see what notes exist in the current project
|
|
42
43
|
|
|
43
44
|
## If the note actually exists:
|
|
44
45
|
```
|
|
45
46
|
# First, find the correct identifier:
|
|
46
|
-
search_notes("{identifier}")
|
|
47
|
+
search_notes("{project}", "{identifier}")
|
|
47
48
|
|
|
48
49
|
# Then delete using the correct identifier:
|
|
49
|
-
delete_note("correct-identifier-from-search")
|
|
50
|
+
delete_note("{project}", "correct-identifier-from-search")
|
|
50
51
|
```
|
|
51
52
|
|
|
52
53
|
## If you want to delete multiple similar notes:
|
|
@@ -69,12 +70,12 @@ You don't have permission to delete '{identifier}': {error_message}
|
|
|
69
70
|
3. **Project access**: Ensure you're in the correct project with proper permissions
|
|
70
71
|
|
|
71
72
|
## Alternative actions:
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
- Verify note exists first: `read_note("{identifier}")`
|
|
73
|
+
- List available projects: `list_memory_projects()`
|
|
74
|
+
- Specify the correct project: `delete_note("{identifier}", project="project-name")`
|
|
75
|
+
- Verify note exists first: `read_note("{identifier}", project="project-name")`
|
|
75
76
|
|
|
76
77
|
## If you have read-only access:
|
|
77
|
-
|
|
78
|
+
Ask someone with write access to delete the note."""
|
|
78
79
|
|
|
79
80
|
# Server/filesystem errors
|
|
80
81
|
if (
|
|
@@ -92,8 +93,7 @@ A system error occurred while deleting '{identifier}': {error_message}
|
|
|
92
93
|
3. **Check disk space**: Ensure the system has adequate storage
|
|
93
94
|
|
|
94
95
|
## Troubleshooting:
|
|
95
|
-
- Verify note exists: `read_note("{identifier}")`
|
|
96
|
-
- Check project status: `get_current_project()`
|
|
96
|
+
- Verify note exists: `read_note("{project}","{identifier}")`
|
|
97
97
|
- Try again in a few moments
|
|
98
98
|
|
|
99
99
|
## If problem persists:
|
|
@@ -112,7 +112,7 @@ A database error occurred while deleting '{identifier}': {error_message}
|
|
|
112
112
|
|
|
113
113
|
## Steps to resolve:
|
|
114
114
|
1. **Try again**: Wait a moment and retry the deletion
|
|
115
|
-
2. **Check note status**: `read_note("{identifier}")` to see current state
|
|
115
|
+
2. **Check note status**: `read_note("{project}","{identifier}")` to see current state
|
|
116
116
|
3. **Manual verification**: Use `list_directory()` to see if file still exists
|
|
117
117
|
|
|
118
118
|
## If the note appears gone but database shows it exists:
|
|
@@ -124,7 +124,7 @@ Send a message to support@basicmachines.co - a manual database cleanup may be ne
|
|
|
124
124
|
Error deleting note '{identifier}': {error_message}
|
|
125
125
|
|
|
126
126
|
## General troubleshooting:
|
|
127
|
-
1. **Verify the note exists**: `read_note("{identifier}")` or `search_notes("{identifier}")`
|
|
127
|
+
1. **Verify the note exists**: `read_note("{project}", "{identifier}")` or `search_notes("{project}", "{identifier}")`
|
|
128
128
|
2. **Check permissions**: Ensure you can edit/delete files in this project
|
|
129
129
|
3. **Try again**: The error might be temporary
|
|
130
130
|
4. **Check project**: Make sure you're in the correct project
|
|
@@ -132,60 +132,94 @@ Error deleting note '{identifier}': {error_message}
|
|
|
132
132
|
## Step-by-step approach:
|
|
133
133
|
```
|
|
134
134
|
# 1. Confirm note exists and get correct identifier
|
|
135
|
-
search_notes("{identifier}")
|
|
135
|
+
search_notes("{project}", "{identifier}")
|
|
136
136
|
|
|
137
137
|
# 2. Read the note to verify access
|
|
138
|
-
read_note("correct-identifier-from-search")
|
|
138
|
+
read_note("{project}", "correct-identifier-from-search")
|
|
139
139
|
|
|
140
140
|
# 3. Try deletion with correct identifier
|
|
141
|
-
delete_note("correct-identifier-from-search")
|
|
141
|
+
delete_note("{project}", "correct-identifier-from-search")
|
|
142
142
|
```
|
|
143
143
|
|
|
144
144
|
## Alternative approaches:
|
|
145
|
-
- Check what notes exist: `list_directory("/")`
|
|
146
|
-
- Verify current project: `get_current_project()`
|
|
147
|
-
- Switch projects if needed: `switch_project("correct-project")`
|
|
145
|
+
- Check what notes exist: `list_directory("{project}", "/")`
|
|
148
146
|
|
|
149
147
|
## Need help?
|
|
150
|
-
If the note should be deleted but the operation keeps failing, send a message to support@
|
|
148
|
+
If the note should be deleted but the operation keeps failing, send a message to support@basicmemory.com."""
|
|
151
149
|
|
|
152
150
|
|
|
153
151
|
@mcp.tool(description="Delete a note by title or permalink")
|
|
154
|
-
async def delete_note(
|
|
152
|
+
async def delete_note(
|
|
153
|
+
identifier: str, project: Optional[str] = None, context: Context | None = None
|
|
154
|
+
) -> bool | str:
|
|
155
155
|
"""Delete a note from the knowledge base.
|
|
156
156
|
|
|
157
|
+
Permanently removes a note from the specified project. The note is identified
|
|
158
|
+
by title or permalink. If the note doesn't exist, the operation returns False
|
|
159
|
+
without error. If deletion fails due to other issues, helpful error messages are provided.
|
|
160
|
+
|
|
161
|
+
Project Resolution:
|
|
162
|
+
Server resolves projects in this order: Single Project Mode → project parameter → default project.
|
|
163
|
+
If project unknown, use list_memory_projects() or recent_activity() first.
|
|
164
|
+
|
|
157
165
|
Args:
|
|
158
|
-
|
|
159
|
-
|
|
166
|
+
project: Project name to delete from. Optional - server will resolve using hierarchy.
|
|
167
|
+
If unknown, use list_memory_projects() to discover available projects.
|
|
168
|
+
identifier: Note title or permalink to delete
|
|
169
|
+
Can be a title like "Meeting Notes" or permalink like "notes/meeting-notes"
|
|
170
|
+
context: Optional FastMCP context for performance caching.
|
|
160
171
|
|
|
161
172
|
Returns:
|
|
162
|
-
True if note was deleted, False
|
|
173
|
+
True if note was successfully deleted, False if note was not found.
|
|
174
|
+
On errors, returns a formatted string with helpful troubleshooting guidance.
|
|
163
175
|
|
|
164
176
|
Examples:
|
|
165
177
|
# Delete by title
|
|
166
|
-
delete_note("Meeting Notes: Project Planning")
|
|
178
|
+
delete_note("my-project", "Meeting Notes: Project Planning")
|
|
167
179
|
|
|
168
180
|
# Delete by permalink
|
|
169
|
-
delete_note("notes/project-planning")
|
|
170
|
-
|
|
171
|
-
# Delete from specific project
|
|
172
|
-
delete_note("notes/project-planning", project="work-project")
|
|
173
|
-
"""
|
|
174
|
-
active_project = get_active_project(project)
|
|
175
|
-
project_url = active_project.project_url
|
|
181
|
+
delete_note("work-docs", "notes/project-planning")
|
|
176
182
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
result = DeleteEntitiesResponse.model_validate(response.json())
|
|
183
|
+
# Delete with exact path
|
|
184
|
+
delete_note("research", "experiments/ml-model-results")
|
|
180
185
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
186
|
+
# Common usage pattern
|
|
187
|
+
if delete_note("my-project", "old-draft"):
|
|
188
|
+
print("Note deleted successfully")
|
|
184
189
|
else:
|
|
185
|
-
|
|
186
|
-
return False
|
|
190
|
+
print("Note not found or already deleted")
|
|
187
191
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
+
Raises:
|
|
193
|
+
HTTPError: If project doesn't exist or is inaccessible
|
|
194
|
+
SecurityError: If identifier attempts path traversal
|
|
195
|
+
|
|
196
|
+
Warning:
|
|
197
|
+
This operation is permanent and cannot be undone. The note file
|
|
198
|
+
will be removed from the filesystem and all references will be lost.
|
|
199
|
+
|
|
200
|
+
Note:
|
|
201
|
+
If the note is not found, this function provides helpful error messages
|
|
202
|
+
with suggestions for finding the correct identifier, including search
|
|
203
|
+
commands and alternative formats to try.
|
|
204
|
+
"""
|
|
205
|
+
async with get_client() as client:
|
|
206
|
+
active_project = await get_active_project(client, project, context)
|
|
207
|
+
project_url = active_project.project_url
|
|
208
|
+
|
|
209
|
+
try:
|
|
210
|
+
response = await call_delete(client, f"{project_url}/knowledge/entities/{identifier}")
|
|
211
|
+
result = DeleteEntitiesResponse.model_validate(response.json())
|
|
212
|
+
|
|
213
|
+
if result.deleted:
|
|
214
|
+
logger.info(
|
|
215
|
+
f"Successfully deleted note: {identifier} in project: {active_project.name}"
|
|
216
|
+
)
|
|
217
|
+
return True
|
|
218
|
+
else:
|
|
219
|
+
logger.warning(f"Delete operation completed but note was not deleted: {identifier}")
|
|
220
|
+
return False
|
|
221
|
+
|
|
222
|
+
except Exception as e: # pragma: no cover
|
|
223
|
+
logger.error(f"Delete failed for '{identifier}': {e}, project: {active_project.name}")
|
|
224
|
+
# Return formatted error message for better user experience
|
|
225
|
+
return _format_delete_error_response(active_project.name, str(e), identifier)
|