diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-05 09:54:26 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-05 09:54:26 +0200 |
| commit | d3a038d02ffe35470a6e74c713b343c4b25427d0 (patch) | |
| tree | 36aa218320a0aebcefe0bd884344da7e937b57bc | |
| parent | 636337e4b6ed8a4178bc388a1c47c06c839ba841 (diff) | |
| download | fanfictioner-d3a038d02ffe35470a6e74c713b343c4b25427d0.tar.gz fanfictioner-d3a038d02ffe35470a6e74c713b343c4b25427d0.zip | |
Tie page picks to their prompts and guard bad inputs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | README.md | 6 | ||||
| -rwxr-xr-x | fanfictioner | 17 |
2 files changed, 20 insertions, 3 deletions
@@ -26,6 +26,12 @@ Plan review keys: `c` confirm, `e` edit in `$EDITOR`, `g` ask Gemma to revise, `q` quit. Image review keys: `1`-`3` pick, `r` regenerate, `p` edit prompt, `s` skip edit (edit stage only), `q` quit. +A page can override the base model with a `Model: krea2` line in plan.md. To +redo a page, delete `NNN.png` from the library and its `cand/pNNN_*` folder. +To redo a reference sheet, delete `refs/<Name>.png`; pages already done keep +the old look. A prompt edited with `p` applies until you pick and is not +written back to plan.json. + ## License Copyright (C) 2026 Danilo M. <danix@danix.xyz> diff --git a/fanfictioner b/fanfictioner index 6a9581f..db434be 100755 --- a/fanfictioner +++ b/fanfictioner @@ -16,6 +16,7 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. import argparse +import hashlib import http.client import json import os @@ -420,7 +421,7 @@ def unload_llm(): """Free VRAM for sd-cli. Idempotent: an unloaded or unreachable server is fine.""" try: llm("/models/unload", {"model": LLM_MODEL}, timeout=10) - except OSError: + except (OSError, ValueError): pass @@ -539,7 +540,8 @@ def refs_stage(chars, wd): def page_stage(p, wd, out, base): """Base scene, then chained head edits; each pick kept in cand/pNNN so a quit resumes mid-page.""" - d = wd / "cand" / f"p{p['n']:03d}" + key = json.dumps([p["base_prompt"], p["orientation"], p["model"], p["edits"]]) + d = wd / "cand" / f"p{p['n']:03d}_{hashlib.sha1(key.encode()).hexdigest()[:8]}" size = SIZES[p["orientation"]] scene = d / "base.png" if not scene.exists(): @@ -689,8 +691,17 @@ def main(): return selftest() if not a.story: ap.error("story file required") + if not a.story.is_file(): + ap.error(f"{a.story}: not a file") + if a.story.suffix == "": + ap.error("story file needs an extension, e.g. story.md") try: - lib = load_conf()["LIBRARY"] + try: + lib = load_conf().get("LIBRARY") + except FileNotFoundError: + lib = None + if not lib: + sys.exit(f"set LIBRARY in {CONF}") wd = a.story.with_suffix("") pj = plan_stage(a.story, wd) chars, pages = todo(pj, wd, lib) |
