Files
Claude-Code-Workflow/.claude/python_script/api_indexer.py
catlog22 410d0efd7b feat: Add API indexer and enhance embedding management
- Add new API indexer script for document processing
- Update embedding manager with improved functionality
- Remove old cache files and update dependencies
- Modify workflow execute documentation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-23 19:40:22 +08:00

142 lines
5.1 KiB
Python

#!/usr/bin/env python3
"""
API Documentation Indexer
Parses Markdown documentation to create a searchable index of classes and methods.
"""
import os
import re
import json
import logging
from pathlib import Path
from typing import Dict, Any
from core.file_indexer import FileIndexer
class ApiIndexer:
def __init__(self, config: Dict, root_path: str = "."):
self.config = config
self.root_path = Path(root_path).resolve()
self.file_indexer = FileIndexer(config, root_path)
self.api_index_file = self.file_indexer.cache_dir / "api_index.json"
self.logger = logging.getLogger(__name__)
def build_index(self):
"""Builds the API index from Markdown files."""
self.logger.info("Building API index...")
file_index = self.file_indexer.load_index()
if not file_index:
self.logger.info("File index not found, building it first.")
self.file_indexer.build_index()
file_index = self.file_indexer.load_index()
api_index = {}
for file_info in file_index.values():
if file_info.extension == ".md":
self.logger.debug(f"Parsing {file_info.path}")
try:
with open(file_info.path, "r", encoding="utf-8") as f:
content = f.read()
self._parse_markdown(content, file_info.relative_path, api_index)
except Exception as e:
self.logger.error(f"Error parsing {file_info.path}: {e}")
self._save_index(api_index)
self.logger.info(f"API index built with {len(api_index)} classes.")
def _parse_markdown(self, content: str, file_path: str, api_index: Dict):
"""Parses a single Markdown file for class and method info."""
class_name_match = re.search(r"^#\s+([A-Za-z0-9_]+)", content)
if not class_name_match:
return
class_name = class_name_match.group(1)
api_index[class_name] = {
"file_path": file_path,
"description": "",
"methods": {}
}
# Simple description extraction
desc_match = re.search(r"\*\*Description:\*\*\s*(.+)", content)
if desc_match:
api_index[class_name]["description"] = desc_match.group(1).strip()
# Method extraction
method_sections = re.split(r"###\s+", content)[1:]
for i, section in enumerate(method_sections):
method_signature_match = re.search(r"`(.+?)`", section)
if not method_signature_match:
continue
signature = method_signature_match.group(1)
method_name_match = re.search(r"([A-Za-z0-9_]+)\(“, signature)
if not method_name_match:
continue
method_name = method_name_match.group(1)
method_description = ""
method_desc_match = re.search(r"\*\*Description:\*\*\s*(.+)", section)
if method_desc_match:
method_description = method_desc_match.group(1).strip()
# A simple way to get a line number approximation
line_number = content.count("\n", 0, content.find(f"### `{signature}`")) + 1
api_index[class_name]["methods"Показать больше] = {
"signature": signature,
"description": method_description,
"line_number": line_number
}
def _save_index(self, api_index: Dict):
"""Saves the API index to a file."""
try:
with open(self.api_index_file, "w", encoding="utf-8") as f:
json.dump(api_index, f, indent=2)
except IOError as e:
self.logger.error(f"Could not save API index: {e}")
def search(self, class_name: str, method_name: str = None) -> Any:
"""Searches the API index for a class or method."""
if not self.api_index_file.exists():
self.build_index()
with open(self.api_index_file, "r", encoding="utf-8") as f:
api_index = json.load(f)
if class_name not in api_index:
return None
if method_name:
return api_index[class_name]["methods"].get(method_name)
else:
return api_index[class_name]
if __name__ == "__main__":
from core.config import get_config
import argparse
logging.basicConfig(level=logging.INFO)
parser = argparse.ArgumentParser(description="API Documentation Indexer.")
parser.add_argument("--build", action="store_true", help="Build the API index.")
parser.add_argument("--search_class", help="Search for a class.")
parser.add_argument("--search_method", help="Search for a method within a class (requires --search_class).")
args = parser.parse_args()
config = get_config()
api_indexer = ApiIndexer(config.to_dict())
if args.build:
api_indexer.build_index()
if args.search_class:
result = api_indexer.search(args.search_class, args.search_method)
if result:
print(json.dumps(result, indent=2))
else:
print("Not found.")