memorygraphMCP 0.11.7__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 (65) hide show
  1. memorygraph/__init__.py +50 -0
  2. memorygraph/__main__.py +12 -0
  3. memorygraph/advanced_tools.py +509 -0
  4. memorygraph/analytics/__init__.py +46 -0
  5. memorygraph/analytics/advanced_queries.py +727 -0
  6. memorygraph/backends/__init__.py +21 -0
  7. memorygraph/backends/base.py +179 -0
  8. memorygraph/backends/cloud.py +75 -0
  9. memorygraph/backends/cloud_backend.py +858 -0
  10. memorygraph/backends/factory.py +577 -0
  11. memorygraph/backends/falkordb_backend.py +749 -0
  12. memorygraph/backends/falkordblite_backend.py +746 -0
  13. memorygraph/backends/ladybugdb_backend.py +242 -0
  14. memorygraph/backends/memgraph_backend.py +327 -0
  15. memorygraph/backends/neo4j_backend.py +298 -0
  16. memorygraph/backends/sqlite_fallback.py +463 -0
  17. memorygraph/backends/turso.py +448 -0
  18. memorygraph/cli.py +743 -0
  19. memorygraph/cloud_database.py +297 -0
  20. memorygraph/config.py +295 -0
  21. memorygraph/database.py +933 -0
  22. memorygraph/graph_analytics.py +631 -0
  23. memorygraph/integration/__init__.py +69 -0
  24. memorygraph/integration/context_capture.py +426 -0
  25. memorygraph/integration/project_analysis.py +583 -0
  26. memorygraph/integration/workflow_tracking.py +492 -0
  27. memorygraph/intelligence/__init__.py +59 -0
  28. memorygraph/intelligence/context_retrieval.py +447 -0
  29. memorygraph/intelligence/entity_extraction.py +386 -0
  30. memorygraph/intelligence/pattern_recognition.py +420 -0
  31. memorygraph/intelligence/temporal.py +374 -0
  32. memorygraph/migration/__init__.py +27 -0
  33. memorygraph/migration/manager.py +579 -0
  34. memorygraph/migration/models.py +142 -0
  35. memorygraph/migration/scripts/__init__.py +17 -0
  36. memorygraph/migration/scripts/bitemporal_migration.py +595 -0
  37. memorygraph/migration/scripts/multitenancy_migration.py +452 -0
  38. memorygraph/migration_tools_module.py +146 -0
  39. memorygraph/models.py +684 -0
  40. memorygraph/proactive/__init__.py +46 -0
  41. memorygraph/proactive/outcome_learning.py +444 -0
  42. memorygraph/proactive/predictive.py +410 -0
  43. memorygraph/proactive/session_briefing.py +399 -0
  44. memorygraph/relationships.py +668 -0
  45. memorygraph/server.py +883 -0
  46. memorygraph/sqlite_database.py +1876 -0
  47. memorygraph/tools/__init__.py +59 -0
  48. memorygraph/tools/activity_tools.py +262 -0
  49. memorygraph/tools/memory_tools.py +315 -0
  50. memorygraph/tools/migration_tools.py +181 -0
  51. memorygraph/tools/relationship_tools.py +147 -0
  52. memorygraph/tools/search_tools.py +406 -0
  53. memorygraph/tools/temporal_tools.py +339 -0
  54. memorygraph/utils/__init__.py +10 -0
  55. memorygraph/utils/context_extractor.py +429 -0
  56. memorygraph/utils/error_handling.py +151 -0
  57. memorygraph/utils/export_import.py +425 -0
  58. memorygraph/utils/graph_algorithms.py +200 -0
  59. memorygraph/utils/pagination.py +149 -0
  60. memorygraph/utils/project_detection.py +133 -0
  61. memorygraphmcp-0.11.7.dist-info/METADATA +970 -0
  62. memorygraphmcp-0.11.7.dist-info/RECORD +65 -0
  63. memorygraphmcp-0.11.7.dist-info/WHEEL +4 -0
  64. memorygraphmcp-0.11.7.dist-info/entry_points.txt +2 -0
  65. memorygraphmcp-0.11.7.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,149 @@
