From c76201381a1030216b37cd7ec44c8bd136d1e7dc Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Sat, 31 Jan 2026 08:27:30 +0000 Subject: [PATCH] Add recorder, project, context, search, and history modules --- .cli_memory/context.py | 85 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 .cli_memory/context.py diff --git a/.cli_memory/context.py b/.cli_memory/context.py new file mode 100644 index 0000000..cace762 --- /dev/null +++ b/.cli_memory/context.py @@ -0,0 +1,85 @@ +import os +import subprocess +from typing import Optional, List, Dict, Any +from pathlib import Path + +from .config import Config +from .models import Project +from .project import ProjectDetector + + +class ContextExtractor: + def __init__(self, config: Optional[Config] = None): + self.config = config or Config() + self.project_detector = ProjectDetector(config) + + def get_current_context(self) -> Dict[str, Any]: + working_dir = os.getcwd() + project = self.project_detector.detect(working_dir) + + context = { + "working_directory": working_dir, + "project": project.to_dict() if project else None, + "git_branch": self._get_git_branch(), + "git_status": self._get_git_status(), + "user": os.getenv("USER", "unknown"), + "hostname": os.getenv("HOSTNAME", "unknown"), + "timestamp": str(datetime.utcnow()), + } + + return context + + def _get_git_branch(self) -> Optional[str]: + try: + result = subprocess.run( + ["git", "rev-parse", "--abbrev-ref", "HEAD"], + capture_output=True, + text=True, + timeout=5, + ) + if result.returncode == 0: + return result.stdout.strip() + except (subprocess.SubprocessError, FileNotFoundError): + pass + return None + + def _get_git_status(self) -> Dict[str, Any]: + try: + result = subprocess.run( + ["git", "status", "--porcelain"], + capture_output=True, + text=True, + timeout=5, + ) + if result.returncode == 0: + lines = result.stdout.strip().split("\n") if result.stdout.strip() else [] + return { + "modified": len([l for l in lines if l.startswith(" M") or l.startswith("M ")]), + "staged": len([l for l in lines if l.startswith("M ") or l.startswith("A ")]), + "untracked": len([l for l in lines if l.startswith("??")]), + } + except (subprocess.SubprocessError, FileNotFoundError): + pass + return {"modified": 0, "staged": 0, "untracked": 0} + + def get_project_context_commands(self, project: Project) -> List[str]: + commands = [] + if project.git_remote: + commands.append(f"git remote get-url origin # {project.git_remote}") + for tech in project.tech_stack: + if tech == "Python": + commands.append("python -m pip install -r requirements.txt") + elif tech == "Node.js": + commands.append("npm install") + elif tech == "Docker": + commands.append("docker-compose up -d") + return commands + + def extract_context_from_path(self, path: str) -> Dict[str, Any]: + project = self.project_detector.detect(path) + return { + "path": path, + "project": project.to_dict() if project else None, + "exists": os.path.exists(path), + "is_directory": os.path.isdir(path) if os.path.exists(path) else False, + }