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,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)
|