- Add hokusai/image.py with Pillow-based format detection and conversion
- Pass output_format to OpenAI gpt-image models and BFL API
- Convert mismatched images after provider writes (fallback for all providers)
- Handle RGBA-to-RGB flattening for JPEG targets
- Add Pillow dependency
When a target is present in the state file but no longer in the config,
its output file is deleted (or archived if archive_folder is set) and
its state entry is removed. This runs at the start of every build.
Content targets write a string directly to the output file without
invoking any AI provider. They don't require API keys and are not
archived when overwritten.
Example usage in .hokusai.yaml:
file.txt:
content: ABC
The regenerate command accepts one or more target names and forces them
to be rebuilt even if they are up to date. This respects the
archive_folder setting, archiving previous versions before overwriting.
Download targets now store only 'download: <url>' in the state file
instead of using 'prompt' and 'model: __download__' as a workaround.
Also use exclude_defaults=True when serializing state to omit empty
fields like input_hashes: {} and extra_params: {}.
When archive_folder is set in the project config, artifacts are moved to
numbered archive copies (e.g. x.01.jpg, x.02.jpg) instead of being
overwritten or deleted.
- Build command archives existing artifacts before rebuilding dirty targets
- Clean command moves files to archive instead of deleting them
- Subfolder structure is preserved in the archive directory
- State file is always deleted, never archived
Build targets with subfolder paths (e.g. img/file.jpg) failed because
parent directories did not exist. Create them on demand in
_build_single_target before dispatching to providers.
Also clean up empty subdirectories in the clean command after removing
target files.