项目文件夹

文件
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 13:03:45 +08:00

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()