Jobsuche: Agent pro Benutzer in isoliertem Docker-Container
Jeder Suchlauf läuft nun in einem frischen Container pro Benutzer, dessen pro-Benutzer-Home als ~/.claude gemountet ist — Memories und Session-Contexte liegen damit strikt getrennt pro Benutzer. Die Such-Skills sind Shared-Code aus dem Image und werden im Container nur nach ~/.claude/skills verlinkt. Der Host-Runner startet pro Lauf `docker run --rm` und führt bis zu JOBSUCHE_MAX_PARALLEL (Default 4) Läufe parallel über verschiedene Benutzer aus (jeder hat eigenen Ollama-Key = getrennte Rate-Limits). Der alte gemeinsame ~/.claude-Pfad wird vom Runner nicht mehr beschrieben. - source/agent/: neues Agent-Image (Dockerfile + entrypoint + drei Skills) - scripts/jobsuche-runner.js: agentStarten als docker run, ensureAgentDir, runPool - scripts/jobsuche-runner.sh + bin/-Kopie: Image-Guard - package.json: docker:build-agent (lokal, ohne Registry-Push) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+63
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
# Helper for the Bewerbungs-Tracker REST-API.
|
||||
# Usage:
|
||||
# bt.sh GET /applications
|
||||
# bt.sh GET "/applications?status=Gesendet&limit=20"
|
||||
# bt.sh POST /applications '{"datum":"2026-07-03","firma":"ACME","stelle":"DevOps"}'
|
||||
# bt.sh PUT /applications/12 @/path/to/body.json
|
||||
# bt.sh DELETE /joboffers/5
|
||||
#
|
||||
# Config via env (with sensible defaults):
|
||||
# BEWERBUNG_API_URL base URL (default http://localhost:4327/api/v1)
|
||||
# BEWERBUNG_API_KEY API key (X-API-Key header)
|
||||
# BEWERBUNG_USER username whose key to use (default: admin)
|
||||
#
|
||||
# MULTI-USER: the tracker has one API key PER USER; the key decides whose data you
|
||||
# see and change. There is no global key any more. The old fallback (API_TOKEN from
|
||||
# /opt/jobbi-bewerbung/.env) is gone on purpose: it happened to hold the admin's
|
||||
# token, so it silently acted as admin — and it goes stale the moment a key is
|
||||
# rotated in the UI (Einstellungen -> "Neu generieren").
|
||||
#
|
||||
# Key resolution:
|
||||
# 1. $BEWERBUNG_API_KEY if set (this is what the Jobsuche-Runner passes per user)
|
||||
# 2. otherwise: look up the key of $BEWERBUNG_USER (default admin) in the tracker DB
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
BASE="${BEWERBUNG_API_URL:-http://localhost:4327/api/v1}"
|
||||
DB="${BEWERBUNG_DB:-/opt/jobbi-bewerbung/data/bewerbungen.db}"
|
||||
USER_NAME="${BEWERBUNG_USER:-admin}"
|
||||
KEY="${BEWERBUNG_API_KEY:-}"
|
||||
|
||||
if [[ -z "$KEY" && -f "$DB" ]]; then
|
||||
KEY="$(node -e "
|
||||
const s = require('/opt/jobbi-bewerbung/source/node_modules/sqlite3');
|
||||
const db = new s.Database(process.argv[1]);
|
||||
db.get(
|
||||
\"SELECT a.value FROM app_state a JOIN users u ON u.id = a.user_id \" +
|
||||
\"WHERE u.username = ? AND a.key = 'cfg:API_TOKEN' AND a.value != ''\",
|
||||
[process.argv[2]],
|
||||
(e, r) => process.stdout.write(r && r.value ? r.value : '')
|
||||
);
|
||||
" "$DB" "$USER_NAME" 2>/dev/null || true)"
|
||||
fi
|
||||
|
||||
if [[ -z "$KEY" ]]; then
|
||||
echo "bt.sh: kein API-Key für Benutzer '$USER_NAME'." >&2
|
||||
echo " -> In der App unter Einstellungen -> REST-API einen Token erzeugen," >&2
|
||||
echo " oder BEWERBUNG_API_KEY / BEWERBUNG_USER setzen." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
METHOD="${1:?method required (GET/POST/PUT/DELETE)}"
|
||||
PATH_ARG="${2:?path required, e.g. /applications}"
|
||||
BODY="${3:-}"
|
||||
|
||||
url="${BASE}${PATH_ARG}"
|
||||
args=(-sS -X "$METHOD" -H "X-API-Key: ${KEY}" -w $'\n<http %{http_code}>\n')
|
||||
|
||||
if [[ -n "$BODY" ]]; then
|
||||
args+=(-H "Content-Type: application/json" --data-binary "$BODY")
|
||||
fi
|
||||
|
||||
curl "${args[@]}" "$url"
|
||||
Reference in New Issue
Block a user