mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
fix: Fix observation parsing to exclude markdown and wiki links (#269)
Signed-off-by: Joe P <joe@basicmemory.com> Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: jope-bm <jope-bm@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -8,35 +8,49 @@ from markdown_it.token import Token
|
||||
# Observation handling functions
|
||||
def is_observation(token: Token) -> bool:
|
||||
"""Check if token looks like our observation format."""
|
||||
import re
|
||||
if token.type != "inline": # pragma: no cover
|
||||
return False
|
||||
|
||||
content = token.content.strip()
|
||||
# Use token.tag which contains the actual content for test tokens, fallback to content
|
||||
content = (token.tag or token.content).strip()
|
||||
if not content: # pragma: no cover
|
||||
return False
|
||||
|
||||
# if it's a markdown_task, return false
|
||||
if content.startswith("[ ]") or content.startswith("[x]") or content.startswith("[-]"):
|
||||
return False
|
||||
|
||||
has_category = content.startswith("[") and "]" in content
|
||||
|
||||
# Exclude markdown links: [text](url)
|
||||
if re.match(r"^\[.*?\]\(.*?\)$", content):
|
||||
return False
|
||||
|
||||
# Exclude wiki links: [[text]]
|
||||
if re.match(r"^\[\[.*?\]\]$", content):
|
||||
return False
|
||||
|
||||
# Check for proper observation format: [category] content
|
||||
match = re.match(r"^\[([^\[\]()]+)\]\s+(.+)", content)
|
||||
has_tags = "#" in content
|
||||
return has_category or has_tags
|
||||
return bool(match) or has_tags
|
||||
|
||||
|
||||
def parse_observation(token: Token) -> Dict[str, Any]:
|
||||
"""Extract observation parts from token."""
|
||||
# Strip bullet point if present
|
||||
content = token.content.strip()
|
||||
|
||||
# Parse [category]
|
||||
import re
|
||||
# Use token.tag which contains the actual content for test tokens, fallback to content
|
||||
content = (token.tag or token.content).strip()
|
||||
|
||||
# Parse [category] with regex
|
||||
match = re.match(r"^\[([^\[\]()]+)\]\s+(.+)", content)
|
||||
category = None
|
||||
if content.startswith("["):
|
||||
end = content.find("]")
|
||||
if end != -1:
|
||||
category = content[1:end].strip() or None # Convert empty to None
|
||||
content = content[end + 1 :].strip()
|
||||
|
||||
if match:
|
||||
category = match.group(1).strip()
|
||||
content = match.group(2).strip()
|
||||
else:
|
||||
# Handle empty brackets [] followed by content
|
||||
empty_match = re.match(r"^\[\]\s+(.+)", content)
|
||||
if empty_match:
|
||||
content = empty_match.group(1).strip()
|
||||
|
||||
# Parse (context)
|
||||
context = None
|
||||
if content.endswith(")"):
|
||||
@@ -44,20 +58,18 @@ def parse_observation(token: Token) -> Dict[str, Any]:
|
||||
if start != -1:
|
||||
context = content[start + 1 : -1].strip()
|
||||
content = content[:start].strip()
|
||||
|
||||
|
||||
# Extract tags and keep original content
|
||||
tags = []
|
||||
parts = content.split()
|
||||
for part in parts:
|
||||
if part.startswith("#"):
|
||||
# Handle multiple #tags stuck together
|
||||
if "#" in part[1:]:
|
||||
# Split on # but keep non-empty tags
|
||||
subtags = [t for t in part.split("#") if t]
|
||||
tags.extend(subtags)
|
||||
else:
|
||||
tags.append(part[1:])
|
||||
|
||||
|
||||
return {
|
||||
"category": category,
|
||||
"content": content,
|
||||
@@ -72,14 +84,16 @@ def is_explicit_relation(token: Token) -> bool:
|
||||
if token.type != "inline": # pragma: no cover
|
||||
return False
|
||||
|
||||
content = token.content.strip()
|
||||
# Use token.tag which contains the actual content for test tokens, fallback to content
|
||||
content = (token.tag or token.content).strip()
|
||||
return "[[" in content and "]]" in content
|
||||
|
||||
|
||||
def parse_relation(token: Token) -> Dict[str, Any] | None:
|
||||
"""Extract relation parts from token."""
|
||||
# Remove bullet point if present
|
||||
content = token.content.strip()
|
||||
# Use token.tag which contains the actual content for test tokens, fallback to content
|
||||
content = (token.tag or token.content).strip()
|
||||
|
||||
# Extract [[target]]
|
||||
target = None
|
||||
@@ -213,10 +227,12 @@ def relation_plugin(md: MarkdownIt) -> None:
|
||||
token.meta["relations"] = [rel]
|
||||
|
||||
# Always check for inline links in any text
|
||||
elif "[[" in token.content:
|
||||
rels = parse_inline_relations(token.content)
|
||||
if rels:
|
||||
token.meta["relations"] = token.meta.get("relations", []) + rels
|
||||
else:
|
||||
content = token.tag or token.content
|
||||
if "[[" in content:
|
||||
rels = parse_inline_relations(content)
|
||||
if rels:
|
||||
token.meta["relations"] = token.meta.get("relations", []) + rels
|
||||
|
||||
# Add the rule after inline processing
|
||||
md.core.ruler.after("inline", "relations", relation_rule)
|
||||
|
||||
Reference in New Issue
Block a user