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,86 @@
1
+ """Import command for basic-memory CLI to import project data from Claude.ai."""
2
+
3
+ import asyncio
4
+ import json
5
+ from pathlib import Path
6
+ from typing import Annotated
7
+
8
+ import typer
9
+ from basic_memory.cli.app import claude_app
10
+ from basic_memory.config import ConfigManager, get_project_config
11
+ from basic_memory.importers.claude_projects_importer import ClaudeProjectsImporter
12
+ from basic_memory.markdown import EntityParser, MarkdownProcessor
13
+ from loguru import logger
14
+ from rich.console import Console
15
+ from rich.panel import Panel
16
+
17
+ console = Console()
18
+
19
+
20
+ async def get_markdown_processor() -> MarkdownProcessor:
21
+ """Get MarkdownProcessor instance."""
22
+ config = get_project_config()
23
+ app_config = ConfigManager().config
24
+ entity_parser = EntityParser(config.home)
25
+ return MarkdownProcessor(entity_parser, app_config=app_config)
26
+
27
+
28
+ @claude_app.command(name="projects", help="Import projects from Claude.ai.")
29
+ def import_projects(
30
+ projects_json: Annotated[Path, typer.Argument(..., help="Path to projects.json file")] = Path(
31
+ "projects.json"
32
+ ),
33
+ base_folder: Annotated[
34
+ str, typer.Option(help="The base folder to place project files in.")
35
+ ] = "projects",
36
+ ):
37
+ """Import project data from Claude.ai.
38
+
39
+ This command will:
40
+ 1. Create a directory for each project
41
+ 2. Store docs in a docs/ subdirectory
42
+ 3. Place prompt template in project root
43
+
44
+ After importing, run 'basic-memory sync' to index the new files.
45
+ """
46
+ config = get_project_config()
47
+ try:
48
+ if not projects_json.exists():
49
+ typer.echo(f"Error: File not found: {projects_json}", err=True)
50
+ raise typer.Exit(1)
51
+
52
+ # Get markdown processor
53
+ markdown_processor = asyncio.run(get_markdown_processor())
54
+
55
+ # Create the importer
56
+ importer = ClaudeProjectsImporter(config.home, markdown_processor)
57
+
58
+ # Process the file
59
+ base_path = config.home / base_folder if base_folder else config.home
60
+ console.print(f"\nImporting projects from {projects_json}...writing to {base_path}")
61
+
62
+ # Run the import
63
+ with projects_json.open("r", encoding="utf-8") as file:
64
+ json_data = json.load(file)
65
+ result = asyncio.run(importer.import_data(json_data, base_folder))
66
+
67
+ if not result.success: # pragma: no cover
68
+ typer.echo(f"Error during import: {result.error_message}", err=True)
69
+ raise typer.Exit(1)
70
+
71
+ # Show results
72
+ console.print(
73
+ Panel(
74
+ f"[green]Import complete![/green]\n\n"
75
+ f"Imported {result.documents} project documents\n"
76
+ f"Imported {result.prompts} prompt templates",
77
+ expand=False,
78
+ )
79
+ )
80
+
81
+ console.print("\nRun 'basic-memory sync' to index the new files.")
82
+
83
+ except Exception as e:
84
+ logger.error("Import failed")
85
+ typer.echo(f"Error during import: {e}", err=True)
86
+ raise typer.Exit(1)
@@ -0,0 +1,87 @@
1
+ """Import command for basic-memory CLI to import from JSON memory format."""
2
+
3
+ import asyncio
4
+ import json
5
+ from pathlib import Path
6
+ from typing import Annotated
7
+
8
+ import typer
9
+ from basic_memory.cli.app import import_app
10
+ from basic_memory.config import ConfigManager, get_project_config
11
+ from basic_memory.importers.memory_json_importer import MemoryJsonImporter
12
+ from basic_memory.markdown import EntityParser, MarkdownProcessor
13
+ from loguru import logger
14
+ from rich.console import Console
15
+ from rich.panel import Panel
16
+
17
+ console = Console()
18
+
19
+
20
+ async def get_markdown_processor() -> MarkdownProcessor:
21
+ """Get MarkdownProcessor instance."""
22
+ config = get_project_config()
23
+ app_config = ConfigManager().config
24
+ entity_parser = EntityParser(config.home)
25
+ return MarkdownProcessor(entity_parser, app_config=app_config)
26
+
27
+
28
+ @import_app.command()
29
+ def memory_json(
30
+ json_path: Annotated[Path, typer.Argument(..., help="Path to memory.json file")] = Path(
31
+ "memory.json"
32
+ ),
33
+ destination_folder: Annotated[
34
+ str, typer.Option(help="Optional destination folder within the project")
35
+ ] = "",
36
+ ):
37
+ """Import entities and relations from a memory.json file.
38
+
39
+ This command will:
40
+ 1. Read entities and relations from the JSON file
41
+ 2. Create markdown files for each entity
42
+ 3. Include outgoing relations in each entity's markdown
43
+ """
44
+
45
+ if not json_path.exists():
46
+ typer.echo(f"Error: File not found: {json_path}", err=True)
47
+ raise typer.Exit(1)
48
+
49
+ config = get_project_config()
50
+ try:
51
+ # Get markdown processor
52
+ markdown_processor = asyncio.run(get_markdown_processor())
53
+
54
+ # Create the importer
55
+ importer = MemoryJsonImporter(config.home, markdown_processor)
56
+
57
+ # Process the file
58
+ base_path = config.home if not destination_folder else config.home / destination_folder
59
+ console.print(f"\nImporting from {json_path}...writing to {base_path}")
60
+
61
+ # Run the import for json log format
62
+ file_data = []
63
+ with json_path.open("r", encoding="utf-8") as file:
64
+ for line in file:
65
+ json_data = json.loads(line)
66
+ file_data.append(json_data)
67
+ result = asyncio.run(importer.import_data(file_data, destination_folder))
68
+
69
+ if not result.success: # pragma: no cover
70
+ typer.echo(f"Error during import: {result.error_message}", err=True)
71
+ raise typer.Exit(1)
72
+
73
+ # Show results
74
+ console.print(
75
+ Panel(
76
+ f"[green]Import complete![/green]\n\n"
77
+ f"Created {result.entities} entities\n"
78
+ f"Added {result.relations} relations\n"
79
+ f"Skipped {result.skipped_entities} entities\n",
80
+ expand=False,
81
+ )
82
+ )
83
+
84
+ except Exception as e:
85
+ logger.error("Import failed")
86
+ typer.echo(f"Error during import: {e}", err=True)
87
+ raise typer.Exit(1)
@@ -0,0 +1,76 @@
1
+ """MCP server command with streamable HTTP transport."""
2
+
3
+ import os
4
+ import typer
5
+ from typing import Optional
6
+
7
+ from basic_memory.cli.app import app
8
+ from basic_memory.config import ConfigManager, init_mcp_logging
9
+
10
+ # Import mcp instance (has lifespan that handles initialization and file sync)
11
+ from basic_memory.mcp.server import mcp as mcp_server # pragma: no cover
12
+
13
+ # Import mcp tools to register them
14
+ import basic_memory.mcp.tools # noqa: F401 # pragma: no cover
15
+
16
+ # Import prompts to register them
17
+ import basic_memory.mcp.prompts # noqa: F401 # pragma: no cover
18
+ from loguru import logger
19
+
20
+ config = ConfigManager().config
21
+
22
+ if not config.cloud_mode_enabled:
23
+
24
+ @app.command()
25
+ def mcp(
26
+ transport: str = typer.Option(
27
+ "stdio", help="Transport type: stdio, streamable-http, or sse"
28
+ ),
29
+ host: str = typer.Option(
30
+ "0.0.0.0", help="Host for HTTP transports (use 0.0.0.0 to allow external connections)"
31
+ ),
32
+ port: int = typer.Option(8000, help="Port for HTTP transports"),
33
+ path: str = typer.Option("/mcp", help="Path prefix for streamable-http transport"),
34
+ project: Optional[str] = typer.Option(None, help="Restrict MCP server to single project"),
35
+ ): # pragma: no cover
36
+ """Run the MCP server with configurable transport options.
37
+
38
+ This command starts an MCP server using one of three transport options:
39
+
40
+ - stdio: Standard I/O (good for local usage)
41
+ - streamable-http: Recommended for web deployments (default)
42
+ - sse: Server-Sent Events (for compatibility with existing clients)
43
+
44
+ Initialization, file sync, and cleanup are handled by the MCP server's lifespan.
45
+ """
46
+ # Initialize logging for MCP (file only, stdout breaks protocol)
47
+ init_mcp_logging()
48
+
49
+ # Validate and set project constraint if specified
50
+ if project:
51
+ config_manager = ConfigManager()
52
+ project_name, _ = config_manager.get_project(project)
53
+ if not project_name:
54
+ typer.echo(f"No project found named: {project}", err=True)
55
+ raise typer.Exit(1)
56
+
57
+ # Set env var with validated project name
58
+ os.environ["BASIC_MEMORY_MCP_PROJECT"] = project_name
59
+ logger.info(f"MCP server constrained to project: {project_name}")
60
+
61
+ # Run the MCP server (blocks)
62
+ # Lifespan handles: initialization, migrations, file sync, cleanup
63
+ logger.info(f"Starting MCP server with {transport.upper()} transport")
64
+
65
+ if transport == "stdio":
66
+ mcp_server.run(
67
+ transport=transport,
68
+ )
69
+ elif transport == "streamable-http" or transport == "sse":
70
+ mcp_server.run(
71
+ transport=transport,
72
+ host=host,
73
+ port=port,
74
+ path=path,
75
+ log_level="INFO",
76
+ )