agmem 0.1.1__py3-none-any.whl → 0.1.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.
- {agmem-0.1.1.dist-info → agmem-0.1.3.dist-info}/METADATA +157 -16
- agmem-0.1.3.dist-info/RECORD +105 -0
- memvcs/__init__.py +1 -1
- memvcs/cli.py +45 -31
- memvcs/commands/__init__.py +9 -9
- memvcs/commands/add.py +83 -76
- memvcs/commands/audit.py +59 -0
- memvcs/commands/blame.py +46 -53
- memvcs/commands/branch.py +13 -33
- memvcs/commands/checkout.py +27 -32
- memvcs/commands/clean.py +18 -23
- memvcs/commands/clone.py +11 -1
- memvcs/commands/commit.py +40 -39
- memvcs/commands/daemon.py +109 -76
- memvcs/commands/decay.py +77 -0
- memvcs/commands/diff.py +56 -57
- memvcs/commands/distill.py +90 -0
- memvcs/commands/federated.py +53 -0
- memvcs/commands/fsck.py +86 -61
- memvcs/commands/garden.py +40 -35
- memvcs/commands/gc.py +51 -0
- memvcs/commands/graph.py +41 -48
- memvcs/commands/init.py +16 -24
- memvcs/commands/log.py +25 -40
- memvcs/commands/merge.py +69 -27
- memvcs/commands/pack.py +129 -0
- memvcs/commands/prove.py +66 -0
- memvcs/commands/pull.py +31 -1
- memvcs/commands/push.py +4 -2
- memvcs/commands/recall.py +145 -0
- memvcs/commands/reflog.py +13 -22
- memvcs/commands/remote.py +1 -0
- memvcs/commands/repair.py +66 -0
- memvcs/commands/reset.py +23 -33
- memvcs/commands/resolve.py +130 -0
- memvcs/commands/resurrect.py +82 -0
- memvcs/commands/search.py +3 -4
- memvcs/commands/serve.py +2 -1
- memvcs/commands/show.py +66 -36
- memvcs/commands/stash.py +34 -34
- memvcs/commands/status.py +27 -35
- memvcs/commands/tag.py +23 -47
- memvcs/commands/test.py +30 -44
- memvcs/commands/timeline.py +111 -0
- memvcs/commands/tree.py +26 -27
- memvcs/commands/verify.py +110 -0
- memvcs/commands/when.py +115 -0
- memvcs/core/access_index.py +167 -0
- memvcs/core/audit.py +124 -0
- memvcs/core/config_loader.py +3 -1
- memvcs/core/consistency.py +214 -0
- memvcs/core/crypto_verify.py +280 -0
- memvcs/core/decay.py +185 -0
- memvcs/core/diff.py +158 -143
- memvcs/core/distiller.py +277 -0
- memvcs/core/encryption.py +169 -0
- memvcs/core/federated.py +86 -0
- memvcs/core/gardener.py +176 -145
- memvcs/core/hooks.py +48 -14
- memvcs/core/ipfs_remote.py +39 -0
- memvcs/core/knowledge_graph.py +135 -138
- memvcs/core/llm/__init__.py +10 -0
- memvcs/core/llm/anthropic_provider.py +50 -0
- memvcs/core/llm/base.py +27 -0
- memvcs/core/llm/factory.py +30 -0
- memvcs/core/llm/openai_provider.py +36 -0
- memvcs/core/merge.py +260 -170
- memvcs/core/objects.py +110 -101
- memvcs/core/pack.py +92 -0
- memvcs/core/pii_scanner.py +147 -146
- memvcs/core/privacy_budget.py +63 -0
- memvcs/core/refs.py +132 -115
- memvcs/core/remote.py +38 -0
- memvcs/core/repository.py +254 -164
- memvcs/core/schema.py +155 -113
- memvcs/core/staging.py +60 -65
- memvcs/core/storage/__init__.py +20 -18
- memvcs/core/storage/base.py +74 -70
- memvcs/core/storage/gcs.py +70 -68
- memvcs/core/storage/local.py +42 -40
- memvcs/core/storage/s3.py +105 -110
- memvcs/core/temporal_index.py +121 -0
- memvcs/core/test_runner.py +101 -93
- memvcs/core/trust.py +103 -0
- memvcs/core/vector_store.py +56 -36
- memvcs/core/zk_proofs.py +26 -0
- memvcs/integrations/mcp_server.py +1 -3
- memvcs/integrations/web_ui/server.py +25 -26
- memvcs/retrieval/__init__.py +22 -0
- memvcs/retrieval/base.py +54 -0
- memvcs/retrieval/pack.py +128 -0
- memvcs/retrieval/recaller.py +105 -0
- memvcs/retrieval/strategies.py +314 -0
- memvcs/utils/__init__.py +3 -3
- memvcs/utils/helpers.py +52 -52
- agmem-0.1.1.dist-info/RECORD +0 -67
- {agmem-0.1.1.dist-info → agmem-0.1.3.dist-info}/WHEEL +0 -0
- {agmem-0.1.1.dist-info → agmem-0.1.3.dist-info}/entry_points.txt +0 -0
- {agmem-0.1.1.dist-info → agmem-0.1.3.dist-info}/licenses/LICENSE +0 -0
- {agmem-0.1.1.dist-info → agmem-0.1.3.dist-info}/top_level.txt +0 -0
memvcs/core/hooks.py
CHANGED
|
@@ -16,15 +16,16 @@ PII_SEVERITY_HIGH = "high"
|
|
|
16
16
|
@dataclass
|
|
17
17
|
class HookResult:
|
|
18
18
|
"""Result of running hooks."""
|
|
19
|
+
|
|
19
20
|
success: bool
|
|
20
21
|
errors: List[str] = field(default_factory=list)
|
|
21
22
|
warnings: List[str] = field(default_factory=list)
|
|
22
|
-
|
|
23
|
+
|
|
23
24
|
def add_error(self, message: str):
|
|
24
25
|
"""Add an error and mark as failed."""
|
|
25
26
|
self.errors.append(message)
|
|
26
27
|
self.success = False
|
|
27
|
-
|
|
28
|
+
|
|
28
29
|
def add_warning(self, message: str):
|
|
29
30
|
"""Add a warning (doesn't affect success)."""
|
|
30
31
|
self.warnings.append(message)
|
|
@@ -39,6 +40,7 @@ def _pii_staged_files_to_scan(repo, staged_files: Dict[str, Any]) -> Dict[str, A
|
|
|
39
40
|
"""Return staged files to scan for PII (excludes allowlisted paths)."""
|
|
40
41
|
try:
|
|
41
42
|
from .config_loader import load_agmem_config, pii_enabled, pii_allowlist
|
|
43
|
+
|
|
42
44
|
config = load_agmem_config(getattr(repo, "root", None))
|
|
43
45
|
except ImportError:
|
|
44
46
|
return staged_files
|
|
@@ -58,6 +60,7 @@ def _run_pii_hook(repo, staged_files: Dict[str, Any], result: HookResult) -> Non
|
|
|
58
60
|
"""Run PII scanner on staged files; high severity → error, else → warning."""
|
|
59
61
|
try:
|
|
60
62
|
from .pii_scanner import PIIScanner
|
|
63
|
+
|
|
61
64
|
to_scan = _pii_staged_files_to_scan(repo, staged_files)
|
|
62
65
|
pii_result = PIIScanner.scan_staged_files(repo, to_scan)
|
|
63
66
|
if not pii_result.has_issues:
|
|
@@ -77,11 +80,11 @@ def _run_pii_hook(repo, staged_files: Dict[str, Any], result: HookResult) -> Non
|
|
|
77
80
|
def run_pre_commit_hooks(repo, staged_files: Dict[str, Any]) -> HookResult:
|
|
78
81
|
"""
|
|
79
82
|
Run all pre-commit hooks on staged files.
|
|
80
|
-
|
|
83
|
+
|
|
81
84
|
Args:
|
|
82
85
|
repo: Repository instance
|
|
83
86
|
staged_files: Dict of staged files with their info
|
|
84
|
-
|
|
87
|
+
|
|
85
88
|
Returns:
|
|
86
89
|
HookResult with success status and any errors/warnings
|
|
87
90
|
"""
|
|
@@ -93,42 +96,42 @@ def run_pre_commit_hooks(repo, staged_files: Dict[str, Any]) -> HookResult:
|
|
|
93
96
|
result.add_error(error)
|
|
94
97
|
for warning in file_type_result.warnings:
|
|
95
98
|
result.add_warning(warning)
|
|
96
|
-
|
|
99
|
+
|
|
97
100
|
return result
|
|
98
101
|
|
|
99
102
|
|
|
100
103
|
def validate_file_types(repo, staged_files: Dict[str, Any]) -> HookResult:
|
|
101
104
|
"""
|
|
102
105
|
Validate that staged files are allowed types.
|
|
103
|
-
|
|
106
|
+
|
|
104
107
|
Args:
|
|
105
108
|
repo: Repository instance
|
|
106
109
|
staged_files: Dict of staged files
|
|
107
|
-
|
|
110
|
+
|
|
108
111
|
Returns:
|
|
109
112
|
HookResult with validation status
|
|
110
113
|
"""
|
|
111
114
|
result = HookResult(success=True)
|
|
112
|
-
|
|
115
|
+
|
|
113
116
|
# Get config for allowed extensions
|
|
114
117
|
config = repo.get_config()
|
|
115
|
-
allowed_extensions = config.get(
|
|
116
|
-
|
|
118
|
+
allowed_extensions = config.get("allowed_extensions", [".md", ".txt", ".json", ".yaml", ".yml"])
|
|
119
|
+
|
|
117
120
|
for filepath in staged_files.keys():
|
|
118
121
|
path = Path(filepath)
|
|
119
122
|
ext = path.suffix.lower()
|
|
120
|
-
|
|
123
|
+
|
|
121
124
|
# Skip files without extensions (might be valid)
|
|
122
125
|
if not ext:
|
|
123
126
|
continue
|
|
124
|
-
|
|
127
|
+
|
|
125
128
|
# Check if extension is allowed
|
|
126
129
|
if ext not in allowed_extensions:
|
|
127
130
|
result.add_warning(
|
|
128
131
|
f"File '{filepath}' has extension '{ext}' which may not be optimal for memory storage. "
|
|
129
132
|
f"Recommended: {', '.join(allowed_extensions)}"
|
|
130
133
|
)
|
|
131
|
-
|
|
134
|
+
|
|
132
135
|
return result
|
|
133
136
|
|
|
134
137
|
|
|
@@ -139,7 +142,7 @@ _registered_hooks: List[Callable] = []
|
|
|
139
142
|
def register_hook(hook_fn: Callable):
|
|
140
143
|
"""
|
|
141
144
|
Register a custom pre-commit hook.
|
|
142
|
-
|
|
145
|
+
|
|
143
146
|
Args:
|
|
144
147
|
hook_fn: Function that takes (repo, staged_files) and returns HookResult
|
|
145
148
|
"""
|
|
@@ -149,3 +152,34 @@ def register_hook(hook_fn: Callable):
|
|
|
149
152
|
def get_registered_hooks() -> List[Callable]:
|
|
150
153
|
"""Get all registered hooks."""
|
|
151
154
|
return _registered_hooks.copy()
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def compute_suggested_importance(
|
|
158
|
+
repo: Any,
|
|
159
|
+
staged_files: Dict[str, Any],
|
|
160
|
+
message: str,
|
|
161
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
162
|
+
) -> float:
|
|
163
|
+
"""
|
|
164
|
+
Compute suggested importance score from heuristics.
|
|
165
|
+
|
|
166
|
+
Scoring factors: user emphasis in message, source authority (auto_commit), etc.
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
Float 0.0-1.0; default 0.5 if no heuristics match.
|
|
170
|
+
"""
|
|
171
|
+
metadata = metadata or {}
|
|
172
|
+
message_lower = message.lower()
|
|
173
|
+
|
|
174
|
+
# auto_commit or gardener → lower authority
|
|
175
|
+
if metadata.get("auto_commit") or metadata.get("gardener"):
|
|
176
|
+
return 0.5
|
|
177
|
+
|
|
178
|
+
# User emphasis heuristics
|
|
179
|
+
if "important" in message_lower or "important:" in message_lower:
|
|
180
|
+
return 0.8
|
|
181
|
+
if "remember" in message_lower or "remember this" in message_lower:
|
|
182
|
+
return 0.7
|
|
183
|
+
|
|
184
|
+
# Default
|
|
185
|
+
return 0.5
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
IPFS remote for agmem (stub).
|
|
3
|
+
|
|
4
|
+
Push/pull via CIDs; pinning; gateway fallback when daemon unavailable.
|
|
5
|
+
Requires optional ipfs extra (ipfshttpclient or gateway requests).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Optional, Set
|
|
10
|
+
|
|
11
|
+
from .objects import ObjectStore
|
|
12
|
+
from .remote import _collect_objects_from_commit
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def push_to_ipfs(
|
|
16
|
+
objects_dir: Path,
|
|
17
|
+
branch: str,
|
|
18
|
+
commit_hash: str,
|
|
19
|
+
gateway_url: str = "https://ipfs.io",
|
|
20
|
+
) -> Optional[str]:
|
|
21
|
+
"""Push branch objects to IPFS and return root CID. Stub: returns None until IPFS client added."""
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def pull_from_ipfs(
|
|
26
|
+
objects_dir: Path,
|
|
27
|
+
cid: str,
|
|
28
|
+
gateway_url: str = "https://ipfs.io",
|
|
29
|
+
) -> bool:
|
|
30
|
+
"""Pull objects by CID from IPFS into objects_dir. Stub: returns False until IPFS client added."""
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def parse_ipfs_url(url: str) -> Optional[str]:
|
|
35
|
+
"""Parse ipfs://<cid> or ipfs://<cid>/path. Returns CID or None."""
|
|
36
|
+
if not url.startswith("ipfs://"):
|
|
37
|
+
return None
|
|
38
|
+
rest = url[7:].lstrip("/")
|
|
39
|
+
return rest.split("/")[0] or None
|