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.
Files changed (171) hide show
  1. basic_memory/__init__.py +7 -0
  2. basic_memory/alembic/alembic.ini +119 -0
  3. basic_memory/alembic/env.py +185 -0
  4. basic_memory/alembic/migrations.py +24 -0
  5. basic_memory/alembic/script.py.mako +26 -0
  6. basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +131 -0
  7. basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +93 -0
  8. basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +51 -0
  9. basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +120 -0
  10. basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +112 -0
  11. basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +49 -0
  12. basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +49 -0
  13. basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +56 -0
  14. basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +44 -0
  15. basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +113 -0
  16. basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +37 -0
  17. basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +239 -0
  18. basic_memory/api/__init__.py +5 -0
  19. basic_memory/api/app.py +131 -0
  20. basic_memory/api/routers/__init__.py +11 -0
  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 +318 -0
  24. basic_memory/api/routers/management_router.py +80 -0
  25. basic_memory/api/routers/memory_router.py +90 -0
  26. basic_memory/api/routers/project_router.py +448 -0
  27. basic_memory/api/routers/prompt_router.py +260 -0
  28. basic_memory/api/routers/resource_router.py +249 -0
  29. basic_memory/api/routers/search_router.py +36 -0
  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 +182 -0
  36. basic_memory/api/v2/routers/knowledge_router.py +413 -0
  37. basic_memory/api/v2/routers/memory_router.py +130 -0
  38. basic_memory/api/v2/routers/project_router.py +342 -0
  39. basic_memory/api/v2/routers/prompt_router.py +270 -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/__init__.py +1 -0
  43. basic_memory/cli/app.py +84 -0
  44. basic_memory/cli/auth.py +277 -0
  45. basic_memory/cli/commands/__init__.py +18 -0
  46. basic_memory/cli/commands/cloud/__init__.py +6 -0
  47. basic_memory/cli/commands/cloud/api_client.py +112 -0
  48. basic_memory/cli/commands/cloud/bisync_commands.py +110 -0
  49. basic_memory/cli/commands/cloud/cloud_utils.py +101 -0
  50. basic_memory/cli/commands/cloud/core_commands.py +195 -0
  51. basic_memory/cli/commands/cloud/rclone_commands.py +371 -0
  52. basic_memory/cli/commands/cloud/rclone_config.py +110 -0
  53. basic_memory/cli/commands/cloud/rclone_installer.py +263 -0
  54. basic_memory/cli/commands/cloud/upload.py +233 -0
  55. basic_memory/cli/commands/cloud/upload_command.py +124 -0
  56. basic_memory/cli/commands/command_utils.py +77 -0
  57. basic_memory/cli/commands/db.py +44 -0
  58. basic_memory/cli/commands/format.py +198 -0
  59. basic_memory/cli/commands/import_chatgpt.py +84 -0
  60. basic_memory/cli/commands/import_claude_conversations.py +87 -0
  61. basic_memory/cli/commands/import_claude_projects.py +86 -0
  62. basic_memory/cli/commands/import_memory_json.py +87 -0
  63. basic_memory/cli/commands/mcp.py +76 -0
  64. basic_memory/cli/commands/project.py +889 -0
  65. basic_memory/cli/commands/status.py +174 -0
  66. basic_memory/cli/commands/telemetry.py +81 -0
  67. basic_memory/cli/commands/tool.py +341 -0
  68. basic_memory/cli/main.py +28 -0
  69. basic_memory/config.py +616 -0
  70. basic_memory/db.py +394 -0
  71. basic_memory/deps.py +705 -0
  72. basic_memory/file_utils.py +478 -0
  73. basic_memory/ignore_utils.py +297 -0
  74. basic_memory/importers/__init__.py +27 -0
  75. basic_memory/importers/base.py +79 -0
  76. basic_memory/importers/chatgpt_importer.py +232 -0
  77. basic_memory/importers/claude_conversations_importer.py +180 -0
  78. basic_memory/importers/claude_projects_importer.py +148 -0
  79. basic_memory/importers/memory_json_importer.py +108 -0
  80. basic_memory/importers/utils.py +61 -0
  81. basic_memory/markdown/__init__.py +21 -0
  82. basic_memory/markdown/entity_parser.py +279 -0
  83. basic_memory/markdown/markdown_processor.py +160 -0
  84. basic_memory/markdown/plugins.py +242 -0
  85. basic_memory/markdown/schemas.py +70 -0
  86. basic_memory/markdown/utils.py +117 -0
  87. basic_memory/mcp/__init__.py +1 -0
  88. basic_memory/mcp/async_client.py +139 -0
  89. basic_memory/mcp/project_context.py +141 -0
  90. basic_memory/mcp/prompts/__init__.py +19 -0
  91. basic_memory/mcp/prompts/ai_assistant_guide.py +70 -0
  92. basic_memory/mcp/prompts/continue_conversation.py +62 -0
  93. basic_memory/mcp/prompts/recent_activity.py +188 -0
  94. basic_memory/mcp/prompts/search.py +57 -0
  95. basic_memory/mcp/prompts/utils.py +162 -0
  96. basic_memory/mcp/resources/ai_assistant_guide.md +283 -0
  97. basic_memory/mcp/resources/project_info.py +71 -0
  98. basic_memory/mcp/server.py +81 -0
  99. basic_memory/mcp/tools/__init__.py +48 -0
  100. basic_memory/mcp/tools/build_context.py +120 -0
  101. basic_memory/mcp/tools/canvas.py +152 -0
  102. basic_memory/mcp/tools/chatgpt_tools.py +190 -0
  103. basic_memory/mcp/tools/delete_note.py +242 -0
  104. basic_memory/mcp/tools/edit_note.py +324 -0
  105. basic_memory/mcp/tools/list_directory.py +168 -0
  106. basic_memory/mcp/tools/move_note.py +551 -0
  107. basic_memory/mcp/tools/project_management.py +201 -0
  108. basic_memory/mcp/tools/read_content.py +281 -0
  109. basic_memory/mcp/tools/read_note.py +267 -0
  110. basic_memory/mcp/tools/recent_activity.py +534 -0
  111. basic_memory/mcp/tools/search.py +385 -0
  112. basic_memory/mcp/tools/utils.py +540 -0
  113. basic_memory/mcp/tools/view_note.py +78 -0
  114. basic_memory/mcp/tools/write_note.py +230 -0
  115. basic_memory/models/__init__.py +15 -0
  116. basic_memory/models/base.py +10 -0
  117. basic_memory/models/knowledge.py +226 -0
  118. basic_memory/models/project.py +87 -0
  119. basic_memory/models/search.py +85 -0
  120. basic_memory/repository/__init__.py +11 -0
  121. basic_memory/repository/entity_repository.py +503 -0
  122. basic_memory/repository/observation_repository.py +73 -0
  123. basic_memory/repository/postgres_search_repository.py +379 -0
  124. basic_memory/repository/project_info_repository.py +10 -0
  125. basic_memory/repository/project_repository.py +128 -0
  126. basic_memory/repository/relation_repository.py +146 -0
  127. basic_memory/repository/repository.py +385 -0
  128. basic_memory/repository/search_index_row.py +95 -0
  129. basic_memory/repository/search_repository.py +94 -0
  130. basic_memory/repository/search_repository_base.py +241 -0
  131. basic_memory/repository/sqlite_search_repository.py +439 -0
  132. basic_memory/schemas/__init__.py +86 -0
  133. basic_memory/schemas/base.py +297 -0
  134. basic_memory/schemas/cloud.py +50 -0
  135. basic_memory/schemas/delete.py +37 -0
  136. basic_memory/schemas/directory.py +30 -0
  137. basic_memory/schemas/importer.py +35 -0
  138. basic_memory/schemas/memory.py +285 -0
  139. basic_memory/schemas/project_info.py +212 -0
  140. basic_memory/schemas/prompt.py +90 -0
  141. basic_memory/schemas/request.py +112 -0
  142. basic_memory/schemas/response.py +229 -0
  143. basic_memory/schemas/search.py +117 -0
  144. basic_memory/schemas/sync_report.py +72 -0
  145. basic_memory/schemas/v2/__init__.py +27 -0
  146. basic_memory/schemas/v2/entity.py +129 -0
  147. basic_memory/schemas/v2/resource.py +46 -0
  148. basic_memory/services/__init__.py +8 -0
  149. basic_memory/services/context_service.py +601 -0
  150. basic_memory/services/directory_service.py +308 -0
  151. basic_memory/services/entity_service.py +864 -0
  152. basic_memory/services/exceptions.py +37 -0
  153. basic_memory/services/file_service.py +541 -0
  154. basic_memory/services/initialization.py +216 -0
  155. basic_memory/services/link_resolver.py +121 -0
  156. basic_memory/services/project_service.py +880 -0
  157. basic_memory/services/search_service.py +404 -0
  158. basic_memory/services/service.py +15 -0
  159. basic_memory/sync/__init__.py +6 -0
  160. basic_memory/sync/background_sync.py +26 -0
  161. basic_memory/sync/sync_service.py +1259 -0
  162. basic_memory/sync/watch_service.py +510 -0
  163. basic_memory/telemetry.py +249 -0
  164. basic_memory/templates/prompts/continue_conversation.hbs +110 -0
  165. basic_memory/templates/prompts/search.hbs +101 -0
  166. basic_memory/utils.py +468 -0
  167. basic_memory-0.17.1.dist-info/METADATA +617 -0
  168. basic_memory-0.17.1.dist-info/RECORD +171 -0
  169. basic_memory-0.17.1.dist-info/WHEEL +4 -0
  170. basic_memory-0.17.1.dist-info/entry_points.txt +3 -0
  171. basic_memory-0.17.1.dist-info/licenses/LICENSE +661 -0
