mem0ai--mem0
555e282cc4
pi-agent-plugin checks / lint (push) Has been cancelled
pi-agent-plugin checks / test (20) (push) Has been cancelled
pi-agent-plugin checks / test (22) (push) Has been cancelled
pi-agent-plugin checks / build (push) Has been cancelled
TypeScript SDK CI / check_changes (push) Has been cancelled
TypeScript SDK CI / changelog_check (push) Has been cancelled
ci / changelog_check (push) Has been cancelled
ci / check_changes (push) Has been cancelled
ci / build_mem0 (3.10) (push) Has been cancelled
ci / build_mem0 (3.11) (push) Has been cancelled
ci / build_mem0 (3.12) (push) Has been cancelled
CLI Node CI / lint (push) Has been cancelled
CLI Node CI / test (20) (push) Has been cancelled
CLI Node CI / test (22) (push) Has been cancelled
CLI Node CI / build (push) Has been cancelled
CLI Python CI / lint (push) Has been cancelled
CLI Python CI / test (3.10) (push) Has been cancelled
CLI Python CI / test (3.11) (push) Has been cancelled
CLI Python CI / test (3.12) (push) Has been cancelled
CLI Python CI / build (push) Has been cancelled
openclaw checks / lint (push) Has been cancelled
openclaw checks / test (20) (push) Has been cancelled
openclaw checks / test (22) (push) Has been cancelled
openclaw checks / build (push) Has been cancelled
opencode-plugin checks / build (push) Has been cancelled
TypeScript SDK CI / build_ts_sdk (20) (push) Has been cancelled
TypeScript SDK CI / build_ts_sdk (22) (push) Has been cancelled
TypeScript SDK CI / integration_ts_sdk (20) (push) Has been cancelled
TypeScript SDK CI / integration_ts_sdk (22) (push) Has been cancelled
221 行
8.0 KiB
Python
可执行文件
221 行
8.0 KiB
Python
可执行文件
#!/usr/bin/env python3
|
|
"""
|
|
Mem0 Documentation Search Agent (Mintlify-based)
|
|
On-demand search tool for querying Mem0 documentation without storing content locally.
|
|
|
|
This tool leverages Mintlify's documentation structure to perform just-in-time
|
|
retrieval of technical information from docs.mem0.ai.
|
|
|
|
Usage:
|
|
python mem0_doc_search.py --query "how to add graph memory"
|
|
python mem0_doc_search.py --query "filter syntax for categories"
|
|
python mem0_doc_search.py --page "/platform/features/graph-memory"
|
|
python mem0_doc_search.py --index
|
|
python mem0_doc_search.py --query "webhook events" --section platform
|
|
|
|
Purpose:
|
|
- Avoid bloating local context with full documentation
|
|
- Enable just-in-time retrieval of technical details
|
|
- Query specific documentation pages on demand
|
|
- Search across the full Mem0 documentation site
|
|
"""
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
import urllib.error
|
|
import urllib.parse
|
|
import urllib.request
|
|
|
|
DOCS_BASE = "https://docs.mem0.ai"
|
|
SEARCH_ENDPOINT = f"{DOCS_BASE}/api/search"
|
|
LLMS_INDEX = f"{DOCS_BASE}/llms.txt"
|
|
|
|
# Known documentation sections for targeted retrieval
|
|
SECTION_MAP = {
|
|
"platform": [
|
|
"/platform/overview",
|
|
"/platform/quickstart",
|
|
"/platform/features",
|
|
"/platform/features/graph-memory",
|
|
"/platform/features/selective-memory",
|
|
"/platform/features/custom-categories",
|
|
"/platform/features/v2-memory-filters",
|
|
"/platform/features/async-client",
|
|
"/platform/features/webhooks",
|
|
"/platform/features/multimodal-support",
|
|
],
|
|
"api": [
|
|
"/api-reference/memory/add-memories",
|
|
"/api-reference/memory/v2-search-memories",
|
|
"/api-reference/memory/v2-get-memories",
|
|
"/api-reference/memory/get-memory",
|
|
"/api-reference/memory/update-memory",
|
|
"/api-reference/memory/delete-memory",
|
|
],
|
|
"open-source": [
|
|
"/open-source/overview",
|
|
"/open-source/python-quickstart",
|
|
"/open-source/node-quickstart",
|
|
"/open-source/features",
|
|
"/open-source/features/graph-memory",
|
|
"/open-source/features/rest-api",
|
|
"/open-source/configure-components",
|
|
],
|
|
"sdks": [
|
|
"/sdks/python",
|
|
"/sdks/js",
|
|
],
|
|
"integrations": [
|
|
"/integrations",
|
|
],
|
|
}
|
|
|
|
|
|
def fetch_url(url: str) -> str:
|
|
"""Fetch content from a URL."""
|
|
req = urllib.request.Request(url, headers={"User-Agent": "Mem0DocSearchAgent/1.0"})
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=15) as resp:
|
|
return resp.read().decode("utf-8")
|
|
except urllib.error.HTTPError as e:
|
|
return f"HTTP Error {e.code}: {e.reason}"
|
|
except urllib.error.URLError as e:
|
|
return f"URL Error: {e.reason}"
|
|
|
|
|
|
def search_docs(query: str, section: str | None = None) -> dict:
|
|
"""
|
|
Search Mem0 documentation using Mintlify's search API.
|
|
Falls back to the llms.txt index for keyword matching if the API is unavailable.
|
|
"""
|
|
# Try Mintlify search API first
|
|
params = urllib.parse.urlencode({"query": query})
|
|
search_url = f"{SEARCH_ENDPOINT}?{params}"
|
|
|
|
try:
|
|
result = fetch_url(search_url)
|
|
data = json.loads(result)
|
|
if isinstance(data, dict) and data.get("results"):
|
|
results = data["results"]
|
|
if section and section in SECTION_MAP:
|
|
section_paths = SECTION_MAP[section]
|
|
results = [r for r in results if any(r.get("url", "").startswith(p) for p in section_paths)]
|
|
return {"source": "mintlify_search", "results": results}
|
|
except (json.JSONDecodeError, Exception):
|
|
pass
|
|
|
|
# Fallback: search llms.txt index for matching URLs
|
|
index_content = fetch_url(LLMS_INDEX)
|
|
query_lower = query.lower()
|
|
matching_urls = []
|
|
|
|
for line in index_content.splitlines():
|
|
line = line.strip()
|
|
if not line or line.startswith("#"):
|
|
continue
|
|
if query_lower in line.lower():
|
|
matching_urls.append(line)
|
|
|
|
if section and section in SECTION_MAP:
|
|
section_paths = SECTION_MAP[section]
|
|
matching_urls = [u for u in matching_urls if any(p in u for p in section_paths)]
|
|
|
|
return {
|
|
"source": "llms_txt_index",
|
|
"query": query,
|
|
"matching_urls": matching_urls[:20],
|
|
"suggestion": "Fetch specific URLs for detailed content",
|
|
}
|
|
|
|
|
|
def fetch_page(page_path: str) -> dict:
|
|
"""Fetch a specific documentation page."""
|
|
url = f"{DOCS_BASE}{page_path}" if page_path.startswith("/") else page_path
|
|
content = fetch_url(url)
|
|
return {"url": url, "content": content[:10000], "truncated": len(content) > 10000}
|
|
|
|
|
|
def get_index() -> dict:
|
|
"""Fetch the full documentation index from llms.txt."""
|
|
content = fetch_url(LLMS_INDEX)
|
|
urls = [line.strip() for line in content.splitlines() if line.strip() and not line.startswith("#")]
|
|
return {"total_pages": len(urls), "urls": urls, "sections": list(SECTION_MAP.keys())}
|
|
|
|
|
|
def list_section(section: str) -> dict:
|
|
"""List all known pages in a documentation section."""
|
|
if section not in SECTION_MAP:
|
|
return {"error": f"Unknown section: {section}", "available": list(SECTION_MAP.keys())}
|
|
return {
|
|
"section": section,
|
|
"pages": [f"{DOCS_BASE}{p}" for p in SECTION_MAP[section]],
|
|
}
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Search Mem0 documentation on demand")
|
|
parser.add_argument("--query", help="Search query for documentation")
|
|
parser.add_argument("--page", help="Fetch a specific page path (e.g., /platform/features/graph-memory)")
|
|
parser.add_argument("--index", action="store_true", help="Show full documentation index")
|
|
parser.add_argument("--section", help="Filter by section or list section pages")
|
|
parser.add_argument("--json", action="store_true", help="Output as JSON")
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.index:
|
|
result = get_index()
|
|
elif args.section and not args.query:
|
|
result = list_section(args.section)
|
|
elif args.page:
|
|
result = fetch_page(args.page)
|
|
elif args.query:
|
|
result = search_docs(args.query, section=args.section)
|
|
else:
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
|
|
if args.json:
|
|
print(json.dumps(result, indent=2))
|
|
else:
|
|
if isinstance(result, dict):
|
|
if "results" in result:
|
|
print(f"Source: {result.get('source', 'unknown')}")
|
|
for r in result["results"]:
|
|
print(f" - {r.get('title', 'N/A')}: {r.get('url', 'N/A')}")
|
|
if r.get("description"):
|
|
print(f" {r['description'][:200]}")
|
|
elif "matching_urls" in result:
|
|
print(f"Source: {result['source']}")
|
|
print(f"Query: {result['query']}")
|
|
for url in result["matching_urls"]:
|
|
print(f" - {url}")
|
|
if result.get("suggestion"):
|
|
print(f"\n{result['suggestion']}")
|
|
elif "urls" in result:
|
|
print(f"Total documentation pages: {result['total_pages']}")
|
|
print(f"Sections: {', '.join(result['sections'])}")
|
|
for url in result["urls"][:30]:
|
|
print(f" - {url}")
|
|
if result["total_pages"] > 30:
|
|
print(f" ... and {result['total_pages'] - 30} more")
|
|
elif "pages" in result:
|
|
print(f"Section: {result['section']}")
|
|
for page in result["pages"]:
|
|
print(f" - {page}")
|
|
elif "content" in result:
|
|
print(f"URL: {result['url']}")
|
|
if result.get("truncated"):
|
|
print("[Content truncated to 10000 chars]")
|
|
print(result["content"])
|
|
elif "error" in result:
|
|
print(f"Error: {result['error']}")
|
|
if result.get("available"):
|
|
print(f"Available sections: {', '.join(result['available'])}")
|
|
else:
|
|
print(json.dumps(result, indent=2))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|