mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-09-22 00:32:49 +00:00
docs(protocol): add typed edge link protocol documentation Add comprehensive documentation for the link protocol supporting typed edges in body text. This includes specification for three legal inline forms (bare wikilink, line-level Dataview, inline-bracketed Dataview), predicate syntax rules, and the machine-managed Relations section convention for organizing discovered edges. fix(memory): update path reference from vault_root to working_dir Change the memory_create operation's path anchoring from vault_root to working_dir to maintain consistency with the current working directory configuration. refactor(components): remove edge_extractor module and simplify parsing Remove the edge_extractor component module entirely and inline edge extraction logic directly into LinkedFileParser using parse_wikilinks utility. This simplifies the architecture by eliminating the separate edge extraction component and delegating edge discovery to the maintainer's enrichment operations. feat(parser): update parse method signature and simplify edge extraction Modify LinkedFileParser to return (FileNode, list[FileChunk]) tuple instead of ParsedFile, remove dependency on BaseEdgeExtractor, and implement direct wikilink parsing from body text only. ```
56 lines
1.9 KiB
Python
56 lines
1.9 KiB
Python
"""Wikilink resolution — pure functions over a `BaseFileStore`'s graph.
|
|
|
|
Wikilink resolution is a vault convention (path/stem forms, folder-note
|
|
preference) layered on top of the engine's plain `dict[path, FileNode]`.
|
|
Keeping it out of `BaseFileStore` keeps the engine domain-agnostic.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from reme2.component.file_store.base_file_store import BaseFileStore
|
|
|
|
|
|
def wikilink_candidates(store: BaseFileStore, target: str) -> list[str]:
|
|
"""Paths `[[target]]` would resolve to (folder-note hit wins).
|
|
|
|
Folder-note convention: `topics/X/X.md` is the cluster head for
|
|
bare `[[X]]`, beating any sibling that just shares the stem.
|
|
"""
|
|
folder_hits = sorted(
|
|
p for p in store._stems.get(target, ()) if Path(p).parent.name == target
|
|
)
|
|
if folder_hits:
|
|
return folder_hits
|
|
return store.get_paths_by_stem(target)
|
|
|
|
|
|
def resolve_wikilink(store: BaseFileStore, wikilink: str) -> str | None:
|
|
"""Resolve a `[[target]]` to one absolute path.
|
|
|
|
- Path form (`topics/X/X` or `topics/X/X.md`) → relative to `working_dir`.
|
|
- Stem form (`X`) → folder-note preference, else unique stem hit.
|
|
- Ambiguous stems return None and log a warning.
|
|
"""
|
|
target = wikilink.strip()
|
|
if not target:
|
|
return None
|
|
|
|
if "/" in target or target.endswith(".md"):
|
|
if store.working_dir is None:
|
|
return None
|
|
candidate = target if target.endswith(".md") else f"{target}.md"
|
|
abs_candidate = str((store.working_dir / candidate).resolve())
|
|
return abs_candidate if abs_candidate in store.nodes else None
|
|
|
|
candidates = wikilink_candidates(store, target)
|
|
if len(candidates) == 1:
|
|
return candidates[0]
|
|
if len(candidates) > 1:
|
|
store.logger.warning(
|
|
f"Wikilink [[{target}]] is ambiguous, candidates: {candidates}",
|
|
)
|
|
return None
|