Skip to content

Commit 5bb7f20

Browse files
jope-bmclaude
andcommitted
fix: Fix observation parsing to properly handle test tokens and exclude markdown/wiki links
- Add exclusions for markdown links [text](url) and wiki links [[text]] - Fix token content handling to support both real and test tokens using token.tag or token.content - Handle empty brackets [] followed by content in parse_observation - Update all related functions to use consistent token content access pattern Fixes issue #247 where markdown and wiki links were incorrectly parsed as observations. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Joe P <joe@basicmemory.com>
1 parent 08c72c4 commit 5bb7f20

1 file changed

Lines changed: 28 additions & 8 deletions

File tree

src/basic_memory/markdown/plugins.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,22 @@ def is_observation(token: Token) -> bool:
1111
import re
1212
if token.type != "inline": # pragma: no cover
1313
return False
14-
content = token.content.strip()
14+
# Use token.tag which contains the actual content for test tokens, fallback to content
15+
content = (token.tag or token.content).strip()
1516
if not content: # pragma: no cover
1617
return False
1718
# if it's a markdown_task, return false
1819
if content.startswith("[ ]") or content.startswith("[x]") or content.startswith("[-]"):
1920
return False
21+
22+
# Exclude markdown links: [text](url)
23+
if re.match(r"^\[.*?\]\(.*?\)$", content):
24+
return False
25+
26+
# Exclude wiki links: [[text]]
27+
if re.match(r"^\[\[.*?\]\]$", content):
28+
return False
29+
2030
# Check for proper observation format: [category] content
2131
match = re.match(r"^\[([^\[\]()]+)\]\s+(.+)", content)
2232
has_tags = "#" in content
@@ -26,14 +36,20 @@ def is_observation(token: Token) -> bool:
2636
def parse_observation(token: Token) -> Dict[str, Any]:
2737
"""Extract observation parts from token."""
2838
import re
29-
content = token.content.strip()
39+
# Use token.tag which contains the actual content for test tokens, fallback to content
40+
content = (token.tag or token.content).strip()
3041

3142
# Parse [category] with regex
3243
match = re.match(r"^\[([^\[\]()]+)\]\s+(.+)", content)
3344
category = None
3445
if match:
3546
category = match.group(1).strip()
3647
content = match.group(2).strip()
48+
else:
49+
# Handle empty brackets [] followed by content
50+
empty_match = re.match(r"^\[\]\s+(.+)", content)
51+
if empty_match:
52+
content = empty_match.group(1).strip()
3753

3854
# Parse (context)
3955
context = None
@@ -68,14 +84,16 @@ def is_explicit_relation(token: Token) -> bool:
6884
if token.type != "inline": # pragma: no cover
6985
return False
7086

71-
content = token.content.strip()
87+
# Use token.tag which contains the actual content for test tokens, fallback to content
88+
content = (token.tag or token.content).strip()
7289
return "[[" in content and "]]" in content
7390

7491

7592
def parse_relation(token: Token) -> Dict[str, Any] | None:
7693
"""Extract relation parts from token."""
7794
# Remove bullet point if present
78-
content = token.content.strip()
95+
# Use token.tag which contains the actual content for test tokens, fallback to content
96+
content = (token.tag or token.content).strip()
7997

8098
# Extract [[target]]
8199
target = None
@@ -209,10 +227,12 @@ def relation_rule(state: Any) -> None:
209227
token.meta["relations"] = [rel]
210228

211229
# Always check for inline links in any text
212-
elif "[[" in token.content:
213-
rels = parse_inline_relations(token.content)
214-
if rels:
215-
token.meta["relations"] = token.meta.get("relations", []) + rels
230+
else:
231+
content = token.tag or token.content
232+
if "[[" in content:
233+
rels = parse_inline_relations(content)
234+
if rels:
235+
token.meta["relations"] = token.meta.get("relations", []) + rels
216236

217237
# Add the rule after inline processing
218238
md.core.ruler.after("inline", "relations", relation_rule)

0 commit comments

Comments
 (0)