feat(memory): resolve paths in context reads

This commit is contained in:
HumbleTurtle
2026-07-19 15:18:29 -03:00
parent 7e4002579b
commit 590d10b7da
2 changed files with 14 additions and 9 deletions
+8 -5
View File
@@ -9765,12 +9765,11 @@ def classify_memory_query(args):
def get_memory_context(args):
if args.get("path") or args.get("paths"):
raise RuntimeError("paths are index/routes only; resolve them with nap_node_by_path, then use node_id/uri inputs")
raw_node_ids = args.get("node_ids") or ([args["node_id"]] if args.get("node_id") else [])
raw_uris = args.get("uris") or ([args["uri"]] if args.get("uri") else [])
if not raw_node_ids and not raw_uris:
raise RuntimeError("node_id, node_ids, uri, or uris is required")
raw_paths = args.get("paths") or ([args["path"]] if args.get("path") else [])
if not raw_node_ids and not raw_uris and not raw_paths:
raise RuntimeError("path, paths, node_id, node_ids, uri, or uris is required")
max_nodes = max(1, min(int(args.get("max_nodes", 20)), 100))
depth = max(0, min(int(args.get("depth", 1)), 2))
default_view = "summary"
@@ -9780,6 +9779,8 @@ def get_memory_context(args):
queue.append(("node", get_node_by_id({"node_id": node_id})))
for uri in raw_uris:
queue.append(("node", node_by_uri({"uri": uri})["node"]))
for path in raw_paths:
queue.append(("path", normalize_node_path(path)))
nodes = []
edges = []
seen_paths = set()
@@ -11562,10 +11563,12 @@ def raw_tools():
*kanban_workflow_tool_schemas(),
{
"name": "nap_context",
"description": "Fetch one or more nodes plus bounded outgoing links and backlinks for surrounding context.",
"description": "Resolve one or more paths, node IDs, or nap:// URIs and fetch bounded outgoing links and backlinks in one call.",
"inputSchema": {
"type": "object",
"properties": {
"path": {"type": "string", "description": "Readable route to resolve internally; canonical identity is returned in the result."},
"paths": {"type": "array", "items": {"type": "string"}},
"node_id": {"type": "string"},
"node_ids": {"type": "array", "items": {"type": "string"}},
"uri": {"type": "string"},
+6 -4
View File
@@ -329,8 +329,8 @@ def test_tools_include_node_by_path_descriptor(mod):
assert "node_ids" in context_schema["properties"]
assert "uri" in context_schema["properties"]
assert "uris" in context_schema["properties"]
assert "path" not in context_schema["properties"]
assert "paths" not in context_schema["properties"]
assert "path" in context_schema["properties"]
assert "paths" in context_schema["properties"]
related_schema = next(item for item in mod.tools() if item["name"] == "nap_find_related")["inputSchema"]
assert "node_id" in related_schema["properties"]
@@ -599,6 +599,8 @@ def test_context_and_related_use_identity_inputs(mod):
raise AssertionError(f"unexpected node_id {node_id}")
def fake_read_by_path(args, allow_agent=False):
if args["path"] == "/notes/root":
return root
if args["path"] == "/notes/linked":
return linked
if args["path"] == "/notes/backlink":
@@ -627,8 +629,8 @@ def test_context_and_related_use_identity_inputs(mod):
assert related["target"]["full_path"] == "/notes/root"
assert {item["full_path"] for item in related["items"]} >= {"/notes/backlink", "/notes/linked"}
with pytest.raises(RuntimeError, match="paths are index/routes only"):
mod.get_memory_context({"path": "/notes/root"})
path_context = mod.get_memory_context({"path": "/notes/root", "depth": 0, "view": "paths"})
assert [item["full_path"] for item in path_context["items"]] == ["/notes/root"]
with pytest.raises(RuntimeError, match="path is an index/route only"):
mod.find_related_nodes({"path": "/notes/root"})