feat(memory): resolve paths in context reads
This commit is contained in:
@@ -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"},
|
||||
|
||||
@@ -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"})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user