fix: support partial UUID prefix matching in memory/edge lookups
Closes cal/claude-memory#3. All ID-based lookups now resolve partial UUID prefixes (git-style) instead of requiring exact full UUIDs. Affects _resolve_memory_path, _resolve_edge_path, edge_search, and related(). Ambiguous prefixes raise ValueError with candidates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5cfb91d65f
commit
471d8709f6
@ -662,11 +662,32 @@ class CognitiveMemoryClient:
|
||||
content = f"{fm_str}\n\n{body.strip()}\n" if body.strip() else f"{fm_str}\n"
|
||||
path.write_text(content, encoding="utf-8")
|
||||
|
||||
@staticmethod
|
||||
def _resolve_prefix(partial_id: str, keys) -> Optional[str]:
|
||||
"""Resolve a partial UUID prefix to a full ID (git-style).
|
||||
|
||||
Returns the full key if exactly one match is found, None if zero
|
||||
matches, or raises ValueError on ambiguous (multiple) matches.
|
||||
"""
|
||||
if partial_id in keys:
|
||||
return partial_id
|
||||
matches = [k for k in keys if k.startswith(partial_id)]
|
||||
if len(matches) == 1:
|
||||
return matches[0]
|
||||
if len(matches) > 1:
|
||||
raise ValueError(
|
||||
f"Ambiguous ID prefix '{partial_id}' matches {len(matches)} "
|
||||
f"entries: {', '.join(sorted(matches)[:5])}"
|
||||
)
|
||||
return None
|
||||
|
||||
def _resolve_memory_path(self, memory_id: str) -> Optional[Path]:
|
||||
"""Find the file path for a memory by ID using the index."""
|
||||
index = self._load_index()
|
||||
entry = index.get("entries", {}).get(memory_id)
|
||||
if entry:
|
||||
entries = index.get("entries", {})
|
||||
full_id = self._resolve_prefix(memory_id, entries)
|
||||
if full_id:
|
||||
entry = entries[full_id]
|
||||
path = self.memory_dir / entry["path"]
|
||||
if path.exists():
|
||||
return path
|
||||
@ -834,8 +855,10 @@ class CognitiveMemoryClient:
|
||||
def _resolve_edge_path(self, edge_id: str) -> Optional[Path]:
|
||||
"""Find the file path for an edge by ID using the index."""
|
||||
index = self._load_index()
|
||||
entry = index.get("edges", {}).get(edge_id)
|
||||
if entry:
|
||||
edges = index.get("edges", {})
|
||||
full_id = self._resolve_prefix(edge_id, edges)
|
||||
if full_id:
|
||||
entry = edges[full_id]
|
||||
path = self.memory_dir / entry["path"]
|
||||
if path.exists():
|
||||
return path
|
||||
@ -1243,6 +1266,16 @@ class CognitiveMemoryClient:
|
||||
results = []
|
||||
query_lower = query.lower().strip() if query else ""
|
||||
|
||||
# Resolve partial IDs to full UUIDs via prefix match
|
||||
if from_id:
|
||||
entries = index.get("entries", {})
|
||||
resolved = self._resolve_prefix(from_id, entries)
|
||||
from_id = resolved or from_id
|
||||
if to_id:
|
||||
entries = index.get("entries", {})
|
||||
resolved = self._resolve_prefix(to_id, entries)
|
||||
to_id = resolved or to_id
|
||||
|
||||
for eid, entry in index.get("edges", {}).items():
|
||||
if types and entry.get("type") not in types:
|
||||
continue
|
||||
@ -1532,12 +1565,18 @@ class CognitiveMemoryClient:
|
||||
visited = set()
|
||||
results = []
|
||||
|
||||
# Resolve partial ID prefix to full UUID
|
||||
entries = index.get("entries", {})
|
||||
resolved = self._resolve_prefix(memory_id, entries)
|
||||
if resolved:
|
||||
memory_id = resolved
|
||||
|
||||
def traverse(mid: str, depth: int):
|
||||
if depth > max_depth or mid in visited:
|
||||
return
|
||||
visited.add(mid)
|
||||
|
||||
entry = index.get("entries", {}).get(mid)
|
||||
entry = entries.get(mid)
|
||||
if not entry:
|
||||
return
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user