-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat(gemini-image): v0.2.0 major refactor with modular architecture #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 9 commits
c4e0e82
e786721
d1e7eca
ca1044d
228f081
f2b5793
c889da6
d665a68
b361162
40b52a8
5c2eba6
17943f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,235 @@ | ||
| # python-libs cloudflare-auth Package Fixes Needed | ||
|
|
||
| **Status**: Critical - Package cannot be used as a dependency | ||
| **Discovered**: 2025-12-06 during homelab-infra migration | ||
| **Reporter**: Claude Code (via ByronWilliams) | ||
|
|
||
| --- | ||
|
|
||
| ## Summary | ||
|
|
||
| The `byronwilliamscpa-cloudflare-auth` package has broken imports that prevent it from being used | ||
| as a dependency in other projects. This violates the core purpose of python-libs as a shared | ||
| library repository. | ||
|
|
||
| ## Issues Found | ||
|
|
||
| ### 1. ✅ FIXED LOCALLY: Incorrect Import Statements (21+ occurrences) | ||
|
|
||
| **Problem**: Module imports use `src.cloudflare_auth` instead of `cloudflare_auth` | ||
|
|
||
| **Status**: Fixed locally in this clone (not committed) | ||
|
|
||
| **Files Affected**: | ||
| - `packages/cloudflare-auth/src/cloudflare_auth/__init__.py` | ||
| - `packages/cloudflare-auth/src/cloudflare_auth/middleware.py` | ||
| - `packages/cloudflare-auth/src/cloudflare_auth/middleware_enhanced.py` | ||
| - `packages/cloudflare-auth/src/cloudflare_auth/validators.py` | ||
| - `packages/cloudflare-auth/src/cloudflare_auth/redis_sessions.py` | ||
| - And potentially others | ||
|
|
||
| **Example**: | ||
|
|
||
| ```python | ||
| # Incorrect (current in repo) | ||
| from src.cloudflare_auth.models import CloudflareUser | ||
| from src.cloudflare_auth.middleware import CloudflareAuthMiddleware | ||
|
|
||
| # Correct (fixed locally) | ||
| from cloudflare_auth.models import CloudflareUser | ||
| from cloudflare_auth.middleware import CloudflareAuthMiddleware | ||
| ``` | ||
|
|
||
| **Fix Applied**: | ||
|
|
||
| ```bash | ||
| cd packages/cloudflare-auth | ||
| find src -name "*.py" -exec sed -i 's/from src\.cloudflare_auth/from cloudflare_auth/g' {} \; | ||
| find src -name "*.py" -exec sed -i 's/import src\.cloudflare_auth/import cloudflare_auth/g' {} \; | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ### 2. ❌ NOT FIXED: Missing CloudflareSettings Module | ||
|
|
||
| **Problem**: Multiple files import from non-existent `src.config.settings` module | ||
|
|
||
| **Files Affected**: | ||
| - `packages/cloudflare-auth/src/cloudflare_auth/validators.py:40` | ||
| - `packages/cloudflare-auth/src/cloudflare_auth/middleware.py` | ||
| - `packages/cloudflare-auth/src/cloudflare_auth/middleware_enhanced.py` | ||
|
|
||
| **Import Statement**: | ||
|
|
||
| ```python | ||
| from src.config.settings import CloudflareSettings, get_cloudflare_settings | ||
| ``` | ||
|
|
||
| **Problem**: This module doesn't exist in the cloudflare-auth package | ||
|
|
||
| **Options for Resolution**: | ||
|
|
||
| #### Option A: Create CloudflareSettings within package (RECOMMENDED) | ||
|
|
||
| ```python | ||
| # packages/cloudflare-auth/src/cloudflare_auth/settings.py | ||
| from pydantic_settings import BaseSettings | ||
|
|
||
| class CloudflareSettings(BaseSettings): | ||
| """Cloudflare Access configuration settings.""" | ||
|
|
||
| cloudflare_team_domain: str | ||
| cloudflare_audience_tag: str | ||
| cloudflare_enabled: bool = True | ||
| service_token_enabled: bool = False | ||
| # ... other settings | ||
|
|
||
| class Config: | ||
| env_file = ".env" | ||
|
|
||
| def get_cloudflare_settings() -> CloudflareSettings: | ||
| """Get singleton CloudflareSettings instance.""" | ||
| return CloudflareSettings() | ||
| ``` | ||
|
|
||
| Then update imports: | ||
|
|
||
| ```python | ||
| # In validators.py, middleware.py, middleware_enhanced.py | ||
| from cloudflare_auth.settings import CloudflareSettings, get_cloudflare_settings | ||
| ``` | ||
|
|
||
| #### Option B: Make settings injectable (alternative) | ||
|
|
||
| Remove direct settings import and require settings to be passed as parameters: | ||
|
|
||
| ```python | ||
| # In validators.py | ||
| class CloudflareJWTValidator: | ||
| def __init__(self, team_domain: str, audience_tag: str): | ||
| self.team_domain = team_domain | ||
| self.audience_tag = audience_tag | ||
| ``` | ||
|
|
||
| **Recommendation**: Option A is preferred for backward compatibility and ease of use. | ||
|
|
||
| --- | ||
|
|
||
| ## Root Cause | ||
|
|
||
| The package appears to have been copied from a different project structure where it was nested under `src/` with a separate `src/config/` module. When moved to the python-libs monorepo structure, imports were not updated to reflect the new package structure. | ||
|
|
||
| --- | ||
|
|
||
| ## Impact | ||
|
|
||
| **Current State**: | ||
| - ❌ Package cannot be imported: `ModuleNotFoundError: No module named 'src.config'` | ||
| - ❌ Cannot be used as a dependency in other projects | ||
| - ❌ Forces code duplication instead of reuse | ||
| - ❌ Violates the stated purpose of python-libs repository | ||
|
|
||
| **Blocked Projects**: | ||
| - homelab-infra (PR #54) - waiting for these fixes before tests can run | ||
|
|
||
| --- | ||
|
|
||
| ## Action Items | ||
|
|
||
| ### Immediate (Required for PR #54) | ||
|
|
||
| 1. **Commit local import fixes**: | ||
|
|
||
| ```bash | ||
| cd packages/cloudflare-auth | ||
| git add src/cloudflare_auth/*.py | ||
| git commit -m "fix: correct all module imports from src.cloudflare_auth to cloudflare_auth" | ||
| ``` | ||
|
|
||
| 2. **Create CloudflareSettings module**: | ||
| - Create `src/cloudflare_auth/settings.py` | ||
| - Define `CloudflareSettings` and `get_cloudflare_settings` | ||
| - Update imports in affected files | ||
| - Test imports work correctly | ||
|
|
||
| 3. **Add import tests**: | ||
|
|
||
| ```python | ||
| # tests/test_imports.py | ||
| def test_public_imports(): | ||
| """Verify all public imports work correctly.""" | ||
| from cloudflare_auth import ( | ||
| CloudflareAuthMiddleware, | ||
| CloudflareUser, | ||
| setup_cloudflare_auth_enhanced, | ||
| ) | ||
| assert CloudflareAuthMiddleware is not None | ||
| ``` | ||
|
|
||
| 4. **Add CI check**: | ||
|
|
||
| ```yaml | ||
| # .github/workflows/ci.yml | ||
| - name: Test package imports | ||
| run: | | ||
| uv run python -c "from cloudflare_auth import CloudflareUser" | ||
| ``` | ||
|
|
||
| ### Follow-up (Before PyPI Publication) | ||
|
|
||
| 5. **Publish to PyPI**: | ||
| - Once fixes are complete and tests pass | ||
| - Follow semantic versioning (v0.1.1 for patch) | ||
| - Update homelab-infra to use PyPI package instead of path dependency | ||
|
|
||
| 6. **Update template**: | ||
| - Add import tests to cookiecutter-python-template | ||
| - Ensure packages in workspace members have validated imports | ||
|
|
||
| --- | ||
|
Comment on lines
+139
to
+189
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, check the repository structure
git ls-files | head -20Repository: ByronWilliamsCPA/python-libs Length of output: 766 🏁 Script executed: # Verify the cloudflare-auth package directory structure
if [ -d "packages/cloudflare-auth" ]; then
echo "✓ cloudflare-auth package exists"
find packages/cloudflare-auth -type f -name "*.py" | head -20
else
echo "✗ cloudflare-auth package not found"
fiRepository: ByronWilliamsCPA/python-libs Length of output: 1204 🏁 Script executed: # Check for settings.py and examine FIXES_NEEDED.md
if [ -f "FIXES_NEEDED.md" ]; then
echo "✓ FIXES_NEEDED.md exists"
echo "Checking lines 139-189:"
sed -n '139,189p' FIXES_NEEDED.md
fiRepository: ByronWilliamsCPA/python-libs Length of output: 1526 🏁 Script executed: # Check if docs/secure.md exists and examine it
if [ -f "docs/secure.md" ]; then
echo "✓ docs/secure.md exists"
grep -n "CloudflareSettings" docs/secure.md | head -10
else
echo "✗ docs/secure.md not found"
fiRepository: ByronWilliamsCPA/python-libs Length of output: 481 🏁 Script executed: # Check the actual package structure
if [ -d "packages/cloudflare-auth/src/cloudflare_auth" ]; then
echo "Contents of packages/cloudflare-auth/src/cloudflare_auth:"
ls -la packages/cloudflare-auth/src/cloudflare_auth/
else
echo "✗ Expected directory not found"
fiRepository: ByronWilliamsCPA/python-libs Length of output: 1194 🏁 Script executed: # Check what's exported from __init__.py
echo "=== __init__.py contents ==="
cat -n packages/cloudflare-auth/src/cloudflare_auth/__init__.pyRepository: ByronWilliamsCPA/python-libs Length of output: 3720 🏁 Script executed: # Check if test_imports.py exists
if [ -f "packages/cloudflare-auth/tests/test_imports.py" ]; then
echo "✓ test_imports.py exists"
cat -n packages/cloudflare-auth/tests/test_imports.py
else
echo "✗ test_imports.py does not exist (action item 3 proposes creating it)"
fiRepository: ByronWilliamsCPA/python-libs Length of output: 141 🏁 Script executed: # Check settings.py to verify CloudflareSettings and get_cloudflare_settings are defined
echo "=== settings.py first 50 lines ==="
head -50 packages/cloudflare-auth/src/cloudflare_auth/settings.pyRepository: ByronWilliamsCPA/python-libs Length of output: 1714 🏁 Script executed: # Check existing CI workflows
if [ -d ".github/workflows" ]; then
echo "=== CI Workflow files ==="
ls -la .github/workflows/
else
echo "✗ .github/workflows not found"
fiRepository: ByronWilliamsCPA/python-libs Length of output: 1379 🏁 Script executed: # Check if the CI check already exists for imports
if [ -f ".github/workflows/ci.yml" ]; then
echo "=== Checking for 'Test package imports' in ci.yml ==="
grep -n "Test package imports" .github/workflows/ci.yml || echo "Not found"
fiRepository: ByronWilliamsCPA/python-libs Length of output: 135 🏁 Script executed: # Check ci.yml to understand the current test structure and find where the import test should be added
cat -n .github/workflows/ci.yml | head -100Repository: ByronWilliamsCPA/python-libs Length of output: 3968 🏁 Script executed: # Verify that CloudflareSettings and get_cloudflare_settings are actually exported and importable
grep -n "get_cloudflare_settings" packages/cloudflare-auth/src/cloudflare_auth/settings.pyRepository: ByronWilliamsCPA/python-libs Length of output: 128 🏁 Script executed: # Check if CloudflareSettings and get_cloudflare_settings are exported from __init__.py
grep "CloudflareSettings\|get_cloudflare_settings" packages/cloudflare-auth/src/cloudflare_auth/__init__.pyRepository: ByronWilliamsCPA/python-libs Length of output: 54 🏁 Script executed: # Verify test_settings.py already exists and what it covers
if [ -f "packages/cloudflare-auth/tests/test_settings.py" ]; then
echo "✓ test_settings.py exists"
wc -l packages/cloudflare-auth/tests/test_settings.py
head -40 packages/cloudflare-auth/tests/test_settings.py
fiRepository: ByronWilliamsCPA/python-libs Length of output: 1422 🏁 Script executed: # Check docs/secure.md to see what the intended migration path is for CloudflareSettings
echo "=== docs/secure.md sections about CloudflareSettings ==="
grep -B2 -A2 "CloudflareSettings" docs/secure.md | head -50Repository: ByronWilliamsCPA/python-libs Length of output: 859 🏁 Script executed: # Check if settings should be in __all__ by looking at the full settings.py
tail -20 packages/cloudflare-auth/src/cloudflare_auth/settings.pyRepository: ByronWilliamsCPA/python-libs Length of output: 705 🏁 Script executed: # Verify the actual line count of FIXES_NEEDED.md to understand the context
wc -l FIXES_NEEDED.mdRepository: ByronWilliamsCPA/python-libs Length of output: 91 🏁 Script executed: # Check the markdown line length guideline compliance for FIXES_NEEDED.md around lines 139-189
sed -n '139,189p' FIXES_NEEDED.md | awk '{print length, $0}' | sort -rn | head -10Repository: ByronWilliamsCPA/python-libs Length of output: 723 🏁 Script executed: # Check if the proposed test imports would actually work - verify CloudflareSettings is NOT exported
echo "=== Checking __all__ exports from __init__.py ==="
grep -A 50 "__all__" packages/cloudflare-auth/src/cloudflare_auth/__init__.pyRepository: ByronWilliamsCPA/python-libs Length of output: 899 🏁 Script executed: # Try to verify if importing the proposed items would work
python3 << 'EOF'
import sys
import os
# Simulate what the test would do
try:
# This should work
from cloudflare_auth import CloudflareUser
print("✓ Can import CloudflareUser")
except ImportError as e:
print(f"✗ Cannot import CloudflareUser: {e}")
try:
# This should work
from cloudflare_auth import CloudflareAuthMiddleware
print("✓ Can import CloudflareAuthMiddleware")
except ImportError as e:
print(f"✗ Cannot import CloudflareAuthMiddleware: {e}")
try:
# This should work
from cloudflare_auth import setup_cloudflare_auth_enhanced
print("✓ Can import setup_cloudflare_auth_enhanced")
except ImportError as e:
print(f"✗ Cannot import setup_cloudflare_auth_enhanced: {e}")
try:
# This might NOT work - check if CloudflareSettings is exported
from cloudflare_auth import CloudflareSettings
print("✓ Can import CloudflareSettings from cloudflare_auth")
except ImportError as e:
print(f"✗ Cannot import CloudflareSettings from cloudflare_auth: {e}")
try:
# This will work
from cloudflare_auth.settings import CloudflareSettings, get_cloudflare_settings
print("✓ Can import CloudflareSettings from cloudflare_auth.settings")
except ImportError as e:
print(f"✗ Cannot import from cloudflare_auth.settings: {e}")
EOFRepository: ByronWilliamsCPA/python-libs Length of output: 158 🏁 Script executed: # Look more carefully at the CI section to see if there's any import testing
grep -n "import\|Import\|test.*import" .github/workflows/ci.ymlRepository: ByronWilliamsCPA/python-libs Length of output: 54 🏁 Script executed: # Check if there are any remaining "src.cloudflare_auth" imports that should be "cloudflare_auth"
grep -r "from src\.cloudflare_auth\|from src\.config" packages/cloudflare-auth/src/ 2>/dev/null | grep -v ".pyc" || echo "No src. imports found"Repository: ByronWilliamsCPA/python-libs Length of output: 93 🏁 Script executed: # Check middleware.py and middleware_enhanced.py for import issues
head -30 packages/cloudflare-auth/src/cloudflare_auth/middleware.py | grep "^from\|^import"Repository: ByronWilliamsCPA/python-libs Length of output: 54 Action items 1–2 appear complete; items 3–4 (test_imports.py and CI check) remain pending. The steps correctly reference the cloudflare-auth package structure and align with docs/secure.md. Import fixes appear done (no However:
All referenced file paths and import statements match the actual module layout. Sequencing is sound and ready to implement. 🤖 Prompt for AI Agents |
||
|
|
||
| ## Files Changed Locally (Not Committed) | ||
|
|
||
| All files in `packages/cloudflare-auth/src/cloudflare_auth/`: | ||
| - `__init__.py` - Fixed imports and docstring | ||
| - `middleware.py` - Fixed imports | ||
| - `middleware_enhanced.py` - Fixed imports | ||
| - `validators.py` - Fixed imports | ||
| - `security_helpers.py` - Fixed imports | ||
| - `sessions.py` - Fixed imports | ||
| - `utils.py` - Fixed imports | ||
| - `whitelist.py` - Fixed imports | ||
| - `models.py` - Fixed imports | ||
| - `csrf.py` - Fixed imports | ||
| - `rate_limiter.py` - Fixed imports | ||
| - `redis_sessions.py` - Fixed imports | ||
|
|
||
| --- | ||
|
|
||
| ## Testing Verification | ||
|
|
||
| After fixes are applied, verify with: | ||
|
|
||
| ```bash | ||
| # 1. Clean install test | ||
| cd /tmp | ||
| uv venv test-env | ||
| source test-env/bin/activate | ||
| uv pip install /path/to/python-libs/packages/cloudflare-auth | ||
|
|
||
| # 2. Import test | ||
| python -c "from cloudflare_auth import CloudflareUser, setup_cloudflare_auth_enhanced" | ||
|
|
||
| # 3. Run package tests | ||
| cd /path/to/python-libs/packages/cloudflare-auth | ||
| uv run pytest tests/ -v | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Contact | ||
|
|
||
| For questions or to coordinate fixes: | ||
| - **Project**: homelab-infra (blocked PR #54) | ||
| - **Reporter**: Claude Code | ||
| - **Related**: [homelab-infra PR #54](https://github.com/ByronWilliamsCPA/homelab-infra/pull/54) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| # python-libs Publishing Handoff Document | ||
|
|
||
| > **Repository:** [ByronWilliamsCPA/python-libs](https://github.com/ByronWilliamsCPA/python-libs) | ||
| > **Last Updated:** 2025-12-04 | ||
| > **Repository:** [ByronWilliamsCPA/python-libs](https://github.com/ByronWilliamsCPA/python-libs) | ||
| > **Last Updated:** 2025-12-04 | ||
| > **Status:** Ready for Implementation | ||
|
|
||
| ## Overview | ||
|
|
@@ -144,7 +144,7 @@ jobs: | |
| run: | | ||
| TAG="${{ github.ref_name }}" | ||
| echo "Processing tag: $TAG" | ||
|
|
||
| if [[ "$TAG" == cloudflare-auth-v* ]]; then | ||
| echo "package_dir=packages/cloudflare-auth" >> $GITHUB_OUTPUT | ||
| echo "package_name=byronwilliamscpa-cloudflare-auth" >> $GITHUB_OUTPUT | ||
|
|
@@ -240,60 +240,60 @@ from pydantic_settings import BaseSettings, SettingsConfigDict | |
|
|
||
| class CloudflareSettings(BaseSettings): | ||
| """Configuration for Cloudflare Access authentication.""" | ||
|
|
||
| model_config = SettingsConfigDict( | ||
| env_file=".env", | ||
| env_file_encoding="utf-8", | ||
| extra="ignore", | ||
| case_sensitive=False, | ||
| ) | ||
|
|
||
| # Required | ||
| cloudflare_team_domain: str = Field(default="", alias="CLOUDFLARE_TEAM_DOMAIN") | ||
| cloudflare_audience_tag: str = Field(default="", alias="CLOUDFLARE_AUDIENCE_TAG") | ||
| cloudflare_enabled: bool = Field(default=True, alias="CLOUDFLARE_ENABLED") | ||
|
|
||
| # Headers | ||
| jwt_header_name: str = Field(default="Cf-Access-Jwt-Assertion", alias="CF_JWT_HEADER") | ||
| email_header_name: str = Field(default="Cf-Access-Authenticated-User-Email", alias="CF_EMAIL_HEADER") | ||
|
|
||
| # Security | ||
| require_email_verification: bool = Field(default=True, alias="CF_REQUIRE_EMAIL_VERIFICATION") | ||
| log_auth_failures: bool = Field(default=True, alias="CF_LOG_AUTH_FAILURES") | ||
| require_cloudflare_headers: bool = Field(default=True, alias="CF_REQUIRE_CLOUDFLARE_HEADERS") | ||
|
|
||
| # Access control | ||
| allowed_email_domains: list[str] = Field(default_factory=list, alias="CF_ALLOWED_EMAIL_DOMAINS") | ||
| allowed_tunnel_ips: list[str] = Field(default_factory=list, alias="CF_ALLOWED_TUNNEL_IPS") | ||
|
|
||
| # Cookies | ||
| cookie_domain: Optional[str] = Field(default=None, alias="CF_COOKIE_DOMAIN") | ||
| cookie_path: str = Field(default="/", alias="CF_COOKIE_PATH") | ||
| cookie_secure: bool = Field(default=True, alias="CF_COOKIE_SECURE") | ||
| cookie_samesite: str = Field(default="lax", alias="CF_COOKIE_SAMESITE") | ||
|
|
||
| # JWT | ||
| jwt_algorithm: str = Field(default="RS256", alias="CF_JWT_ALGORITHM") | ||
| jwt_cache_max_keys: int = Field(default=16, alias="CF_JWT_CACHE_MAX_KEYS") | ||
|
|
||
| @field_validator("allowed_email_domains", "allowed_tunnel_ips", mode="before") | ||
| @classmethod | ||
| def parse_comma_separated(cls, v): | ||
| if isinstance(v, str): | ||
| return [item.strip() for item in v.split(",") if item.strip()] if v.strip() else [] | ||
| return v or [] | ||
|
|
||
|
Comment on lines
279
to
+285
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Ensure field validator is robust against edge cases. The
Consider adding a docstring to clarify the expected input formats and return behavior. |
||
| @property | ||
| def issuer(self) -> str: | ||
| if not self.cloudflare_team_domain: | ||
| return "" | ||
| domain = self.cloudflare_team_domain.rstrip("/") | ||
| return f"https://{domain}" if not domain.startswith("https://") else domain | ||
|
|
||
| @property | ||
| def certs_url(self) -> str: | ||
| return f"{self.issuer}/cdn-cgi/access/certs" if self.issuer else "" | ||
|
|
||
| def is_email_allowed(self, email: str) -> bool: | ||
| if not self.allowed_email_domains: | ||
| return True | ||
|
|
@@ -537,4 +537,4 @@ elif [[ "$TAG" == new-package-v* ]]; then | |
|
|
||
| - **Infrastructure Questions:** Byron Williams | ||
| - **Infisical Issues:** Check https://secrets.byronwilliamscpa.com status | ||
| - **GCP Issues:** Check `assured-oss-457903` project in GCP Console | ||
| - **GCP Issues:** Check `assured-oss-457903` project in GCP Console | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| # Changelog | ||
|
|
||
| All notable changes to this project will be documented in this file. | ||
|
|
||
| The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), | ||
| and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
|
|
||
| ## [0.2.0] - 2026-01-09 | ||
|
|
||
| ### Added | ||
|
|
||
| - OpenSSF-required files: LICENSE, SECURITY.md, CONTRIBUTING.md, CHANGELOG.md | ||
| - `exceptions.py` module with custom exception hierarchy | ||
| - `client.py` module with `GeminiClient` class and retry logic using tenacity | ||
| - `io.py` module with magic byte format detection | ||
| - `registry.py` module for PROMPTS.md documentation | ||
| - `response_parser.py` module for API response handling | ||
| - Structured logging with structlog (replaces print statements) | ||
| - `--no-document` CLI flag to disable PROMPTS.md logging | ||
| - `--resume` flag for story sequence generation (skips existing parts) | ||
| - JSON sidecar metadata files for generated images | ||
| - Python 3.10 compatibility (replaced `datetime.UTC` with `timezone.utc`) | ||
|
|
||
| ### Changed | ||
|
|
||
| - Refactored `generator.py` into smaller, focused modules | ||
| - Improved error handling with specific exception types | ||
| - Output paths now honor absolute paths (no forced `output/` prefix) | ||
| - API key loading now uses python-dotenv for robust .env handling | ||
|
|
||
| ### Fixed | ||
|
|
||
| - JPEG/PNG format mismatch from Gemini API (magic byte detection) | ||
| - Story mode now resumes from last completed part instead of regenerating | ||
|
|
||
| ## [0.1.0] - 2024-12-15 | ||
|
|
||
| ### Added | ||
|
|
||
| - Initial release | ||
| - `generate_image()` function for text-to-image generation | ||
| - `generate_story_sequence()` function for multi-part stories | ||
| - `finalize_draft()` function for draft-to-final workflow | ||
| - CLI (`gemini-image` command) | ||
| - Support for Gemini 2.5 Flash and Gemini 3 Pro models | ||
| - Aspect ratio and resolution configuration | ||
| - Reference image support for editing | ||
| - Thinking mode with intermediate image visualization | ||
| - Draft mode for cost-effective iteration | ||
|
|
||
| [0.2.0]: https://github.com/ByronWilliamsCPA/python-libs/compare/gemini-image-v0.1.0...gemini-image-v0.2.0 | ||
| [0.1.0]: https://github.com/ByronWilliamsCPA/python-libs/releases/tag/gemini-image-v0.1.0 |
Uh oh!
There was an error while loading. Please reload this page.