Update recursive_context.py
Browse files- recursive_context.py +69 -1
recursive_context.py
CHANGED
|
@@ -461,7 +461,7 @@ class RecursiveContextManager:
|
|
| 461 |
subprocess.run(["git", "init"], cwd=self.repo_path, check=True)
|
| 462 |
subprocess.run(["git", "remote", "add", "origin", remote_url], cwd=self.repo_path)
|
| 463 |
|
| 464 |
-
# 2. Fetch and Reset
|
| 465 |
subprocess.run(["git", "fetch", "origin"], cwd=self.repo_path, check=True)
|
| 466 |
res = subprocess.run(
|
| 467 |
["git", "reset", "--hard", f"origin/{branch}"],
|
|
@@ -475,6 +475,74 @@ class RecursiveContextManager:
|
|
| 475 |
|
| 476 |
except Exception as e:
|
| 477 |
return f"❌ Critical Git Error: {e}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 478 |
# =====================================================================
|
| 479 |
# RECURSIVE SEARCH TOOLS
|
| 480 |
# =====================================================================
|
|
|
|
| 461 |
subprocess.run(["git", "init"], cwd=self.repo_path, check=True)
|
| 462 |
subprocess.run(["git", "remote", "add", "origin", remote_url], cwd=self.repo_path)
|
| 463 |
|
| 464 |
+
# 2. Fetch and Reset
|
| 465 |
subprocess.run(["git", "fetch", "origin"], cwd=self.repo_path, check=True)
|
| 466 |
res = subprocess.run(
|
| 467 |
["git", "reset", "--hard", f"origin/{branch}"],
|
|
|
|
| 475 |
|
| 476 |
except Exception as e:
|
| 477 |
return f"❌ Critical Git Error: {e}"
|
| 478 |
+
|
| 479 |
+
# =====================================================================
|
| 480 |
+
# WORKING MEMORY NOTEBOOK (Structured List)
|
| 481 |
+
# =====================================================================
|
| 482 |
+
def _load_notebook(self) -> List[Dict]:
|
| 483 |
+
"""Internal helper to load notebook JSON."""
|
| 484 |
+
notebook_path = self.repo_path / "memory" / "notebook.json"
|
| 485 |
+
if not notebook_path.exists():
|
| 486 |
+
return []
|
| 487 |
+
try:
|
| 488 |
+
return json.loads(notebook_path.read_text(encoding='utf-8'))
|
| 489 |
+
except:
|
| 490 |
+
return []
|
| 491 |
+
|
| 492 |
+
def _save_notebook(self, notes: List[Dict]):
|
| 493 |
+
"""Internal helper to save notebook JSON with audit logging."""
|
| 494 |
+
notebook_path = self.repo_path / "memory" / "notebook.json"
|
| 495 |
+
log_path = self.repo_path / "memory" / "history.log"
|
| 496 |
+
|
| 497 |
+
notebook_path.parent.mkdir(parents=True, exist_ok=True)
|
| 498 |
+
notebook_path.write_text(json.dumps(notes, indent=2), encoding='utf-8')
|
| 499 |
+
|
| 500 |
+
# Audit Log (Metadata only)
|
| 501 |
+
try:
|
| 502 |
+
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
| 503 |
+
with open(log_path, "a") as f:
|
| 504 |
+
f.write(f"[{timestamp}] NOTEBOOK UPDATED | Count: {len(notes)}\n")
|
| 505 |
+
except: pass
|
| 506 |
+
|
| 507 |
+
def notebook_read(self) -> str:
|
| 508 |
+
"""Reads the Working Memory notebook."""
|
| 509 |
+
notes = self._load_notebook()
|
| 510 |
+
if not notes:
|
| 511 |
+
return "" # Return empty string so UI doesn't clutter if empty
|
| 512 |
+
|
| 513 |
+
display = []
|
| 514 |
+
for i, note in enumerate(notes):
|
| 515 |
+
# Format: "1. [2026-02-03 14:00] Note content..."
|
| 516 |
+
display.append(f"{i+1}. [{note['timestamp']}] {note['content']}")
|
| 517 |
+
return "\n".join(display)
|
| 518 |
+
|
| 519 |
+
def notebook_add(self, content: str) -> str:
|
| 520 |
+
"""Adds a new note to the notebook."""
|
| 521 |
+
notes = self._load_notebook()
|
| 522 |
+
|
| 523 |
+
# Pocket Notebook Limit (Force curation)
|
| 524 |
+
if len(notes) >= 25:
|
| 525 |
+
return "⚠️ Notebook full (25/25 slots). Please delete obsolete notes first."
|
| 526 |
+
|
| 527 |
+
timestamp = time.strftime("%Y-%m-%d %H:%M")
|
| 528 |
+
notes.append({"timestamp": timestamp, "content": content})
|
| 529 |
+
self._save_notebook(notes)
|
| 530 |
+
return f"✅ Note added. ({len(notes)}/25 slots used)"
|
| 531 |
+
|
| 532 |
+
def notebook_delete(self, index: int) -> str:
|
| 533 |
+
"""Deletes a note by its number (1-based index)."""
|
| 534 |
+
notes = self._load_notebook()
|
| 535 |
+
try:
|
| 536 |
+
# Convert 1-based index (User view) to 0-based (List view)
|
| 537 |
+
idx = int(index) - 1
|
| 538 |
+
if 0 <= idx < len(notes):
|
| 539 |
+
removed = notes.pop(idx)
|
| 540 |
+
self._save_notebook(notes)
|
| 541 |
+
return f"✅ Deleted note #{index}: '{removed['content'][:30]}...'"
|
| 542 |
+
else:
|
| 543 |
+
return f"❌ Invalid index: {index}. Valid range: 1-{len(notes)}"
|
| 544 |
+
except ValueError:
|
| 545 |
+
return "❌ Index must be a number."
|
| 546 |
# =====================================================================
|
| 547 |
# RECURSIVE SEARCH TOOLS
|
| 548 |
# =====================================================================
|