Update recursive_context.py
Browse files- recursive_context.py +51 -19
recursive_context.py
CHANGED
|
@@ -701,8 +701,8 @@ class RecursiveContextManager:
|
|
| 701 |
# 3. Push the entire manifest back to your PRO storage dataset
|
| 702 |
self.persistence.save_conversations(full_data)
|
| 703 |
|
| 704 |
-
|
| 705 |
-
#
|
| 706 |
# =====================================================================
|
| 707 |
def push_to_github(self, commit_message="Auto-backup from Clawdbot"):
|
| 708 |
"""Pushes the current workspace to the configured GitHub repository."""
|
|
@@ -714,7 +714,7 @@ class RecursiveContextManager:
|
|
| 714 |
if not (self.repo_path / ".git").exists():
|
| 715 |
subprocess.run(["git", "init"], cwd=self.repo_path, check=True)
|
| 716 |
subprocess.run(["git", "remote", "add", "origin", remote_url], cwd=self.repo_path)
|
| 717 |
-
subprocess.run(["git", "fetch", "origin"], cwd=self.repo_path, check=True)
|
| 718 |
subprocess.run(["git", "add", "."], cwd=self.repo_path, check=True)
|
| 719 |
subprocess.run(["git", "commit", "-m", commit_message], cwd=self.repo_path, capture_output=True, text=True)
|
| 720 |
push_res = subprocess.run(["git", "push", "-u", "origin", "main", "--force"], cwd=self.repo_path, capture_output=True, text=True)
|
|
@@ -736,22 +736,54 @@ class RecursiveContextManager:
|
|
| 736 |
return f"✅ RESTORED from GitHub/{branch}" if res.returncode == 0 else f"⚠️ Pull Failed: {res.stderr}"
|
| 737 |
except Exception as e: return f"❌ Critical Git Error: {e}"
|
| 738 |
|
| 739 |
-
|
| 740 |
-
|
| 741 |
-
|
| 742 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 743 |
|
| 744 |
-
def
|
| 745 |
-
"""
|
| 746 |
-
|
|
|
|
|
|
|
|
|
|
| 747 |
try:
|
| 748 |
-
memory_file.parent.mkdir(parents=True, exist_ok=True)
|
| 749 |
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
| 750 |
-
|
| 751 |
-
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
|
| 755 |
-
|
| 756 |
-
|
| 757 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 701 |
# 3. Push the entire manifest back to your PRO storage dataset
|
| 702 |
self.persistence.save_conversations(full_data)
|
| 703 |
|
| 704 |
+
# =====================================================================
|
| 705 |
+
# GIT TOOLS
|
| 706 |
# =====================================================================
|
| 707 |
def push_to_github(self, commit_message="Auto-backup from Clawdbot"):
|
| 708 |
"""Pushes the current workspace to the configured GitHub repository."""
|
|
|
|
| 714 |
if not (self.repo_path / ".git").exists():
|
| 715 |
subprocess.run(["git", "init"], cwd=self.repo_path, check=True)
|
| 716 |
subprocess.run(["git", "remote", "add", "origin", remote_url], cwd=self.repo_path)
|
| 717 |
+
subprocess.run(["git", "fetch", "origin"], cwd=self.repo_path, check=True)
|
| 718 |
subprocess.run(["git", "add", "."], cwd=self.repo_path, check=True)
|
| 719 |
subprocess.run(["git", "commit", "-m", commit_message], cwd=self.repo_path, capture_output=True, text=True)
|
| 720 |
push_res = subprocess.run(["git", "push", "-u", "origin", "main", "--force"], cwd=self.repo_path, capture_output=True, text=True)
|
|
|
|
| 736 |
return f"✅ RESTORED from GitHub/{branch}" if res.returncode == 0 else f"⚠️ Pull Failed: {res.stderr}"
|
| 737 |
except Exception as e: return f"❌ Critical Git Error: {e}"
|
| 738 |
|
| 739 |
+
# =====================================================================
|
| 740 |
+
# WORKING MEMORY NOTEBOOK (Structured List)
|
| 741 |
+
# =====================================================================
|
| 742 |
+
def _load_notebook(self) -> List[Dict]:
|
| 743 |
+
"""Internal helper to load notebook JSON."""
|
| 744 |
+
notebook_path = self.repo_path / "memory" / "notebook.json"
|
| 745 |
+
if not notebook_path.exists(): return []
|
| 746 |
+
try: return json.loads(notebook_path.read_text(encoding='utf-8'))
|
| 747 |
+
except: return []
|
| 748 |
|
| 749 |
+
def _save_notebook(self, notes: List[Dict]):
|
| 750 |
+
"""Internal helper to save notebook JSON with audit logging."""
|
| 751 |
+
notebook_path = self.repo_path / "memory" / "notebook.json"
|
| 752 |
+
log_path = self.repo_path / "memory" / "history.log"
|
| 753 |
+
notebook_path.parent.mkdir(parents=True, exist_ok=True)
|
| 754 |
+
notebook_path.write_text(json.dumps(notes, indent=2), encoding='utf-8')
|
| 755 |
try:
|
|
|
|
| 756 |
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
| 757 |
+
with open(log_path, "a") as f: f.write(f"[{timestamp}] NOTEBOOK UPDATED | Count: {len(notes)}\n")
|
| 758 |
+
except: pass
|
| 759 |
+
|
| 760 |
+
def notebook_read(self) -> str:
|
| 761 |
+
"""Reads the Working Memory notebook."""
|
| 762 |
+
notes = self._load_notebook()
|
| 763 |
+
if not notes: return ""
|
| 764 |
+
display = []
|
| 765 |
+
for i, note in enumerate(notes):
|
| 766 |
+
display.append(f"{i+1}. [{note['timestamp']}] {note['content']}")
|
| 767 |
+
return "\n".join(display)
|
| 768 |
+
|
| 769 |
+
def notebook_add(self, content: str) -> str:
|
| 770 |
+
"""Adds a new note to the notebook."""
|
| 771 |
+
notes = self._load_notebook()
|
| 772 |
+
if len(notes) >= 25: return "⚠️ Notebook full (25/25 slots). Please delete obsolete notes first."
|
| 773 |
+
timestamp = time.strftime("%Y-%m-%d %H:%M")
|
| 774 |
+
notes.append({"timestamp": timestamp, "content": content})
|
| 775 |
+
self._save_notebook(notes)
|
| 776 |
+
return f"✅ Note added. ({len(notes)}/25 slots used)"
|
| 777 |
+
|
| 778 |
+
def notebook_delete(self, index: int) -> str:
|
| 779 |
+
"""Deletes a note by its number (1-based index)."""
|
| 780 |
+
notes = self._load_notebook()
|
| 781 |
+
try:
|
| 782 |
+
idx = int(index) - 1
|
| 783 |
+
if 0 <= idx < len(notes):
|
| 784 |
+
removed = notes.pop(idx)
|
| 785 |
+
self._save_notebook(notes)
|
| 786 |
+
return f"✅ Deleted note #{index}: '{removed['content'][:30]}...'"
|
| 787 |
+
else: return f"❌ Invalid index: {index}. Valid range: 1-{len(notes)}"
|
| 788 |
+
except ValueError: return "❌ Index must be a number."
|
| 789 |
+
|