- Fix `RefineStage` overflow by applying `overflow-hidden` to the parent container and `min-h-0` to the `ScrollArea`.
- Update `generateTextureSheet` to use Chroma Green background.
- Update `refineAsset` prompt to extract the main equipment into a white background, using name and description for context.
- Update tests and API to support these changes.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
* Update Look Details Dialog with image zoom and scrollable list
* add missing migration
* minor change
* fix test
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: yiling ji <njjyl723@gmail.com>
- Updated `getGridDimensions` in `src/service/extraction.ts` to use a 2x2 grid for 4 or fewer assets, and a 3x3 grid otherwise.
- Updated `src/service/extraction.test.ts` to reflect the new grid dimensions in the `cropAssets` test.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Renamed the keyframes in `AnalyzeStage.tsx` to `scanline-analyze` to prevent conflict with the global `scanline` animation.
Also removed unused `scanline` keyframes from `RefineStage.tsx` to avoid potential future conflicts.
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
* feat(ai): use OpenAI Image Edit API instead of Responses API
Replaces the deprecated/unofficial Responses API usage for image generation with the standard `client.images.edit` API.
This change supports multi-image inputs and follows the user's provided example for `gpt-image-1.5` model compatibility.
- Updates `generateImageOpenAI` in `src/service/ai.ts` to use `client.images.edit`.
- Handles conversion of text prompts and inline/reference images to the required format using `toFile`.
- Updates `src/service/ai.test.ts` to mock the new API call and verify correct behavior.
* feat(ai): use OpenAI Image Edit API instead of Responses API
Replaces the deprecated/unofficial Responses API usage for image generation with the standard `client.images.edit` API.
This change supports multi-image inputs and follows the user's provided example for `gpt-image-1.5` model compatibility.
- Updates `generateImageOpenAI` in `src/service/ai.ts` to use `client.images.edit`.
- Removes `response_format` parameter as it's not supported/needed for GPT image models (which default to base64).
- Handles conversion of text prompts and inline/reference images to the required format using `toFile`.
- Updates `src/service/ai.test.ts` to mock the new API call and verify correct behavior.
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
* Fix toast visibility z-index issue and Create Look dialog error handling
- Moved `<Toaster />` outside of `SidebarProvider` in `Layout.tsx` and increased z-index to ensure toasts appear above dialog overlays.
- Updated `CreateLookDialog.tsx` to use `toast.error()` for API errors instead of displaying them inline at the bottom of the dialog.
* Fix Extractor error handling, toast visibility, and Create Look dialog errors
- Updated `ExtractorDialog.tsx` to reset the stage to `'selection'` on refinement error, preventing infinite loading.
- Updated `CreateLookDialog.tsx` to use `toast.error()` for API errors instead of inline text.
- Moved `<Toaster />` in `Layout.tsx` outside of `SidebarProvider` to ensure toasts appear above dialog overlays.
- Ensured `package.json` and `sonner.tsx` remain clean (reverted temporary changes).
* fix sonner
* fix lint
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: yiling ji <njjyl723@gmail.com>
- Moved `GithubIcon` to `src/ui/components/Icons.tsx` as `Icons.Github`.
- Updated `src/ui/Layout.tsx` to use the new `Icons.Github` component.
- Increased icon size to `h-7 w-7`.
- Deleted `src/ui/components/GithubIcon.tsx`.
- Removed `subCategory` field from Equipment model (DB), API, and UI.
- Generated Prisma migration `20260219022619_remove_subcategory_and_update_settings`.
- Implemented API Key masking (******) in settings service and UI.
- Updated Settings page to show 'Saved' state for API Key/URL buttons.
- Renamed 'Extraction Flow Defaults' to 'Default Models' in Settings.
- Fixed Fitting Room scrolling issue by adding `min-h-0` constraints.
- Updated tests and verifying scripts.
- Added download option to VibeCard dropdown menu when an image is present.
- Added download option to Fitting Room generated look card dropdown menu.
- Implemented client-side download logic using temporary anchor tag.
- Verified with typecheck and tests.
- Updated `docker-compose.yml` to pull `yilingj/forgery:latest` instead of building locally.
- Updated `README.md` with instructions for using Docker Compose with the pre-built image.
- Added instructions for standalone `docker run` execution in `README.md`.
- Added `.github/workflows/release.yml` for multi-platform Docker builds.
- Configured triggers for `main` branch pushes and `v*` tags.
- Uses `docker/metadata-action` for tagging:
- `latest` is only updated on semantic version tags (e.g., `v1.0.0`).
- `main` branch pushes are tagged with `main` and commit SHA.
- Supports `linux/amd64` and `linux/arm64`.
- Uses hardcoded `yilingj` username and `DOCKERHUB_TOKEN` secret.
- Added `.github/workflows/release.yml` for multi-platform Docker builds.
- Configured triggers for `main` branch pushes and `v*` tags.
- Uses `docker/metadata-action` for tagging:
- `latest` is only updated on semantic version tags (e.g., `v1.0.0`).
- `main` branch pushes are tagged with `main` and commit SHA.
- Supports `linux/amd64` and `linux/arm64`.
- Requires `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` secrets.
- Added `.github/workflows/release.yml` to build and push Docker images to Docker Hub.
- Configured trigger on `push` to `main` branch and `v*` tags.
- Enabled multi-platform builds for `linux/amd64` and `linux/arm64`.
- Uses `docker/metadata-action` for automatic tagging (`latest`, semver).
- Requires `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` secrets.
- Update `VibeCard` to support custom `children` content and ensure text readability with a gradient overlay.
- Refactor Outfit list in `Equipments.tsx` to use a grid of `VibeCard` components.
- Implement a 3x3 equipment preview grid inside Outfit cards, with overflow (+N) handling.
- Center the preview grid to 80% height as per design requirements.
- Update `CreateOutfitDialog` to support editing existing outfits (PUT request).
- Change category selection in `CreateOutfitDialog` to single-select.
- Update equipment selection grid in `CreateOutfitDialog` to fixed 3 columns.
- Add "Edit" action to Outfit cards.
- Fitting Room:
- Constrain page height to viewport.
- Use `ScrollArea` for "Generated Looks".
- Ensure character image uses `object-contain` and empty state is centered.
- Extractor:
- Add "Save as Outfit" checkbox and name input to `RefineStage`.
- Implement API call to create outfit upon completion.
- Dockerfile:
- Copy `example-data` directory to final image.
- Fixed Fitting Room page overflow by constraining height and using ScrollArea for the Generated Looks section.
- Added "Save as Outfit" checkbox and input to the Refine stage of the Extractor dialog.
- Installed @radix-ui/react-checkbox and added Shadcn Checkbox component.
- Updated Dockerfile to include example-data directory in the final image.
- Removed hardcoded `BUILTIN_POSES` and `BUILTIN_EXPRESSIONS` constants.
- Updated `PoseService` and `ExpressionService` to only list and delete items from the database.
- Removed the `type` field ('builtin' | 'custom') from `PoseItem` and `ExpressionItem`.
- Updated `GenerationService` to resolve pose and expression assets strictly from the database (`data/files`) instead of falling back to `public/`.
- Updated `Poses.tsx` and `Expressions.tsx` to remove "SYSTEM" vs "CUSTOM" UI distinction and enable deletion for all items.
- Updated `pose.test.ts` and created `expression.test.ts` to verify the new behavior.
- Fixed `generation.test.ts` to mock database calls correctly for pose/expression lookups and avoid polluting other tests.
- Removed hardcoded `BUILTIN_POSES` and `BUILTIN_EXPRESSIONS` constants.
- Updated `PoseService` and `ExpressionService` to only list and delete items from the database.
- Removed the `type` field ('builtin' | 'custom') from `PoseItem` and `ExpressionItem`.
- Updated `GenerationService` to resolve pose and expression assets strictly from the database (`data/files`) instead of falling back to `public/`.
- Updated `Poses.tsx` and `Expressions.tsx` to remove "SYSTEM" vs "CUSTOM" UI distinction and enable deletion for all items.
- Updated `pose.test.ts` and created `expression.test.ts` to verify the new behavior.
- Added `POST /api/equipments` endpoint to create equipment from an existing asset.
- Created `UploadEquipmentDialog` component with drag-and-drop and clipboard paste support.
- Added "Upload" button to the Equipments page header.
- Verified new equipment creation flow via frontend verification script.
- Added `POST /api/equipments` endpoint to create equipment from an existing asset.
- Created `UploadEquipmentDialog` component with drag-and-drop and clipboard paste support.
- Added "Upload" button to the Equipments page header.
- Verified new equipment creation flow via frontend verification script.
- Update prisma/schema.prisma to use @default(ulid()) for all relevant models
- Remove manual ulid() calls from all service files
- Update list APIs to order by id descending
- Update AssetService tests to match new behavior
- Update AGENTS.md with new conventions
- Remove empty migration file (20260217022222_add_ulid_default)
* I added `DialogFooter` to `ExtractorDialog`.
* I moved the action buttons (Start, Cancel, and the finish button) from `AnalyzeStage`, `SelectionStage`, and `RefineStage` to the `ExtractorDialog` footer.
* I lifted the `selectedIndices` state from `SelectionStage` to `ExtractorDialog`.
* I updated `AnalyzeStage` to show the status in the primary action button.
* I enabled cancellation during analysis.
* I ensured that `onSuccess` is called only when the user clicks the finish button in the Refine stage.