Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/ai-brain-core / sub_brains/hypothalamus/devtools/fetcher.py |
| Date | Not specified in source |
| Repository | Janady13/ai-brain-core |
| Revision | f7275582f13ada80bfb3b1008089800ca26f4a23 |
| Branch | main |
| Path or archive member | sub_brains/hypothalamus/devtools/fetcher.py |
| Original SHA-256 | 7e54e22c6b73c06ef8c217ce1c6d20400a4422ad08dd648cc535f584be6bfbaf |
| Git blob SHA | 165dbd1ae41cae8bb4e7840e2ae93c4f3c6a8240 |
| Reading-copy SHA-256 | 7e54e22c6b73c06ef8c217ce1c6d20400a4422ad08dd648cc535f584be6bfbaf |
Every recorded occurrence
These 3 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| Janady13/ai-brain-core / sub_brains/hypothalamus/devtools/fetcher.py | main | f7275582f13ada80bfb3b1008089800ca26f4a23 | Open original |
| Janady13/ai-brain-core / sub_brains/hypothalamus/devtools/fetcher.py | claude/agi-architecture-diagram-01GJ7CohfKvLb77yiKpHqd6d | 365850e27004318edd582881225024026b118c2d | Open original |
| Janady13/ai-brain-core / sub_brains/hypothalamus/devtools/fetcher.py | healer-core | 0fe4cbbaa91912149f1a8e32205371ff67017268 | Open original |
Recovered source transcript
Download complete source text ↓153 lines · 5.4 KB
#!/usr/bin/env python3
import ai_brain_env # auto-inserted by update_ai_brain_env_paths.sh
"""
devtools/fetcher.py
Trigger safe sync of devtools modules when a module reports an error.
Behavior:
- If ~/Desktop/AI_Brain/manager_sync.sh exists & is executable, run it in background and log.
- Otherwise, if a module repo URL is provided (via file mapping or env), attempt git pull/clone into the module folder.
- Rate-limited per-module (10 minutes) to avoid loops.
- Writes logs to ~/Desktop/AI_Brain/logs/fetcher.log
Usage:
python3 fetcher.py --module git_health
python3 fetcher.py --module ssh_keeper --repo https://github.com/OWNER/repo.git
"""
import argparse, os, time, subprocess
from pathlib import Path
import json
HOME = Path.home()
BRAIN_HOME = HOME / "Desktop" / "AI_Brain"
BASE = BRAIN_HOME / "sub_brains" / "hypothalamus" / "devtools"
LOG = BRAIN_HOME / "logs" / "fetcher.log"
MGR_SYNC = BRAIN_HOME / "manager_sync.sh"
RATE_LIMIT_SECS = 600 # 10 minutes
RATE_DIR = BRAIN_HOME / "status" / "fetcher_rate"
RATE_DIR.mkdir(parents=True, exist_ok=True)
def log(msg):
ts = time.strftime("%Y-%m-%d %H:%M:%S")
line = f"{ts} {msg}"
print(line)
try:
with open(LOG, "a") as f:
f.write(line + "\n")
except Exception:
pass
def touched_recent(module):
stamp = RATE_DIR / f"{module}.last"
if not stamp.exists():
return False
try:
t = float(stamp.read_text().strip())
return (time.time() - t) < RATE_LIMIT_SECS
except Exception:
return False
def touch_stamp(module):
stamp = RATE_DIR / f"{module}.last"
try:
stamp.write_text(str(time.time()))
except Exception:
pass
def run_manager_sync():
try:
if MGR_SYNC.exists() and os.access(str(MGR_SYNC), os.X_OK):
log("Starting manager_sync.sh (background)...")
# append stdout/stderr to manager_sync.log
mgr_log = BRAIN_HOME / "logs" / "manager_sync.log"
with open(mgr_log, "ab") as out:
p = subprocess.Popen([str(MGR_SYNC)], stdout=out, stderr=out)
log(f"manager_sync.sh started pid={p.pid}")
return True
except Exception as e:
log(f"manager_sync invocation failed: {e}")
return False
def clone_or_pull(module, repo_url=None):
target = BASE / module
if repo_url is None:
# Try to read mapping file: BRAIN_HOME/hypothalamus_devtools_sources.json
mapping_file = BRAIN_HOME / "hypothalamus_devtools_sources.json"
if mapping_file.exists():
try:
m = json.loads(mapping_file.read_text())
repo_url = m.get(module)
except Exception:
repo_url = None
if not repo_url:
log(f"No repo URL available for {module}; cannot clone/pull.")
return False
# If target exists and is a git repo -> git pull
if (target / ".git").exists():
log(f"Attempting git -C {target} pull")
try:
p = subprocess.run(f'git -C "{target}" fetch --all --prune && git -C "{target}" reset --hard origin/$(git -C "{target}" rev-parse --abbrev-ref @{1} 2>/dev/null || echo main)', shell=True, check=False)
log(f"git pull returncode={p.returncode}")
return p.returncode == 0
except Exception as e:
log(f"git pull failed for {module}: {e}")
return False
else:
# clone shallow
parent = target.parent
parent.mkdir(parents=True, exist_ok=True)
tmp = str(target) + ".tmp"
try:
log(f"Cloning {repo_url} -> {tmp}")
p = subprocess.run(f'git clone --depth=1 "{repo_url}" "{tmp}"', shell=True, check=False)
if p.returncode == 0:
# move into place (backup any old dir)
if target.exists():
bak = str(target) + ".bak." + time.strftime("%Y%m%dT%H%M%SZ")
Path(target).rename(bak)
log(f"Backed up old {target} -> {bak}")
Path(tmp).rename(target)
log(f"Cloned {module} into {target}")
return True
else:
log(f"Clone failed returncode={p.returncode}")
# cleanup
try:
if Path(tmp).exists():
if Path(tmp).is_dir():
subprocess.run(f'rm -rf "{tmp}"', shell=True)
except Exception:
pass
return False
except Exception as e:
log(f"Clone error for {module}: {e}")
return False
def main():
p = argparse.ArgumentParser()
p.add_argument("--module", required=True)
p.add_argument("--repo", default=None)
args = p.parse_args()
module = args.module
repo = args.repo
log(f"fetcher invoked for module={module} repo={repo}")
if touched_recent(module):
log(f"Rate-limited: recently attempted fetch for {module}; skipping")
return
touch_stamp(module)
# prefer manager_sync
if run_manager_sync():
log("Triggered manager_sync; fetcher done")
return
# fallback: clone or pull the module repo
ok = clone_or_pull(module, repo_url=repo)
if ok:
log(f"Successfully fetched/updated module {module}")
else:
log(f"Failed to fetch/update module {module}; check logs and network")
if __name__ == "__main__":
main()