Files
jobbi-bewerbung/scripts/jobsuche-runner.sh
T
thomasandClaude Opus 4.8 9418750061 Jobsuche als Feature der App: Suchprofil pro Benutzer statt Cron-Prompt
Die Jobsuche lag in zwei Host-Skripten (jobsuche-cron.sh, jobsuche-remote-cron.sh)
aus der Ein-Benutzer-Zeit: Die Suchkriterien (sieben Staedte, Rollen, Buzzwords)
standen fest im Prompt, und importiert wurde mit EINEM globalen API-Token aus der
.env - der zufaellig dem Admin gehoerte. Auf der Multi-User-Plattform ist beides
hinfaellig.

Jetzt legt jeder Benutzer sein Suchprofil selbst fest (/jobsuche):
- Modus: regional / 100 % Remote / beides
- Staedte (die erste gilt als Wohnort und wird hoechstpriorisiert, max. 12)
- Feinschliff: zusaetzliche Begriffe, Ausschluesse
- Zeitplan: Wochentage + Uhrzeit, plus Button "Jetzt suchen"
Rollen und Technologien bleiben abgeleitet - aus dem Lebenslauf des Benutzers
(basis_dokumente), nicht aus einer gepflegten Liste. Admins koennen Profil und
Zeitplan eines Benutzers ueber /jobsuche?user=<id> mitpflegen (Link im Admin-Panel).

Aufteilung App/Host: Der Container hat weder claude noch ollama. Die App reiht
Laeufe daher nur in die Warteschlange ein (Tabelle suchlaeufe); der neue Runner
auf dem Host (scripts/jobsuche-runner.js, Cron alle 5 Min) arbeitet sie ab, baut
den Prompt je Benutzer aus dessen Profil + Lebenslauf und laeuft mit DESSEN
Zugangsdaten:
- BEWERBUNG_API_KEY = eigener API-Token des Benutzers (wird beim ersten Lauf
  automatisch erzeugt), damit Treffer im richtigen Konto landen und durch dieselbe
  Dedup-/Blacklist-Logik gehen,
- ANTHROPIC_BASE_URL/AUTH_TOKEN = eigener Ollama-Key des Benutzers ueber die
  Anthropic-kompatible Schnittstelle von Ollama Cloud (https://ollama.com/v1/messages,
  verifiziert: gueltiger Key -> 200, ungueltiger -> 401). Damit zahlt jeder seine
  eigene Suche, statt alles ueber die Host-Subscription zu buchen
  (JOBSUCHE_KI_AUTH=host stellt das alte Verhalten wieder her).

Ohne eigenen Ollama-Key oder ohne Lebenslauf bricht der Lauf mit klarer Meldung ab
statt still nichts zu tun; die Oberflaeche warnt vorab. Kein Stapeln: solange ein
Lauf offen ist, erzeugt ein weiterer Klick keinen zweiten. Verwaiste Laeufe
(Prozess weg) werden nach Zeitlimit als Fehler freigegeben.

Verifiziert mit zwei Benutzern: Zugriffsschutz (fremdes Profil -> 403), Speichern,
Warteschlange, automatische Key-Erzeugung, Prompt-Aufbau aus Profil + CV,
Ergebnis-Ruecklauf in die Oberflaeche, Fehlerpfade und die Faelligkeitslogik des
Zeitplans (Tag/Uhrzeit/bereits gelaufen).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 23:28:56 +02:00

59 lines
2.0 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Cron-Einstiegspunkt für die Jobsuche (Multi-User).
#
# Ersetzt jobsuche-cron.sh + jobsuche-remote-cron.sh: Diese beiden hatten das
# Suchprofil (sieben Städte, Rollen, Buzzwords) fest im Prompt stehen und liefen
# mit EINEM globalen API-Token aus der .env — beides ist mit der Multi-User-
# Plattform hinfällig.
#
# Jetzt: Jeder Benutzer pflegt sein Suchprofil und seinen Zeitplan in der App
# (/jobsuche). Dieses Skript ruft nur noch den Runner auf, der fällige und manuell
# angeforderte Läufe abarbeitet — je Benutzer mit dessen eigenem Ollama- und
# API-Schlüssel.
#
# Cron (alle 5 Minuten — die Uhrzeit steuert der Benutzer, nicht der Cron):
# */5 * * * * /opt/jobbi-bewerbung/bin/jobsuche-runner.sh
#
# Manueller Lauf: /opt/jobbi-bewerbung/bin/jobsuche-runner.sh
set -uo pipefail
export HOME="${HOME:-/root}"
export PATH="/root/.local/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
# Claude Code verweigert --dangerously-skip-permissions als root; in dieser
# Container-/Sandbox-Umgebung mit IS_SANDBOX=1 erlaubt.
export IS_SANDBOX=1
PROJECT_DIR="/opt/jobbi-bewerbung"
LOG_DIR="$PROJECT_DIR/logs"
RUNNER="$PROJECT_DIR/source/scripts/jobsuche-runner.js"
mkdir -p "$LOG_DIR"
LOG="$LOG_DIR/jobsuche-runner.log"
# Einzelinstanz: ein noch laufender Suchlauf darf vom nächsten Cron-Tick nicht
# ein zweites Mal gestartet werden.
exec 9>"$LOG_DIR/jobsuche-runner.lock"
if ! flock -n 9; then
exit 0
fi
cd "$PROJECT_DIR" || exit 1
# API-Erreichbarkeit prüfen — ohne den Tracker kann der Agent nichts importieren.
if ! curl -fsS --max-time 10 http://localhost:4327/api/v1/health >/dev/null 2>&1; then
echo "$(date -Is) FEHLER: Bewerbungs-Tracker (localhost:4327) nicht erreichbar Lauf übersprungen." >> "$LOG"
exit 1
fi
node "$RUNNER" >> "$LOG" 2>&1
STATUS=$?
# Log der Runner-Steuerung kurz halten (die eigentlichen Suchlauf-Logs liegen
# je Lauf separat und werden vom Runner selbst rotiert).
if [ -f "$LOG" ] && [ "$(wc -l < "$LOG")" -gt 5000 ]; then
tail -n 2000 "$LOG" > "$LOG.tmp" && mv "$LOG.tmp" "$LOG"
fi
exit $STATUS