basic-memory 0.14.2__py3-none-any.whl → 0.14.3__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.

Files changed (51) hide show
  1. basic_memory/__init__.py +1 -1
  2. basic_memory/alembic/env.py +3 -1
  3. basic_memory/api/app.py +4 -1
  4. basic_memory/api/routers/management_router.py +3 -1
  5. basic_memory/api/routers/project_router.py +21 -13
  6. basic_memory/cli/app.py +3 -3
  7. basic_memory/cli/commands/__init__.py +1 -2
  8. basic_memory/cli/commands/db.py +5 -5
  9. basic_memory/cli/commands/import_chatgpt.py +3 -2
  10. basic_memory/cli/commands/import_claude_conversations.py +3 -1
  11. basic_memory/cli/commands/import_claude_projects.py +3 -1
  12. basic_memory/cli/commands/import_memory_json.py +5 -2
  13. basic_memory/cli/commands/mcp.py +3 -15
  14. basic_memory/cli/commands/project.py +41 -0
  15. basic_memory/cli/commands/status.py +4 -1
  16. basic_memory/cli/commands/sync.py +10 -2
  17. basic_memory/cli/main.py +0 -1
  18. basic_memory/config.py +46 -31
  19. basic_memory/db.py +2 -6
  20. basic_memory/deps.py +3 -2
  21. basic_memory/importers/chatgpt_importer.py +19 -9
  22. basic_memory/importers/memory_json_importer.py +22 -7
  23. basic_memory/mcp/async_client.py +22 -2
  24. basic_memory/mcp/project_session.py +6 -4
  25. basic_memory/mcp/prompts/__init__.py +0 -2
  26. basic_memory/mcp/server.py +8 -71
  27. basic_memory/mcp/tools/move_note.py +24 -12
  28. basic_memory/mcp/tools/read_content.py +16 -0
  29. basic_memory/mcp/tools/read_note.py +12 -0
  30. basic_memory/mcp/tools/sync_status.py +3 -2
  31. basic_memory/mcp/tools/write_note.py +9 -1
  32. basic_memory/models/project.py +3 -3
  33. basic_memory/repository/project_repository.py +18 -0
  34. basic_memory/schemas/importer.py +1 -0
  35. basic_memory/services/entity_service.py +49 -3
  36. basic_memory/services/initialization.py +0 -75
  37. basic_memory/services/project_service.py +85 -28
  38. basic_memory/sync/background_sync.py +4 -3
  39. basic_memory/sync/sync_service.py +50 -1
  40. basic_memory/utils.py +105 -4
  41. {basic_memory-0.14.2.dist-info → basic_memory-0.14.3.dist-info}/METADATA +2 -2
  42. {basic_memory-0.14.2.dist-info → basic_memory-0.14.3.dist-info}/RECORD +45 -51
  43. basic_memory/cli/commands/auth.py +0 -136
  44. basic_memory/mcp/auth_provider.py +0 -270
  45. basic_memory/mcp/external_auth_provider.py +0 -321
  46. basic_memory/mcp/prompts/sync_status.py +0 -112
  47. basic_memory/mcp/supabase_auth_provider.py +0 -463
  48. basic_memory/services/migration_service.py +0 -168
  49. {basic_memory-0.14.2.dist-info → basic_memory-0.14.3.dist-info}/WHEEL +0 -0
  50. {basic_memory-0.14.2.dist-info → basic_memory-0.14.3.dist-info}/entry_points.txt +0 -0
  51. {basic_memory-0.14.2.dist-info → basic_memory-0.14.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,168 +0,0 @@
1
- """Migration service for handling background migrations and status tracking."""
2
-
3
- import asyncio
4
- from dataclasses import dataclass
5
- from enum import Enum
6
- from pathlib import Path
7
- from typing import Optional
8
-
9
- from loguru import logger
10
-
11
- from basic_memory.config import BasicMemoryConfig
12
-
13
-
14
- class MigrationStatus(Enum):
15
- """Status of migration operations."""
16
-
17
- NOT_NEEDED = "not_needed"
18
- PENDING = "pending"
19
- IN_PROGRESS = "in_progress"
20
- COMPLETED = "completed"
21
- FAILED = "failed"
22
-
23
-
24
- @dataclass
25
- class MigrationState:
26
- """Current state of migration operations."""
27
-
28
- status: MigrationStatus
29
- message: str
30
- progress: Optional[str] = None
31
- error: Optional[str] = None
32
- projects_migrated: int = 0
33
- projects_total: int = 0
34
-
35
-
36
- class MigrationManager:
37
- """Manages background migration operations and status tracking."""
38
-
39
- def __init__(self):
40
- self._state = MigrationState(
41
- status=MigrationStatus.NOT_NEEDED, message="No migration required"
42
- )
43
- self._migration_task: Optional[asyncio.Task] = None
44
-
45
- @property
46
- def state(self) -> MigrationState:
47
- """Get current migration state."""
48
- return self._state
49
-
50
- @property
51
- def is_ready(self) -> bool:
52
- """Check if the system is ready for normal operations."""
53
- return self._state.status in (MigrationStatus.NOT_NEEDED, MigrationStatus.COMPLETED)
54
-
55
- @property
56
- def status_message(self) -> str:
57
- """Get a user-friendly status message."""
58
- if self._state.status == MigrationStatus.IN_PROGRESS:
59
- progress = (
60
- f" ({self._state.projects_migrated}/{self._state.projects_total})"
61
- if self._state.projects_total > 0
62
- else ""
63
- )
64
- return f"🔄 File sync in progress{progress}: {self._state.message}. Use sync_status() tool for details."
65
- elif self._state.status == MigrationStatus.FAILED:
66
- return f"❌ File sync failed: {self._state.error or 'Unknown error'}. Use sync_status() tool for details."
67
- elif self._state.status == MigrationStatus.COMPLETED:
68
- return "✅ File sync completed successfully"
69
- else:
70
- return "✅ System ready"
71
-
72
- async def check_migration_needed(self, app_config: BasicMemoryConfig) -> bool:
73
- """Check if migration is needed without performing it."""
74
- from basic_memory import db
75
- from basic_memory.repository import ProjectRepository
76
-
77
- try:
78
- # Get database session
79
- _, session_maker = await db.get_or_create_db(
80
- db_path=app_config.database_path, db_type=db.DatabaseType.FILESYSTEM
81
- )
82
- project_repository = ProjectRepository(session_maker)
83
-
84
- # Check for legacy projects
85
- legacy_projects = []
86
- for project_name, project_path in app_config.projects.items():
87
- legacy_dir = Path(project_path) / ".basic-memory"
88
- if legacy_dir.exists():
89
- project = await project_repository.get_by_name(project_name)
90
- if project:
91
- legacy_projects.append(project)
92
-
93
- if legacy_projects:
94
- self._state = MigrationState(
95
- status=MigrationStatus.PENDING,
96
- message="Legacy projects detected",
97
- projects_total=len(legacy_projects),
98
- )
99
- return True
100
- else:
101
- self._state = MigrationState(
102
- status=MigrationStatus.NOT_NEEDED, message="No migration required"
103
- )
104
- return False
105
-
106
- except Exception as e:
107
- logger.error(f"Error checking migration status: {e}")
108
- self._state = MigrationState(
109
- status=MigrationStatus.FAILED, message="Migration check failed", error=str(e)
110
- )
111
- return False
112
-
113
- async def start_background_migration(self, app_config: BasicMemoryConfig) -> None:
114
- """Start migration in background if needed."""
115
- if not await self.check_migration_needed(app_config):
116
- return
117
-
118
- if self._migration_task and not self._migration_task.done():
119
- logger.info("Migration already in progress")
120
- return
121
-
122
- logger.info("Starting background migration")
123
- self._migration_task = asyncio.create_task(self._run_migration(app_config))
124
-
125
- async def _run_migration(self, app_config: BasicMemoryConfig) -> None:
126
- """Run the actual migration process."""
127
- try:
128
- self._state.status = MigrationStatus.IN_PROGRESS
129
- self._state.message = "Migrating legacy projects"
130
-
131
- # Import here to avoid circular imports
132
- from basic_memory.services.initialization import migrate_legacy_projects
133
-
134
- # Run the migration
135
- await migrate_legacy_projects(app_config)
136
-
137
- self._state = MigrationState(
138
- status=MigrationStatus.COMPLETED, message="Migration completed successfully"
139
- )
140
- logger.info("Background migration completed successfully")
141
-
142
- except Exception as e:
143
- logger.error(f"Background migration failed: {e}")
144
- self._state = MigrationState(
145
- status=MigrationStatus.FAILED, message="Migration failed", error=str(e)
146
- )
147
-
148
- async def wait_for_completion(self, timeout: Optional[float] = None) -> bool:
149
- """Wait for migration to complete."""
150
- if self.is_ready:
151
- return True
152
-
153
- if not self._migration_task:
154
- return False
155
-
156
- try:
157
- await asyncio.wait_for(self._migration_task, timeout=timeout)
158
- return self.is_ready
159
- except asyncio.TimeoutError:
160
- return False
161
-
162
- def mark_completed(self, message: str = "Migration completed") -> None:
163
- """Mark migration as completed externally."""
164
- self._state = MigrationState(status=MigrationStatus.COMPLETED, message=message)
165
-
166
-
167
- # Global migration manager instance
168
- migration_manager = MigrationManager()