Doua lucruri cerute de utilizator, ambele pe acelasi drum: sa poti lega
puntea fara sa ai un ecran de scanat, si sa poti trimite Mariei o poza cu
eroarea in loc sa transcrii mesajul.
Asociere prin cod de 8 caractere (alternativa la QR):
- endpoint-ul /pair exista, dar nu era folosibil: fara `browser` explicit
WhatsApp refuza codul, iar dupa introducerea lui corecta serverul cere un
restart (515) care consuma din bugetul de reincercari si putea opri puntea.
Acum descriptorul e Browsers.ubuntu('Chrome') si restartRequired reconecteaza
imediat, fara sa numere.
- codul are TTL de 3 minute, iar /status il da doar cat timp e valabil —
un cod expirat afisat in dashboard trimite omul sa tasteze degeaba.
- dashboard: camp pentru numar + buton, in acelasi card cu QR-ul.
Imagini cu erori (capturi de ecran):
- puntea descarca imaginile in ~/.maria-bridge/media/ (imageMessage sau
document cu mimetype image/*, si prin ambalajele efemer/"vezi o data" —
fara despachetare pareau mesaje fara continut si se aruncau tacut).
- rag/ocr.py: tesseract ron+eng. Modelul de raspuns e strict text, deci OCR
nu e o optiune de calitate, e singura cale.
- cautarea in index merge DOAR pe liniile care arata a eroare; o fereastra
intreaga de meniuri si totaluri dilueaza embedding-ul si scoate chunk-uri
fara legatura. Modelul primeste captura intreaga, marcata ca text OCR.
- capturile se sterg imediat dupa citire (pot contine date de client).
- cand nu se citeste nimic si nu exista legenda, Maria cere textul erorii
in loc sa raspunda in gol.
16 teste noi (42 in total). install.sh verifica tesseract; README documenteaza
ambele metode de asociere si drumul unei capturi.
Separat, in docs/chatboti-si-punti.md: chatul "Eu" e vazut de AMBELE punti de pe
numar. Puntea lui Echo (LXC 110) e asociata ca dispozitiv :11 al aceluiasi cont,
momentan nelegata dar pornita — daca se reasociaza, raspunde in "Eu" langa Maria.
Notat si ca serviciile lui Echo sunt unitati de UTILIZATOR: `systemctl is-active`
ca root raspunde "inactive" desi botul ruleaza.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4uzvgm7AyJch5WH8QHRhY
166 lines
7.3 KiB
Bash
Executable File
166 lines
7.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# install.sh — instaleaza puntea WhatsApp+RAG a lui Maria pe LXC 171 (claude-agent).
|
|
#
|
|
# IDEMPOTENT: se poate rula de cate ori vrei. Nu suprascrie niciodata
|
|
# ~/.maria-bridge/env (acolo sta configuratia completata de om).
|
|
#
|
|
# ./ops/install.sh # instaleaza / actualizeaza, NU porneste serviciile
|
|
# ./ops/install.sh --start # in plus porneste bridge+rag (bridge cere QR scanat)
|
|
#
|
|
# Controlul (start/stop/restart, documente, reindexare, sincronizare Drive) se
|
|
# face din dashboard-ul PUNTII DISCORD (discord-bridge/dashboard/), sectiunea
|
|
# "Maria — WhatsApp + RAG" — decizie deliberata: un singur panou comun, nu un
|
|
# dashboard separat per serviciu. Vezi discord-bridge/README.md.
|
|
#
|
|
# Ce face:
|
|
# 1. ~/.maria-bridge/ cu 0700, subdirectoare (logs/, documents/, whatsapp-auth/)
|
|
# 2. env 0600 din ops/env.example (doar daca lipseste)
|
|
# 3. npm install pentru whatsapp/ (Baileys)
|
|
# 4. venv + pip install pentru rag/requirements.txt
|
|
# 5. loginctl enable-linger (serviciile de utilizator supravietuiesc logout-ului)
|
|
# 6. symlink-uri unit -> ~/.config/systemd/user/ (bridge, rag, timer sync)
|
|
# 7. systemd-analyze verify + enable
|
|
set -uo pipefail
|
|
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
SRC="$(dirname "$HERE")" # .../maria-whatsapp-bridge
|
|
STATE_DIR="$HOME/.maria-bridge"
|
|
UNIT_DIR="$HOME/.config/systemd/user"
|
|
UNITS=(maria-whatsapp.service maria-rag.service maria-sync.service maria-sync.timer)
|
|
DO_START=0
|
|
[ "${1:-}" = "--start" ] && DO_START=1
|
|
|
|
info() { printf ' \033[32m*\033[0m %s\n' "$*"; }
|
|
warn() { printf ' \033[33m!\033[0m %s\n' "$*"; }
|
|
die() { printf ' \033[31mX\033[0m %s\n' "$*" >&2; exit 1; }
|
|
|
|
[ "$(id -u)" -eq 0 ] && die "NU rula ca root. Serviciile Maria sunt servicii de utilizator (claude)."
|
|
|
|
echo "== Punte WhatsApp+RAG Maria: instalare =="
|
|
echo " sursa: $SRC"
|
|
|
|
# --- 1. director de stare --------------------------------------------------
|
|
mkdir -p "$STATE_DIR/logs" "$STATE_DIR/documents" "$STATE_DIR/whatsapp-auth"
|
|
chmod 0700 "$STATE_DIR"
|
|
info "director de stare: $STATE_DIR (0700)"
|
|
|
|
# --- 2. env ----------------------------------------------------------------
|
|
if [ -f "$STATE_DIR/env" ]; then
|
|
chmod 0600 "$STATE_DIR/env"
|
|
info "env exista deja, nu se atinge"
|
|
else
|
|
cp "$HERE/env.example" "$STATE_DIR/env"
|
|
chmod 0600 "$STATE_DIR/env"
|
|
info "env creat din env.example (0600) — completeaza LLM_URL/DRIVE_REMOTE dupa caz"
|
|
fi
|
|
|
|
# --- 3. dependinte Node (whatsapp/) -----------------------------------------
|
|
if command -v npm >/dev/null 2>&1; then
|
|
if [ -d "$SRC/whatsapp/node_modules" ]; then
|
|
info "node_modules exista deja in whatsapp/"
|
|
else
|
|
(cd "$SRC/whatsapp" && npm install --omit=dev) \
|
|
&& info "npm install: gata (Baileys si dependinte)" \
|
|
|| warn "npm install a esuat (retea?) — reia cu: cd $SRC/whatsapp && npm install"
|
|
fi
|
|
else
|
|
warn "npm lipseste din PATH — instaleaza Node (nvm) inainte de a porni puntea"
|
|
fi
|
|
|
|
# --- 4. venv + dependinte Python (rag/) -------------------------------------
|
|
if [ ! -x "$STATE_DIR/venv/bin/python" ]; then
|
|
python3 -m venv "$STATE_DIR/venv" || die "crearea venv a esuat"
|
|
info "venv creat: $STATE_DIR/venv"
|
|
else
|
|
info "venv exista deja"
|
|
fi
|
|
"$STATE_DIR/venv/bin/python" -m pip install --quiet --upgrade pip >/dev/null 2>&1
|
|
if "$STATE_DIR/venv/bin/python" -m pip install --quiet -r "$SRC/rag/requirements.txt"; then
|
|
info "dependinte Python instalate din rag/requirements.txt"
|
|
else
|
|
warn "instalarea dependintelor Python a esuat (retea?) — reia cu: $STATE_DIR/venv/bin/pip install -r $SRC/rag/requirements.txt"
|
|
fi
|
|
|
|
# --- 5. linger ---------------------------------------------------------------
|
|
if [ "$(loginctl show-user "$USER" -p Linger --value 2>/dev/null)" = "yes" ]; then
|
|
info "linger deja activ pentru $USER"
|
|
else
|
|
if loginctl enable-linger "$USER" 2>/dev/null; then
|
|
info "linger activat pentru $USER"
|
|
elif sudo -n loginctl enable-linger "$USER" 2>/dev/null; then
|
|
info "linger activat pentru $USER (prin sudo)"
|
|
else
|
|
warn "nu am putut activa linger; ruleaza manual: sudo loginctl enable-linger $USER"
|
|
fi
|
|
fi
|
|
|
|
# --- 6. unit-uri -------------------------------------------------------------
|
|
mkdir -p "$UNIT_DIR"
|
|
for u in "${UNITS[@]}"; do
|
|
ln -sfn "$HERE/$u" "$UNIT_DIR/$u"
|
|
info "unit legat: $UNIT_DIR/$u -> $HERE/$u"
|
|
done
|
|
|
|
systemctl --user daemon-reload 2>/dev/null || warn "daemon-reload a esuat (sesiune fara systemd de utilizator?)"
|
|
|
|
if systemd-analyze verify "$UNIT_DIR/maria-whatsapp.service" 2>&1 | grep -vE 'Unknown key|^$' | grep -q .; then
|
|
systemd-analyze verify "$UNIT_DIR/maria-whatsapp.service" 2>&1 | sed 's/^/ /'
|
|
warn "systemd-analyze verify a raportat probleme (vezi mai sus)"
|
|
else
|
|
info "systemd-analyze verify: curat"
|
|
fi
|
|
|
|
# --- 7. rclone (optional, pentru sincronizare Drive) ------------------------
|
|
if command -v rclone >/dev/null 2>&1; then
|
|
info "rclone gasit: $(command -v rclone)"
|
|
if ! grep -qE '^DRIVE_REMOTE=.+' "$STATE_DIR/env" 2>/dev/null; then
|
|
warn "DRIVE_REMOTE necompletat — sincronizarea cu Google Drive ramane dezactivata"
|
|
warn "vezi README.md, sectiunea 'Sincronizare cu Google Drive'"
|
|
fi
|
|
else
|
|
warn "rclone nu e instalat — sincronizarea automata cu Google Drive nu va functiona"
|
|
warn "instaleaza cu: sudo apt-get install -y rclone (apoi vezi README.md)"
|
|
fi
|
|
|
|
# --- 7b. tesseract (OCR pentru capturile de ecran primite) -------------------
|
|
# Fara el, Maria raspunde in continuare la text, dar la o captura cu eroare
|
|
# raspunde ca nu poate citi imaginea. Vezi rag/ocr.py.
|
|
if command -v tesseract >/dev/null 2>&1; then
|
|
if tesseract --list-langs 2>/dev/null | grep -qx ron; then
|
|
info "tesseract gasit, cu limba romana"
|
|
else
|
|
warn "tesseract nu are pachetul de limba romana (ron) — OCR-ul va fi mai slab"
|
|
warn "instaleaza cu: sudo apt-get install -y tesseract-ocr-ron"
|
|
fi
|
|
else
|
|
warn "tesseract nu e instalat — capturile de ecran primite pe WhatsApp nu pot fi citite"
|
|
warn "instaleaza cu: sudo apt-get install -y tesseract-ocr tesseract-ocr-ron"
|
|
fi
|
|
|
|
# --- 8. enable / start -------------------------------------------------------
|
|
for u in maria-whatsapp.service maria-rag.service; do
|
|
systemctl --user enable "$u" >/dev/null 2>&1 \
|
|
&& info "$u enabled (porneste la boot)" \
|
|
|| warn "enable pentru $u a esuat"
|
|
done
|
|
systemctl --user enable --now maria-sync.timer >/dev/null 2>&1 \
|
|
&& info "timer de sincronizare Drive activat (la fiecare 10 min)" \
|
|
|| warn "enable pentru maria-sync.timer a esuat"
|
|
|
|
if [ "$DO_START" -eq 1 ]; then
|
|
systemctl --user restart maria-whatsapp.service && info "punte WhatsApp pornita"
|
|
echo
|
|
echo " Deschide dashboard-ul puntii Discord (sectiunea 'Maria — WhatsApp + RAG')"
|
|
echo " si asociaza WhatsApp din cardul 'Conectare WhatsApp' inainte sa pornesti"
|
|
echo " maria-rag: fie scanezi codul QR, fie ceri un cod de asociere pentru numar."
|
|
systemctl --user restart maria-rag.service && info "consumer RAG pornit"
|
|
systemctl --user --no-pager status maria-whatsapp.service | sed 's/^/ /'
|
|
else
|
|
echo
|
|
echo " Serviciile bridge/rag NU au fost pornite (intentionat: bridge-ul cere"
|
|
echo " asocierea WhatsApp — cod QR sau cod de asociere — actiune manuala)."
|
|
echo " Dupa ce completezi $STATE_DIR/env: $0 --start"
|
|
fi
|
|
|
|
echo "== gata =="
|