From e3c18f15ed9e77909245e03335d7e0cb89a314df Mon Sep 17 00:00:00 2001 From: Marius Mutu Date: Wed, 29 Apr 2026 20:13:54 +0000 Subject: [PATCH] chore: auto-commit from dashboard --- cron/jobs.json | 4 +- dashboard/notes.html | 1 + memory/kb/index.json | 43 ++++++++++------- scripts/transcribe_video.sh | 94 +++++++++++++++++++++++++++++++++++-- tasks/lessons.md | 7 +++ 5 files changed, 124 insertions(+), 25 deletions(-) diff --git a/cron/jobs.json b/cron/jobs.json index 556e027..057c65d 100644 --- a/cron/jobs.json +++ b/cron/jobs.json @@ -269,9 +269,9 @@ "prompt": "Heartbeat check. Rulează src/heartbeat.py printr-un scurt raport de status.\nDacă nu e nimic de raportat (email=0, calendar nu are evenimente <2h, kb ok), răspunde doar cu HEARTBEAT_OK și oprește-te — nu trimite mesaj.\nDacă e ceva: raport scurt pe Discord #echo-work.", "allowed_tools": [], "enabled": true, - "last_run": "2026-04-29T16:00:00.003223+00:00", + "last_run": "2026-04-29T18:00:00.001439+00:00", "last_status": "ok", - "next_run": "2026-04-29T18:00:00+00:00" + "next_run": "2026-04-30T06:00:00+00:00" }, { "name": "night-execute", diff --git a/dashboard/notes.html b/dashboard/notes.html index cc7fd75..11e9071 100644 --- a/dashboard/notes.html +++ b/dashboard/notes.html @@ -1128,6 +1128,7 @@ } function renderNoteCard(note) { + if (!note.file) return ''; // Domains (portocaliu), Types (mov), Tags colapsate cu expand const tags = note.tags || []; const noteId = note.file.replace(/[^a-zA-Z0-9]/g, '_'); diff --git a/memory/kb/index.json b/memory/kb/index.json index 9ce5dfb..1721b8b 100644 --- a/memory/kb/index.json +++ b/memory/kb/index.json @@ -1,5 +1,25 @@ { "notes": [ + { + "file": "notes-data/facebook/2026-04-29_julien-blanc-love-yourself.md", + "title": "Love Yourself Even If They Don't", + "date": "2026-04-29", + "tags": [ + "self-love", + "self-esteem", + "social-approval", + "mindset" + ], + "domains": [], + "types": [ + "coaching" + ], + "category": "facebook", + "project": null, + "subdir": null, + "video": "", + "tldr": "Julien Blanc face un exercițiu pe stradă: îl întreabă pe un trecător care e artistul lui preferat. Răspunsul: Glenn Gould. Nimeni din grup nu știa cine e, apoi toți l-au criticat. Întrebarea lui Julie..." + }, { "file": "notes-data/youtube/2026-04-29_ternary-models-local-ai.md", "title": "I Just Tried The Brand New Ternary Model And It's Great!", @@ -8559,8 +8579,8 @@ "title": "Proiect: Vending Master - Integrare Website → ROA", "date": "2026-01-30", "tags": [ - "integrare", - "vending-master" + "vending-master", + "integrare" ], "domains": [ "work" @@ -9037,21 +9057,6 @@ "subdir": null, "video": "", "tldr": "Tutorial complet pentru a vorbi cu Claude Code prin telefon, folosind 3CX (sistem telefonic cloud gratuit) + un proiect GitHub custom. Setup-ul implică: 3CX cloud (gratuit, <10 useri), un voice server..." - }, - { - "id": "facebook/2026-04-29_julien-blanc-love-yourself", - "title": "Love Yourself Even If They Don't — Julien Blanc", - "path": "memory/kb/facebook/2026-04-29_julien-blanc-love-yourself.md", - "date": "2026-04-29", - "tags": [ - "coaching", - "self-love", - "self-esteem", - "social-approval", - "mindset" - ], - "source": "facebook-reel", - "creator": "Julien Blanc" } ], "stats": { @@ -9069,6 +9074,7 @@ "conversations": 0, "emails": 18, "exercitii": 4, + "facebook": 1, "health": 6, "insights": 46, "projects": 233, @@ -9103,6 +9109,7 @@ "conversations", "emails", "exercitii", + "facebook", "health", "insights", "projects", @@ -9112,4 +9119,4 @@ "youtube", "memory" ] -} +} \ No newline at end of file diff --git a/scripts/transcribe_video.sh b/scripts/transcribe_video.sh index 74c9a86..156c6ed 100755 --- a/scripts/transcribe_video.sh +++ b/scripts/transcribe_video.sh @@ -1,18 +1,31 @@ #!/usr/bin/env bash # Descarcă un video (Facebook, YouTube etc.), extrage audio, transcrie cu Whisper. # Usage: ./transcribe_video.sh [language] +# ./transcribe_video.sh [language] --save-kb # Exemple: # ./transcribe_video.sh "https://www.facebook.com/share/v/1EdPt3q2sq/" +# ./transcribe_video.sh "https://www.facebook.com/share/r/1akfPJYvTw/" ro --save-kb # ./transcribe_video.sh "https://youtu.be/xyz" ro set -euo pipefail URL="${1:-}" LANG="${2:-en}" +SAVE_KB=0 + +# Parse flags +for arg in "$@"; do + if [[ "$arg" == "--save-kb" ]]; then + SAVE_KB=1 + fi +done + WORKDIR="/tmp/transcribe_$$" +PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +KB_DIR="$PROJECT_ROOT/memory/kb" if [[ -z "$URL" ]]; then - echo "Usage: $0 [language (default: en)]" + echo "Usage: $0 [language (default: en)] [--save-kb]" exit 1 fi @@ -21,7 +34,13 @@ export PATH="/home/moltbot/bin:$PATH" mkdir -p "$WORKDIR" trap 'rm -rf "$WORKDIR"' EXIT -echo "→ Descarc video..." +echo "→ Obțin informații video..." +INFO_JSON=$(yt-dlp "$URL" --dump-json --no-download -q 2>/dev/null || echo "{}") +TITLE=$(echo "$INFO_JSON" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('title','Unknown'))" 2>/dev/null || echo "Unknown") +CREATOR=$(echo "$INFO_JSON" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('uploader') or d.get('channel') or '')" 2>/dev/null || echo "") +DURATION=$(echo "$INFO_JSON" | python3 -c "import json,sys; d=json.load(sys.stdin); s=d.get('duration',0); print(f'{s//60}:{s%60:02d}')" 2>/dev/null || echo "?") + +echo "→ Descarc video: $TITLE..." yt-dlp "$URL" -o "$WORKDIR/video.%(ext)s" --no-playlist -q VIDEO_FILE=$(ls "$WORKDIR"/video.* 2>/dev/null | head -1) @@ -34,12 +53,77 @@ echo "→ Extrag audio..." ffmpeg -i "$VIDEO_FILE" -vn -acodec pcm_s16le -ar 16000 -ac 1 "$WORKDIR/audio.wav" -y -loglevel error echo "→ Transcriu cu Whisper (model: small, limbă: $LANG)..." -python3 -c " +TRANSCRIPT=$(python3 -c " import whisper model = whisper.load_model('small') result = model.transcribe('$WORKDIR/audio.wav', language='$LANG') print(result['text']) -" 2>/dev/null +" 2>/dev/null) echo "" -echo "✓ Gata." +echo "=== $TITLE ===" +echo "$TRANSCRIPT" +echo "" +echo "✓ Transcriere completă." + +if [[ "$SAVE_KB" == "1" ]]; then + DATE=$(date +%Y-%m-%d) + + # Slug din titlu: lowercase, fără diacritice, doar alfanumerice și cratime + SLUG=$(echo "$TITLE" | python3 -c " +import sys, re, unicodedata +s = sys.stdin.read().strip() +s = unicodedata.normalize('NFD', s) +s = ''.join(c for c in s if unicodedata.category(c) != 'Mn') +s = s.lower() +s = re.sub(r'[^a-z0-9]+', '-', s) +s = s.strip('-')[:50] +print(s) +") + + # Detectează categoria din URL + if echo "$URL" | grep -qi "facebook\.com"; then + CATEGORY="facebook" + FORMAT="Reel (~${DURATION} min)" + elif echo "$URL" | grep -qi "youtube\.com\|youtu\.be"; then + CATEGORY="youtube" + FORMAT="Video (~${DURATION} min)" + else + CATEGORY="media" + FORMAT="Video (~${DURATION} min)" + fi + + NOTE_DIR="$KB_DIR/$CATEGORY" + mkdir -p "$NOTE_DIR" + NOTE_FILE="$NOTE_DIR/${DATE}_${SLUG}.md" + + cat > "$NOTE_FILE" << NOTEEOF +# $TITLE + +**Sursa:** $URL +**Data:** $DATE +**Creator:** $CREATOR +**Format:** $FORMAT +**Tags:** @coaching + +--- + +## TL;DR + + + +--- + +## Transcrierea + +$TRANSCRIPT +NOTEEOF + + echo "" + echo "→ Notiță salvată: $NOTE_FILE" + + echo "→ Reindexez KB..." + python3 "$PROJECT_ROOT/tools/update_notes_index.py" + + echo "✓ KB actualizat. Link: /echo/files.html#memory/kb/$CATEGORY/${DATE}_${SLUG}.md" +fi diff --git a/tasks/lessons.md b/tasks/lessons.md index c5e309c..6cd5ae6 100644 --- a/tasks/lessons.md +++ b/tasks/lessons.md @@ -16,3 +16,10 @@ Lecții capturate din corectările lui Marius. Citește acest fișier la începu --- + +## Nu scrie manual în index.json — rulează update_notes_index.py +**Data:** 2026-04-29 +**Context:** Salvam o notiță din Facebook reel în memory/kb/. Am adăugat manual o intrare în index.json cu schema greșită (`id` + `path` în loc de `file`), ceea ce a blocat notes.html pe "Se încarcă..." cu un TypeError în renderNoteCard. +**Greșeala:** Am editat index.json direct, cu o schemă diferită față de ce produce update_notes_index.py. +**Regula:** Niciodată nu scriei manual în `memory/kb/index.json`. Fluxul corect: (1) creezi fișierul `.md` în `memory/kb//`, (2) rulezi `python3 tools/update_notes_index.py`. Dacă ai nevoie să salvezi o notiță din Facebook/video, folosești `scripts/transcribe_video.sh --save-kb` care face totul corect. +**Când se aplică:** Orice salvare de notiță în KB (Facebook, YouTube, coaching, insights, orice). Dacă ești tentat să `json.dump` în index.json — stop, rulează scriptul.