diff --git a/.agents/scripts/higgsfield-helper.sh b/.agents/scripts/higgsfield-helper.sh index cdb33ffca..e947c1c9d 100755 --- a/.agents/scripts/higgsfield-helper.sh +++ b/.agents/scripts/higgsfield-helper.sh @@ -267,6 +267,7 @@ Options (pass after command): --headless Run without browser window (default) --model, -m Model: soul, nano_banana, seedream, kling-2.6, etc. --output, -o Output directory + --project Project name for organized output dirs ({output}/{project}/{type}/) --image-file Image file for upload --timeout Timeout in milliseconds --effect App/effect slug @@ -276,12 +277,15 @@ Options (pass after command): --character-image Character face image for pipeline --dialogue Dialogue text for lipsync --unlimited Prefer unlimited models only + --no-sidecar Disable JSON sidecar metadata files + --no-dedup Disable SHA-256 duplicate detection Examples: higgsfield-helper.sh setup higgsfield-helper.sh login higgsfield-helper.sh image "A cyberpunk city at night, neon lights, rain" higgsfield-helper.sh image "Portrait of a woman" --model nano_banana + higgsfield-helper.sh image "Portrait" --project my-video --output ~/Projects/ higgsfield-helper.sh video "Camera pans across mountain landscape" higgsfield-helper.sh video "Person walks forward" --image-file photo.jpg higgsfield-helper.sh lipsync "Hello world!" --image-file face.jpg diff --git a/.agents/scripts/higgsfield/playwright-automator.mjs b/.agents/scripts/higgsfield/playwright-automator.mjs index c4e15ade6..b07bcc1ce 100644 --- a/.agents/scripts/higgsfield/playwright-automator.mjs +++ b/.agents/scripts/higgsfield/playwright-automator.mjs @@ -9,6 +9,7 @@ import { join, basename, extname, dirname } from 'path'; import { homedir } from 'os'; import { execSync } from 'child_process'; import { fileURLToPath } from 'url'; +import { createHash } from 'crypto'; // Constants const BASE_URL = 'https://higgsfield.ai'; @@ -253,6 +254,12 @@ function parseArgs() { options.feature = args[++i]; } else if (args[i] === '--subtype') { options.subtype = args[++i]; + } else if (args[i] === '--project') { + options.project = args[++i]; + } else if (args[i] === '--no-sidecar') { + options.noSidecar = true; + } else if (args[i] === '--no-dedup') { + options.noDedup = true; } else if (args[i] === '--force') { options.force = true; } else if (args[i] === '--dry-run') { @@ -1284,9 +1291,10 @@ async function generateImage(options = {}) { // Download only the new results if (options.wait !== false) { - const outputDir = options.output || DOWNLOAD_DIR; + const baseOutput = options.output || DOWNLOAD_DIR; + const outputDir = resolveOutputDir(baseOutput, options, 'images'); if (newImageIndices.length > 0) { - await downloadSpecificImages(page, outputDir, newImageIndices); + await downloadSpecificImages(page, outputDir, newImageIndices, options); } else if (generationComplete) { // Count-based detection failed (page may have refreshed during generation). // Use batch size as a cap: download at most N images from the top of the grid. @@ -1295,7 +1303,7 @@ async function generateImage(options = {}) { console.log(`Count-based detection missed new images. Downloading top ${downloadCount} (batch=${batchSize})...`); const fallbackIndices = []; for (let i = 0; i < downloadCount; i++) fallbackIndices.push(i); - await downloadSpecificImages(page, outputDir, fallbackIndices); + await downloadSpecificImages(page, outputDir, fallbackIndices, options); } else { console.log('No new images detected. Generation may still be in progress.'); console.log('Try: node playwright-automator.mjs download'); @@ -1324,7 +1332,7 @@ async function generateImage(options = {}) { // Strategy 2 (FALLBACK): Navigate to the page fresh to trigger the API call, // then extract the URL from the intercepted response. // Strategy 3 (LAST RESORT): Extract