diff --git a/TOOLS.md b/TOOLS.md index 848e81e..f42d0d3 100644 --- a/TOOLS.md +++ b/TOOLS.md @@ -51,6 +51,69 @@ python3 tools/email_send.py "dest@email.com" "Subiect" "Corp mesaj" - **Repo:** ~/clawd → gitea.romfast.ro/romfast/clawd - **Commit script:** `python3 tools/git_commit.py --push` +### Docker LXC (portainer) +- **Host:** 10.0.20.170 (LXC 100 pe pvemini) +- **User:** echo +- **SSH:** `ssh echo@10.0.20.170` +- **Portainer:** https://10.0.20.170:9443 +- **Docker:** v28.3.3 + Compose v2.39.1 +- **Resurse:** 1GB RAM, 20GB disk (4.1GB folosit) +- **Proiecte:** `/opt/docker/` + +**Containere:** +| Container | Port | Status | Descriere | +|-----------|------|--------|-----------| +| portainer | 9443 | ✅ | Management Docker | +| nginx | 443, 8080 | ✅ | Reverse proxy | +| roa-efactura | 5003 | ⚠️ unhealthy | E-Factura ANAF | +| pdf-qr-app | 5002 | ✅ | QR facturi | +| flask_app | 5001 | ✅ | ROA Flask | +| bt-web-automation | 5000, 8081 | ✅ | BT automation | +| pulse | 7655 | ✅ | Monitoring Proxmox | +| wol-manager | - | ✅ | Wake-on-LAN | +| rustdesk (hbbs+hbbr) | 21115-21119 | ✅ | Remote desktop server | + +**Proiecte docker-compose:** +- `/opt/docker/docker-compose.yaml` - stack principal (nginx, flask, efactura, qr) +- `/opt/docker/wol/docker-compose.yml` - Wake-on-LAN +- `/opt/docker/qrinvoice/docker-compose.yml` - QR Invoice app + +### Proxmox Cluster (3 noduri) +**User:** echo | **Restricție:** doar din 10.0.20.173 (moltbot) | **Sudo:** qm, pct, pvesh + +#### pveelite (10.0.20.202) +- **Resurse:** 16GB RAM, 557GB disk +- **SSH:** `ssh echo@10.0.20.202` + +| VMID | Tip | Nume | Status | +|------|-----|------|--------| +| 109 | VM | oracle-dr-windows | stopped | +| 101 | LXC | minecraft | stopped | +| 110 | LXC | moltbot | running | +| 301 | LXC | docker-portainer-template | stopped | + +#### pvemini (10.0.20.201) +- **Resurse:** 64GB RAM, 1.4TB disk +- **SSH:** `ssh echo@10.0.20.201` + +| VMID | Tip | Nume | Status | +|------|-----|------|--------| +| 201 | VM | roacentral | running | +| 300 | VM | Win11-Template | stopped | +| 302 | VM | oracle-test-302 | stopped | +| 100 | LXC | portainer | running | +| 103 | LXC | dokploy | running | +| 104 | LXC | flowise | running | +| 105 | LXC | test | stopped | +| 106 | LXC | gitea | running | +| 108 | LXC | central-oracle | running | +| 171 | LXC | claude-agent | running | + +#### pve1 (10.0.20.200) +- **Resurse:** 32GB RAM, 1.3TB disk +- **SSH:** `ssh echo@10.0.20.200` +- **Status:** Gol (fără VM/LXC) + --- ## ⚡ Echo Work - Unelte specifice diff --git a/agents/echo-health/memory/provocare-azi.md b/agents/echo-health/memory/provocare-azi.md index 9177a80..094ff50 100644 --- a/agents/echo-health/memory/provocare-azi.md +++ b/agents/echo-health/memory/provocare-azi.md @@ -1,2 +1,2 @@ -TIP: Mișcare fizică / Pattern Interrupt -PROVOCARE: Ridică-te, fă 5 respirații adânci (inspiră 4 sec, expiră 6 sec), întinde-te (ridică brațele, deschide pieptul), mergi 2 minute oriunde. E resetare de stare prin corp - corpul nu știe să mintă. +TIP: Recunoștință / Priming seară +PROVOCARE: 3 minute înainte de somn - găsește 3 momente bune din zi și SIMTE-le (nu doar gândește). Unde în corp? Ce senzație? Antrenament de sistem nervos. diff --git a/agents/echo-work/memory/approved-tasks.md b/agents/echo-work/memory/approved-tasks.md new file mode 100644 index 0000000..39d3297 --- /dev/null +++ b/agents/echo-work/memory/approved-tasks.md @@ -0,0 +1,8 @@ +# Task-uri aprobate pentru execuție + +Acest fișier e populat de raportul de seară când Marius aprobă task-uri. +Job-ul night-execute (23:00) le execută și golește fișierul. + +--- + + diff --git a/agents/echo-work/memory/reguli-comunicare.md b/agents/echo-work/memory/reguli-comunicare.md index 96cf9e8..3b179b9 100644 --- a/agents/echo-work/memory/reguli-comunicare.md +++ b/agents/echo-work/memory/reguli-comunicare.md @@ -9,5 +9,20 @@ Când primesc mesaj de la alt agent (via sessions_send): Marius nu vede mesajele interne - trebuie să comunic transparent ce se întâmplă. +--- + +## Execuție task-uri + +**Din raportul de seară (job evening-report):** +- Aprobări ("ok X") → notez în `approved-tasks.md` +- Confirm: "✅ Notat pentru 23:00: [task-uri]" +- Job-ul `night-execute` (23:00) execută + +**Din conversație directă separată:** +- Dacă Marius cere explicit → execut imediat +- Dacă e continuare din raport → respectă fluxul 23:00 + +**NU amesteca contextele!** + --- *Adăugat: 2026-01-31* diff --git a/dashboard/api.py b/dashboard/api.py index 33891ad..b8805a5 100644 --- a/dashboard/api.py +++ b/dashboard/api.py @@ -108,6 +108,8 @@ class TaskBoardHandler(SimpleHTTPRequestHandler): self.handle_activity() elif self.path.startswith('/api/files'): self.handle_files_get() + elif self.path.startswith('/api/diff'): + self.handle_git_diff() elif self.path.startswith('/api/'): self.send_error(404) else: @@ -155,6 +157,14 @@ class TaskBoardHandler(SimpleHTTPRequestHandler): cwd=workspace, capture_output=True, text=True, timeout=5 ).stdout.strip() + # Parse uncommitted into structured format + uncommitted_parsed = [] + for line in uncommitted: + if len(line) >= 3: + status = line[:2].strip() + filepath = line[3:].strip() + uncommitted_parsed.append({'status': status, 'path': filepath}) + self.send_json({ 'branch': branch, 'lastCommit': { @@ -163,6 +173,7 @@ class TaskBoardHandler(SimpleHTTPRequestHandler): 'time': commit_parts[2] if len(commit_parts) > 2 else '' }, 'uncommitted': uncommitted, + 'uncommittedParsed': uncommitted_parsed, 'uncommittedCount': len(uncommitted), 'diffStat': diff_stat, 'clean': len(uncommitted) == 0 @@ -170,6 +181,60 @@ class TaskBoardHandler(SimpleHTTPRequestHandler): except Exception as e: self.send_json({'error': str(e)}, 500) + def handle_git_diff(self): + """Get git diff for a specific file.""" + from urllib.parse import urlparse, parse_qs + parsed = urlparse(self.path) + params = parse_qs(parsed.query) + + filepath = params.get('path', [''])[0] + + if not filepath: + self.send_json({'error': 'path required'}, 400) + return + + try: + workspace = Path('/home/moltbot/clawd') + + # Security check + target = (workspace / filepath).resolve() + if not str(target).startswith(str(workspace)): + self.send_json({'error': 'Access denied'}, 403) + return + + # Get diff (try staged first, then unstaged) + diff = subprocess.run( + ['git', 'diff', '--cached', '--', filepath], + cwd=workspace, capture_output=True, text=True, timeout=10 + ).stdout + + if not diff: + diff = subprocess.run( + ['git', 'diff', '--', filepath], + cwd=workspace, capture_output=True, text=True, timeout=10 + ).stdout + + # If still no diff, file might be untracked - show full content + if not diff: + status = subprocess.run( + ['git', 'status', '--short', '--', filepath], + cwd=workspace, capture_output=True, text=True, timeout=5 + ).stdout.strip() + + if status.startswith('??'): + # Untracked file - show as new + if target.exists(): + content = target.read_text(encoding='utf-8', errors='replace')[:50000] + diff = f"+++ b/{filepath}\n" + '\n'.join(f'+{line}' for line in content.split('\n')) + + self.send_json({ + 'path': filepath, + 'diff': diff or 'No changes', + 'hasDiff': bool(diff) + }) + except Exception as e: + self.send_json({'error': str(e)}, 500) + def handle_agents_status(self): """Get agents status - fast version reading session files directly.""" try: @@ -361,11 +426,44 @@ class TaskBoardHandler(SimpleHTTPRequestHandler): 'text': message[:60] + ('...' if len(message) > 60 else ''), 'agent': 'git', 'time': local_time.strftime('%H:%M'), - 'timestamp': timestamp * 1000 + 'timestamp': timestamp * 1000, + 'commitHash': commit_hash[:8] }) except: pass + # 2b. Git uncommitted files + try: + result = subprocess.run( + ['git', 'status', '--short'], + cwd=workspace, capture_output=True, text=True, timeout=10 + ) + if result.returncode == 0 and result.stdout.strip(): + for line in result.stdout.strip().split('\n'): + if len(line) >= 4: + # Git status format: XY filename (XY = 2 chars status) + # Handle both "M " and " M" formats + status = line[:2] + # Find filepath - skip status chars and any spaces + filepath = line[2:].lstrip() + if not filepath: + continue + status_clean = status.strip() + status_labels = {'M': 'modificat', 'A': 'adăugat', 'D': 'șters', '??': 'nou', 'R': 'redenumit'} + status_label = status_labels.get(status_clean, status_clean) + activities.append({ + 'type': 'git-file', + 'icon': 'file-diff', + 'text': f"{filepath}", + 'agent': f"git ({status_label})", + 'time': 'acum', + 'timestamp': int(datetime.now().timestamp() * 1000), + 'path': filepath, + 'gitStatus': status_clean + }) + except: + pass + # 3. Recent files in kb/ (last 24h) try: kb_dir = workspace / 'kb' diff --git a/dashboard/favicon.svg b/dashboard/favicon.svg new file mode 100644 index 0000000..9fac3a0 --- /dev/null +++ b/dashboard/favicon.svg @@ -0,0 +1,4 @@ + diff --git a/dashboard/files.html b/dashboard/files.html index cb51d86..33c4509 100644 --- a/dashboard/files.html +++ b/dashboard/files.html @@ -3,6 +3,7 @@
+