skills/memstate/scripts/memstate_get.py (2743 bytes)
1 #!/usr/bin/env python3 2 """Browse and retrieve memories from the memstated daemon. 3 4 Usage: 5 memstate_get.py # This repo's tree plus the user scope (names only) 6 memstate_get.py --scope user # The user scope tree, pruned to this host 7 memstate_get.py --list-projects # List all project ids 8 memstate_get.py --keypath db --include-content # Subtree with content 9 memstate_get.py --scope user --keypath preferences # User-scope subtree with content 10 memstate_get.py --project other_app --keypath db # Another project's subtree 11 memstate_get.py --memory-id 42 # Single memory by numeric ID 12 """ 13 import argparse 14 import sys 15 import urllib.error 16 import urllib.parse 17 18 from _client import (USER_PROJECT, add_scope_args, count_values, emit, fetch, 19 get, host_slug, list_projects_visible, prune_other_hosts, 20 resolve_project) 21 22 23 def _tree(project: str) -> dict: 24 return fetch("GET", f"/tree?project_id={urllib.parse.quote(project)}") 25 26 27 def _user_tree() -> dict: 28 """The user scope, pruned to this machine's host.<slug> subtree. A 29 soft-deleted _user project (HTTP 409) yields an empty scope so the 30 project tree still prints.""" 31 try: 32 domains = _tree(USER_PROJECT).get("domains") or [] 33 except urllib.error.HTTPError: 34 domains = [] 35 domains = prune_other_hosts(domains) 36 return {"host": host_slug(), "domains": domains, "total_memories": count_values(domains)} 37 38 39 def main() -> int: 40 ap = argparse.ArgumentParser(description="Browse and retrieve memories (server)") 41 add_scope_args(ap) 42 ap.add_argument("--list-projects", action="store_true", 43 help="list every project id in the store") 44 ap.add_argument("--keypath") 45 ap.add_argument("--memory-id", type=int) 46 ap.add_argument("--include-content", action="store_true") 47 args = ap.parse_args() 48 49 if args.list_projects: 50 return emit(list_projects_visible) 51 52 if args.memory_id is not None: 53 return get(f"/memories/{args.memory_id}") 54 55 project = resolve_project(args) 56 if args.keypath: 57 body = { 58 "project_id": project, 59 "keypath": args.keypath, 60 "recursive": True, 61 "include_content": args.include_content, 62 } 63 return emit(lambda: fetch("POST", "/keypaths", body)) 64 65 if project == USER_PROJECT: 66 return emit(_user_tree) 67 68 # The user scope rides along with every project tree, like the proxy. 69 def combined() -> dict: 70 tree = _tree(project) 71 tree["user"] = _user_tree() 72 return tree 73 74 return emit(combined) 75 76 77 if __name__ == "__main__": 78 sys.exit(main())