gpt-image-* models return b64_json by default and reject the
response_format parameter with a 400 error. Only pass it for
DALL-E models which default to url.
Skip the file-existence check when the prompt contains newlines (can't
be a filename) and catch OSError for prompts that exceed the OS path
length limit.
- State filename now derives from config: cards.bulkgen.yaml produces
.cards.bulkgen-state.yaml instead of .bulkgen.state.yaml
- Store resolved prompt text and extra params directly in state file
instead of hashing them, making state files human-readable
- Only file input contents remain hashed (SHA-256)
- Thread project_name through builder and CLI
- Remove hash_string() and _extra_hash() helpers
- Update .gitignore pattern to .*.bulkgen-state.yaml
- Add openai_text.py: text generation via OpenAI chat completions API
(gpt-4o, gpt-4o-mini, gpt-4.1, gpt-4.1-mini, gpt-4.1-nano, o3-mini)
- Add openai_image.py: image generation via OpenAI images API
(gpt-image-1 with reference image support, dall-e-3, dall-e-2)
- Refactor builder provider dispatch from TargetType to model-name index
to support multiple providers per target type
- Fix circular import between config.py and providers/__init__.py
using TYPE_CHECKING guard
- Fix stale default model assertions in tests
- Add openai>=1.0.0 dependency
- Rename ImageProvider to BlackForestProvider, TextProvider to MistralProvider
- Add get_provided_models() abstract method to Provider base class
- Move model lists from models.py into each provider's get_provided_models()
- Add providers/registry.py to aggregate models from all providers
- Extract infer_required_capabilities and resolve_model from config.py to resolve.py
- Update tests to use new names and import paths
- Add click as explicit dependency (already bundled with typer)
- Replace typer.echo calls with click.echo + click.style for colorized output
- Add BuildEvent enum and ProgressCallback to builder for decoupled progress reporting
- Remove direct typer dependency from builder module
- Show per-target status with colored labels (skip/ok/fail/...)
- Display elapsed build time in summary
- Colorize graph and clean command output
- Update CLI tests to match new output format
The text provider now includes reference_images alongside inputs when
building prompts. Image files are sent as base64 data URLs via
ImageURLChunk for actual multimodal vision support, replacing the
previous [Attached image: ...] placeholder text.
Replace singular reference_image field with reference_images list to
support an arbitrary number of reference images. Map them to the correct
BFL API parameter names based on model family:
- flux-2-*: input_image, input_image_2, ..., input_image_8
- flux-kontext-*: input_image, input_image_2, ..., input_image_4
- flux 1.x: image_prompt (single)
BREAKING CHANGE: reference_image config field renamed to reference_images (list).
The tests.conftest import could not be resolved in the nix sandbox
because tests is not a proper package. Define the WriteConfig type
alias directly in test_builder.py and test_graph.py instead.
Implement bulkgen/providers/bfl.py with a fully async httpx-based client
that supports all current and future BFL models (including flux-2-*).
Remove the blackforest dependency and simplify the image provider by
eliminating the asyncio.to_thread wrapper.
Add cachix/git-hooks.nix input and wire basedpyright, ruff,
ruff-format, and commitizen hooks into flake checks and devShell.
The basedpyright hook runs against a Nix-built venv so imports
resolve correctly in the sandbox.
Expose homeManagerModules.bulkgen and homeManagerModules.default
from the flake. The module provides programs.bulkgen.enable and
programs.bulkgen.package options, adding bulkgen to home.packages
when enabled.
- Replace pyright with basedpyright in devenv.nix (custom hook)
- Add basedpyright to devenv packages
- Fix all basedpyright warnings: add DiGraph[str] type args, annotate
class attributes, narrow SyncResponse, handle unused call results,
suppress unavoidable Any from yaml.safe_load and untyped blackforest
- Replace pydantic-settings[yaml] with direct pyyaml dependency
- Update CLAUDE.md to reflect basedpyright and dependency changes
CLAUDE.md covers architecture, data flow, code style conventions,
provider specifics, and all commands needed for development.
README.md covers installation, quick start, full config format
reference, CLI usage, incremental builds, and environment variables.
- build: executes all or specific target with dependency resolution
- clean: removes generated artifacts and state file, preserves inputs
- graph: prints dependency graph with build stages
- Config discovery: finds single *.bulkgen.yaml in working directory
- Uses native async API (chat.complete_async)
- Appends text input file contents to prompt with headers
- Notes image inputs as attached references
- Writes raw LLM response directly to output file
- build_graph() creates a DAG from project config with validation
- get_build_order() wraps topological_generations() for parallel batches
- get_subgraph_for_target() extracts transitive deps for single-target builds
- Validates missing dependencies and cycle detection
- TargetType enum with IMAGE/TEXT variants
- Defaults, TargetConfig, ProjectConfig pydantic models
- infer_target_type() for extension-based type dispatch
- resolve_model() for default/override model resolution
- load_config() using yaml.safe_load + model_validate