refactor: auto-detect headless mode via TTY; AUTO_MODE becomes an override
The primary use case is headless Docker, so auto mode is now the default whenever stdin has no TTY. Interactive mode activates when a terminal is present (docker run -it, local shell). AUTO_MODE=true remains as an explicit override for scripting with a pseudo-TTY. Removes AUTO_MODE=true, stdin_open, tty, and FORCE_CPU=false from compose.yml — none are needed for headless operation. Updates README and the interactive-mode hint in the CLI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -128,7 +128,6 @@ services:
|
|||||||
- IMMICH_URL=http://192.168.1.10:2283
|
- IMMICH_URL=http://192.168.1.10:2283
|
||||||
- API_KEY=your-immich-api-key
|
- API_KEY=your-immich-api-key
|
||||||
- FRIGATE_URL=http://192.168.1.10:5000
|
- FRIGATE_URL=http://192.168.1.10:5000
|
||||||
- AUTO_MODE=true
|
|
||||||
- CRON_SCHEDULE=0 3 * * 0 # Every Sunday at 3 AM
|
- CRON_SCHEDULE=0 3 * * 0 # Every Sunday at 3 AM
|
||||||
volumes:
|
volumes:
|
||||||
- /path/to/models:/models
|
- /path/to/models:/models
|
||||||
@@ -161,7 +160,7 @@ The first run after a fresh install downloads the embedding models (~1-2 GB). Su
|
|||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
| :--- | :--- | :--- |
|
| :--- | :--- | :--- |
|
||||||
| `AUTO_MODE` | `false` | Run without interactive prompts — required for Docker/cron use |
|
| `AUTO_MODE` | *(auto)* | Force non-interactive mode even in a terminal; auto-detected otherwise (no TTY = auto) |
|
||||||
| `TRAINING_MODE` | `face` | `face` — upload crops to Frigate API; `object` — save crops to disk |
|
| `TRAINING_MODE` | `face` | `face` — upload crops to Frigate API; `object` — save crops to disk |
|
||||||
| `STRATEGY` | `auto` | `auto` (adaptive), `standard` (30 images), `broad` (100 images) |
|
| `STRATEGY` | `auto` | `auto` (adaptive), `standard` (30 images), `broad` (100 images) |
|
||||||
| `LIMIT` | *(unset)* | Exact image count — overrides `STRATEGY` |
|
| `LIMIT` | *(unset)* | Exact image count — overrides `STRATEGY` |
|
||||||
|
|||||||
+4
-4
@@ -9,7 +9,9 @@ services:
|
|||||||
- FRIGATE_URL=${FRIGATE_URL}
|
- FRIGATE_URL=${FRIGATE_URL}
|
||||||
|
|
||||||
# ── Mode & Strategy ───────────────────────────────────────────────────
|
# ── Mode & Strategy ───────────────────────────────────────────────────
|
||||||
- AUTO_MODE=true
|
# Auto mode is active by default when no TTY is present (Docker/cron).
|
||||||
|
# Run with `docker run -it` or set AUTO_MODE=true to force non-interactive
|
||||||
|
# in a terminal.
|
||||||
# TRAINING_MODE: face = upload to Frigate face recognition API
|
# TRAINING_MODE: face = upload to Frigate face recognition API
|
||||||
# object = save crops to output dir for manual Frigate placement
|
# object = save crops to output dir for manual Frigate placement
|
||||||
- TRAINING_MODE=face
|
- TRAINING_MODE=face
|
||||||
@@ -34,7 +36,7 @@ services:
|
|||||||
# - MAX_AUTO_IMAGES=80 # Hard cap on auto-diversity selection (default: 80)
|
# - MAX_AUTO_IMAGES=80 # Hard cap on auto-diversity selection (default: 80)
|
||||||
|
|
||||||
# ── Caching & Models ──────────────────────────────────────────────────
|
# ── Caching & Models ──────────────────────────────────────────────────
|
||||||
- FORCE_CPU=false
|
# - FORCE_CPU=true # Disable GPU, fall back to CPU
|
||||||
# - ENABLE_CACHE=false # Disable embedding cache (default: true)
|
# - ENABLE_CACHE=false # Disable embedding cache (default: true)
|
||||||
- CACHE_DIR=/app/.if_cache
|
- CACHE_DIR=/app/.if_cache
|
||||||
- HF_HOME=/models/huggingface
|
- HF_HOME=/models/huggingface
|
||||||
@@ -55,8 +57,6 @@ services:
|
|||||||
- /path/to/winnow/models:/models
|
- /path/to/winnow/models:/models
|
||||||
- /path/to/winnow/cache:/app/.if_cache
|
- /path/to/winnow/cache:/app/.if_cache
|
||||||
- /path/to/winnow/output:/app/frigate_train
|
- /path/to/winnow/output:/app/frigate_train
|
||||||
stdin_open: true
|
|
||||||
tty: true
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
|
|||||||
+4
-7
@@ -64,21 +64,18 @@ def main() -> None:
|
|||||||
rprint("[bold red]Could not fetch people from Immich. Check URL/Key.[/bold red]")
|
rprint("[bold red]Could not fetch people from Immich. Check URL/Key.[/bold red]")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check for non-interactive mode; also force auto when stdin has no TTY
|
# Auto mode when no TTY (Docker, cron, pipes) — the primary use case.
|
||||||
# (e.g. Docker without -it) to avoid an EOFError crash
|
# A TTY means local interactive use; AUTO_MODE=true overrides that for scripting.
|
||||||
auto_mode = os.environ.get("AUTO_MODE", "false").lower() == "true" or not sys.stdin.isatty()
|
auto_mode = not sys.stdin.isatty() or os.environ.get("AUTO_MODE", "").lower() in ("true", "1", "yes")
|
||||||
dry_run = os.environ.get("DRY_RUN", "false").lower() in ("true", "1", "yes")
|
dry_run = os.environ.get("DRY_RUN", "false").lower() in ("true", "1", "yes")
|
||||||
|
|
||||||
if dry_run:
|
if dry_run:
|
||||||
rprint("[bold yellow]DRY RUN — no images will be downloaded or uploaded[/bold yellow]")
|
rprint("[bold yellow]DRY RUN — no images will be downloaded or uploaded[/bold yellow]")
|
||||||
|
|
||||||
if auto_mode:
|
if auto_mode:
|
||||||
if not sys.stdin.isatty() and os.environ.get("AUTO_MODE", "false").lower() != "true":
|
|
||||||
rprint("[dim]No TTY detected — running in auto mode. Set AUTO_MODE=true to suppress this.[/dim]")
|
|
||||||
else:
|
|
||||||
rprint("[bold cyan]Running in AUTO mode (non-interactive)[/bold cyan]")
|
|
||||||
jobs = auto_configure(people)
|
jobs = auto_configure(people)
|
||||||
else:
|
else:
|
||||||
|
rprint("[bold cyan]Interactive mode — set AUTO_MODE=true to skip prompts[/bold cyan]")
|
||||||
jobs = interactive_configure(people)
|
jobs = interactive_configure(people)
|
||||||
|
|
||||||
if jobs:
|
if jobs:
|
||||||
|
|||||||
Reference in New Issue
Block a user