#!/usr/bin/env bash # Orchestrate the books pipeline: EPUB -> chapters.json -> per-chapter job # manifest -> (translation by Claude Code subagents) -> bundled book_.json. # # This script DOES NOT run the LLM translation pass. After Phase 2 it stops # and prints how many jobs are pending. Use Claude Code subagents (or a fresh # session per the README) to fill in build//jobs/*.output.json, then # re-run this script — it will pick up where it left off via Phase 3. # # Usage: # ./run.sh [--slug SLUG] [--batch-size N] set -euo pipefail HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$HERE" if [[ $# -lt 1 ]]; then echo "usage: $0 [--slug SLUG] [--batch-size N]" exit 2 fi EPUB="$1"; shift SLUG="" BATCH_SIZE="30" while [[ $# -gt 0 ]]; do case "$1" in --slug) SLUG="$2"; shift 2 ;; --batch-size) BATCH_SIZE="$2"; shift 2 ;; *) echo "unknown option: $1" >&2; exit 2 ;; esac done EPUB_ABS="$(cd "$(dirname "$EPUB")" && pwd)/$(basename "$EPUB")" echo "=== Phase 1: extract_epub.py ===" if [[ -n "$SLUG" ]]; then python3 extract_epub.py "$EPUB_ABS" --slug "$SLUG" else python3 extract_epub.py "$EPUB_ABS" fi # If --slug wasn't passed, recover the slug from the chapters file just written. if [[ -z "$SLUG" ]]; then SLUG=$(python3 -c "import json,glob; p=sorted(glob.glob('build/*/chapters.json'), key=lambda x: -__import__('os').path.getmtime(x))[0]; print(json.load(open(p))['slug'])") fi echo echo "=== Phase 2: translate_chapters.py ===" python3 translate_chapters.py "$SLUG" --batch-size "$BATCH_SIZE" PENDING_FILE="build/$SLUG/jobs/_pending.txt" PENDING_COUNT=$(wc -l < "$PENDING_FILE" | tr -d ' ') echo echo "=== Phase 3: bundle_book.py ===" if [[ "$PENDING_COUNT" -gt 0 ]]; then echo " $PENDING_COUNT translation job(s) still pending." echo " Run the Claude Code subagent translation step (see README.md), then re-run this script." echo " Bundling with empty placeholders so you can preview app structure now." python3 bundle_book.py "$SLUG" else python3 bundle_book.py "$SLUG" --require-all fi