1
+ """
2
+ Pagination utilities for working with memories across different backends.
3
+
4
+ Provides reusable pagination helpers that work with both MemoryDatabase
5
+ and SQLiteMemoryDatabase interfaces.
6
+ """
7
+
8
+ import logging
9
+ from typing import AsyncIterator, List, Callable, Optional
10
+
11
+ from ..models import Memory, SearchQuery
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ async def paginate_memories(
17
+ db, # MemoryDatabase or SQLiteMemoryDatabase
18
+ batch_size: int = 1000,
19
+ progress_callback: Optional[Callable[[int], None]] = None
20
+ ) -> AsyncIterator[List[Memory]]:
21
+ """
22
+ Async generator that yields batches of memories.
23
+
24
+ Works with both MemoryDatabase and SQLiteMemoryDatabase by using
25
+ the search_memories interface with pagination support.
26
+
27
+ Args:
28
+ db: Database instance (any backend)
29
+ batch_size: Number of memories to fetch per batch
30
+ progress_callback: Optional callback(total_yielded) for progress reporting
31
+
32
+ Yields:
33
+ Batches of Memory objects
34
+
35
+ Example:
36
+ async for batch in paginate_memories(db, batch_size=500):
37
+ for memory in batch:
38
+ print(memory.title)
39
+ """
40
+ offset = 0
41
+ total_yielded = 0
42
+
43
+ while True:
44
+ query = SearchQuery(
45
+ query="", # Empty query matches all memories
46
+ limit=batch_size,
47
+ offset=offset,
48
+ match_mode="any"
49
+ )
50
+
51
+ # Use paginated search if available, fallback to regular search
52
+ if hasattr(db, 'search_memories_paginated'):
53
+ result = await db.search_memories_paginated(query)
54
+ memories = result.results
55
+ has_more = result.has_more
56
+ else:
57
+ # Fallback for backends without pagination
58
+ memories = await db.search_memories(query)
59
+ has_more = len(memories) >= batch_size
60
+
61
+ if memories:
62
+ yield memories
63
+ total_yielded += len(memories)
64
+
65
+ if progress_callback:
66
+ progress_callback(total_yielded)
67
+
68
+ if not has_more or not memories:
69
+ break
70
+
71
+ offset += batch_size
72
+
73
+
74
+ async def count_memories(db) -> int:
75
+ """
76
+ Count total memories in database using efficient method.
77
+
78
+ Args:
79
+ db: Database instance (any backend)
80
+
81
+ Returns:
82
+ Total number of memories
83
+ """
84
+ query = SearchQuery(query="", limit=1, offset=0, match_mode="any")
85
+
86
+ # Use paginated search for efficient counting if available
87
+ if hasattr(db, 'search_memories_paginated'):
88
+ result = await db.search_memories_paginated(query)
89
+ return result.total_count
90
+ else:
91
+ # Fallback: count manually by iterating
92
+ count = 0
93
+ async for batch in paginate_memories(db, batch_size=1000):
94
+ count += len(batch)
95
+ return count
96
+
97
+
98
+ async def count_relationships(db) -> int:
99
+ """
100
+ Count total relationships in database.
101
+
102
+ Args:
103
+ db: Database instance (any backend)
104
+
105
+ Returns:
106
+ Total number of relationships (deduplicated)
107
+ """
108
+ count = 0
109
+ seen_relationships = set()
110
+
111
+ async for batch in paginate_memories(db, batch_size=1000):
112
+ for memory in batch:
113
+ try:
114
+ related = await db.get_related_memories(memory.id, max_depth=1)
115
+ for _, relationship in related:
116
+ # Use tuple as key for deduplication
117
+ key = (
118
+ relationship.from_memory_id,
119
+ relationship.to_memory_id,
120
+ relationship.type.value
121
+ )
122
+ if key not in seen_relationships:
123
+ seen_relationships.add(key)
124
+ count += 1
125
+ except Exception as e:
126
+ logger.warning(f"Failed to count relationships for memory {memory.id}: {e}")
127
+ continue
128
+
129
+ return count
130
+
131
+
132
+ async def get_all_memories(db) -> List[Memory]:
133
+ """
134
+ Get all memories from database.
135
+
136
+ Args:
137
+ db: Database instance (any backend)
138
+
139
+ Returns:
140
+ List of all memories
141
+
142
+ Warning:
143
+ This loads all memories into memory. For large databases,
144
+ prefer using paginate_memories() to process in batches.
145
+ """
146
+ all_memories = []
147
+ async for batch in paginate_memories(db, batch_size=1000):
148
+ all_memories.extend(batch)
149
+ return all_memories
@@ -0,0 +1,133 @@
1
+ """
2
+ Project context detection utilities.
3
+
4
+ Auto-detects project name and context from environment.
5
+ """
6
+
7
+ import os
8
+ import subprocess
9
+ from typing import Optional, Dict, Any
10
+ import logging
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ def detect_project_context(cwd: Optional[str] = None) -> Optional[Dict[str, Any]]:
16
+ """
17
+ Detect project context from current working directory or git repository.
18
+
19
+ Args:
20
+ cwd: Current working directory (defaults to os.getcwd())
21
+
22
+ Returns:
23
+ Dictionary with project information:
24
+ - project_name: Name of the project
25
+ - project_path: Absolute path to project root
26
+ - is_git_repo: Whether this is a git repository
27
+ - git_remote: Git remote URL (if available)
28
+
29
+ Returns None if project cannot be detected.
30
+ """
31
+ if cwd is None:
32
+ cwd = os.getcwd()
33
+
34
+ cwd = os.path.abspath(cwd)
35
+
36
+ result = {
37
+ "project_path": cwd,
38
+ "is_git_repo": False
39
+ }
40
+
41
+ # Try to detect from git repository
42
+ git_info = _detect_from_git(cwd)
43
+ if git_info:
44
+ result.update(git_info)
45
+ result["is_git_repo"] = True
46
+ return result
47
+
48
+ # Fallback: use directory name
49
+ project_name = os.path.basename(cwd)
50
+ result["project_name"] = project_name
51
+
52
+ return result
53
+
54
+
55
+ def _detect_from_git(cwd: str) -> Optional[Dict[str, Any]]:
56
+ """
57
+ Detect project information from git repository.
58
+
59
+ Args:
60
+ cwd: Current working directory
61
+
62
+ Returns:
63
+ Dictionary with git-based project info, or None if not a git repo
64
+ """
65
+ try:
66
+ # Check if this is a git repository
67
+ git_check = subprocess.run(
68
+ ["git", "rev-parse", "--is-inside-work-tree"],
69
+ cwd=cwd,
70
+ capture_output=True,
71
+ text=True,
72
+ timeout=2
73
+ )
74
+
75
+ if git_check.returncode != 0:
76
+ return None
77
+
78
+ # Get repository root
79
+ repo_root = subprocess.run(
80
+ ["git", "rev-parse", "--show-toplevel"],
81
+ cwd=cwd,
82
+ capture_output=True,
83
+ text=True,
84
+ timeout=2
85
+ )
86
+
87
+ if repo_root.returncode != 0:
88
+ return None
89
+
90
+ project_path = repo_root.stdout.strip()
91
+ project_name = os.path.basename(project_path)
92
+
93
+ result = {
94
+ "project_name": project_name,
95
+ "project_path": project_path
96
+ }
97
+
98
+ # Try to get git remote (optional)
99
+ try:
100
+ remote = subprocess.run(
101
+ ["git", "remote", "get-url", "origin"],
102
+ cwd=cwd,
103
+ capture_output=True,
104
+ text=True,
105
+ timeout=2
106
+ )
107
+
108
+ if remote.returncode == 0:
109
+ result["git_remote"] = remote.stdout.strip()
110
+ except (subprocess.TimeoutExpired, FileNotFoundError):
111
+ pass # Git remote is optional
112
+
113
+ return result
114
+
115
+ except (subprocess.TimeoutExpired, FileNotFoundError, OSError) as e:
116
+ logger.debug(f"Git detection failed: {e}")
117
+ return None
118
+
119
+
120
+ def get_project_from_memories(db, limit: int = 50) -> Optional[str]:
121
+ """
122
+ Infer current project from frequently mentioned project paths in recent memories.
123
+
124
+ Args:
125
+ db: Database instance
126
+ limit: Number of recent memories to analyze
127
+
128
+ Returns:
129
+ Most common project path, or None if cannot determine
130
+ """
131
+ # This would require database access, which we'll implement later
132
+ # For now, return None
133
+ return None