@@ -0,0 +1,168 @@
1
+ """List directory tool for Basic Memory MCP server."""
2
+
3
+ from typing import Optional
4
+
5
+ from loguru import logger
6
+ from fastmcp import Context
7
+
8
+ from basic_memory.mcp.async_client import get_client
9
+ from basic_memory.mcp.project_context import get_active_project
10
+ from basic_memory.mcp.server import mcp
11
+ from basic_memory.mcp.tools.utils import call_get
12
+ from basic_memory.telemetry import track_mcp_tool
13
+
14
+
15
+ @mcp.tool(
16
+ description="List directory contents with filtering and depth control.",
17
+ )
18
+ async def list_directory(
19
+ dir_name: str = "/",
20
+ depth: int = 1,
21
+ file_name_glob: Optional[str] = None,
22
+ project: Optional[str] = None,
23
+ context: Context | None = None,
24
+ ) -> str:
25
+ """List directory contents from the knowledge base with optional filtering.
26
+
27
+ This tool provides 'ls' functionality for browsing the knowledge base directory structure.
28
+ It can list immediate children or recursively explore subdirectories with depth control,
29
+ and supports glob pattern filtering for finding specific files.
30
+
31
+ Args:
32
+ dir_name: Directory path to list (default: root "/")
33
+ Examples: "/", "/projects", "/research/ml"
34
+ depth: Recursion depth (1-10, default: 1 for immediate children only)
35
+ Higher values show subdirectory contents recursively
36
+ file_name_glob: Optional glob pattern for filtering file names
37
+ Examples: "*.md", "*meeting*", "project_*"
38
+ project: Project name to list directory from. Optional - server will resolve using hierarchy.
39
+ If unknown, use list_memory_projects() to discover available projects.
40
+ context: Optional FastMCP context for performance caching.
41
+
42
+ Returns:
43
+ Formatted listing of directory contents with file metadata
44
+
45
+ Examples:
46
+ # List root directory contents
47
+ list_directory()
48
+
49
+ # List specific folder
50
+ list_directory(dir_name="/projects")
51
+
52
+ # Find all markdown files
53
+ list_directory(file_name_glob="*.md")
54
+
55
+ # Deep exploration of research folder
56
+ list_directory(dir_name="/research", depth=3)
57
+
58
+ # Find meeting notes in projects folder
59
+ list_directory(dir_name="/projects", file_name_glob="*meeting*")
60
+
61
+ # Explicit project specification
62
+ list_directory(project="work-docs", dir_name="/projects")
63
+
64
+ Raises:
65
+ ToolError: If project doesn't exist or directory path is invalid
66
+ """
67
+ track_mcp_tool("list_directory")
68
+ async with get_client() as client:
69
+ active_project = await get_active_project(client, project, context)
70
+
71
+ # Prepare query parameters
72
+ params = {
73
+ "dir_name": dir_name,
74
+ "depth": str(depth),
75
+ }
76
+ if file_name_glob:
77
+ params["file_name_glob"] = file_name_glob
78
+
79
+ logger.debug(
80
+ f"Listing directory '{dir_name}' in project {project} with depth={depth}, glob='{file_name_glob}'"
81
+ )
82
+
83
+ # Call the API endpoint
84
+ response = await call_get(
85
+ client,
86
+ f"/v2/projects/{active_project.id}/directory/list",
87
+ params=params,
88
+ )
89
+
90
+ nodes = response.json()
91
+
92
+ if not nodes:
93
+ filter_desc = ""
94
+ if file_name_glob:
95
+ filter_desc = f" matching '{file_name_glob}'"
96
+ return f"No files found in directory '{dir_name}'{filter_desc}"
97
+
98
+ # Format the results
99
+ output_lines = []
100
+ if file_name_glob:
101
+ output_lines.append(
102
+ f"Files in '{dir_name}' matching '{file_name_glob}' (depth {depth}):"
103
+ )
104
+ else:
105
+ output_lines.append(f"Contents of '{dir_name}' (depth {depth}):")
106
+ output_lines.append("")
107
+
108
+ # Group by type and sort
109
+ directories = [n for n in nodes if n["type"] == "directory"]
110
+ files = [n for n in nodes if n["type"] == "file"]
111
+
112
+ # Sort by name
113
+ directories.sort(key=lambda x: x["name"])
114
+ files.sort(key=lambda x: x["name"])
115
+
116
+ # Display directories first
117
+ for node in directories:
118
+ path_display = node["directory_path"]
119
+ output_lines.append(f"📁 {node['name']:<30} {path_display}")
120
+
121
+ # Add separator if we have both directories and files
122
+ if directories and files:
123
+ output_lines.append("")
124
+
125
+ # Display files with metadata
126
+ for node in files:
127
+ path_display = node["directory_path"]
128
+ title = node.get("title", "")
129
+ updated = node.get("updated_at", "")
130
+
131
+ # Remove leading slash if present, requesting the file via read_note does not use the beginning slash'
132
+ if path_display.startswith("/"):
133
+ path_display = path_display[1:]
134
+
135
+ # Format date if available
136
+ date_str = ""
137
+ if updated:
138
+ try:
139
+ from datetime import datetime
140
+
141
+ dt = datetime.fromisoformat(updated.replace("Z", "+00:00"))
142
+ date_str = dt.strftime("%Y-%m-%d")
143
+ except Exception: # pragma: no cover
144
+ date_str = updated[:10] if len(updated) >= 10 else ""
145
+
146
+ # Create formatted line
147
+ file_line = f"📄 {node['name']:<30} {path_display}"
148
+ if title and title != node["name"]:
149
+ file_line += f" | {title}"
150
+ if date_str:
151
+ file_line += f" | {date_str}"
152
+
153
+ output_lines.append(file_line)
154
+
155
+ # Add summary
156
+ output_lines.append("")
157
+ total_count = len(directories) + len(files)
158
+ summary_parts = []
159
+ if directories:
160
+ summary_parts.append(
161
+ f"{len(directories)} director{'y' if len(directories) == 1 else 'ies'}"
162
+ )
163
+ if files:
164
+ summary_parts.append(f"{len(files)} file{'s' if len(files) != 1 else ''}")
165
+
166
+ output_lines.append(f"Total: {total_count} items ({', '.join(summary_parts)})")
167
+
168
+ return "\n".join(output_lines)