#!/usr/bin/env node // Quick Edit benchmark v2 runner (standalone; not a Playwright spec). // // For each fixed prompt: import a fixed photo, run the editor agent, and // record the executed op trace, latency (ms), undo-group count (history.mark // delta), new layers, and before/after screenshots. Grading (eye + gpt-5.4) // happens separately on the saved images (see quickedit-bench-grade.js). // // Usage: // BASE_URL=http://127.0.0.1:7011 SESSION_FILE=/path/sessions.json \ // NODE_PATH=/path/node_modules node quickedit-bench.js // // CATS=structural,looks limit to categories // PROMPTS=1,2,3 limit to ids // OUT=/tmp/opencode/qe-bench // PHOTOS=/tmp/opencode where the fixed jpg fixtures live // HEADFUL=1 const fs = require('node:fs'); const path = require('node:path'); const { chromium } = require('@playwright/test'); const BASE = process.env.BASE_URL || 'http://127.0.0.1:7011'; const OUT = process.env.OUT || '/tmp/opencode/qe-bench'; const PHOTOS = process.env.PHOTOS || '/tmp/opencode'; const SESSION_FILE = process.env.SESSION_FILE || '/home/pewds/odysseus-cookbook-fresh/data/sessions.json'; // photo fixtures (in PHOTOS/): real-person.jpg pic-64.jpg pic-1015.jpg // pic-1018.jpg real-sky.jpg real-city.jpg real-mountainlake.jpg // real-beachsunset.jpg old-faded.jpg food.jpg night.jpg pic-1016.jpg // pic-1027.jpg demo-street.jpg const P = { portrait: 'real-person.jpg', portrait2: 'pic-64.jpg', fjord: 'pic-1015.jpg', hills: 'pic-1018.jpg', sky: 'real-sky.jpg', city: 'real-city.jpg', lake: 'real-mountainlake.jpg', sunset: 'real-beachsunset.jpg', old: 'old-faded.jpg', canyon: 'pic-1016.jpg', face: 'pic-1027.jpg', street: 'demo-street.jpg', }; const CASES = [ // ---- structural (30) ---- { id: 1, cat: 'structural', photo: P.sky, prompt: 'crop to a square' }, { id: 2, cat: 'structural', photo: P.sky, prompt: 'make this 16:9' }, { id: 3, cat: 'structural', photo: P.portrait, prompt: 'crop to 9:16 for a story' }, { id: 4, cat: 'structural', photo: P.fjord, prompt: 'crop to 4:5' }, { id: 5, cat: 'structural', photo: P.city, prompt: 'trim the empty borders' }, { id: 6, cat: 'structural', photo: P.hills, prompt: 'resize to 1920 wide' }, { id: 7, cat: 'structural', photo: P.fjord, prompt: 'resize to 1080 tall' }, { id: 8, cat: 'structural', photo: P.hills, prompt: 'rotate the whole image 90 degrees' }, { id: 9, cat: 'structural', photo: P.city, prompt: 'rotate the canvas 180' }, { id: 10, cat: 'structural', photo: P.fjord, prompt: 'flip the canvas horizontally' }, { id: 11, cat: 'structural', photo: P.sky, prompt: 'flip the whole image vertically' }, { id: 12, cat: 'structural', photo: P.hills, prompt: 'rotate only this layer 90 degrees' }, { id: 13, cat: 'structural', photo: P.city, prompt: 'flip this layer horizontally' }, { id: 14, cat: 'structural', photo: P.sky, prompt: 'add the title "SUMMER"' }, { id: 15, cat: 'structural', photo: P.fjord, setup: 'text', prompt: 'make the text bigger' }, { id: 16, cat: 'structural', photo: P.city, setup: 'text', prompt: 'make the text smaller' }, { id: 17, cat: 'structural', photo: P.hills, setup: 'text', prompt: 'make the title red' }, { id: 18, cat: 'structural', photo: P.sky, prompt: 'align the layer to the centre', setup: 'align' }, { id: 19, cat: 'structural', photo: P.fjord, prompt: 'align the layer to the left', setup: 'align' }, { id: 20, cat: 'structural', photo: P.city, prompt: 'align the layer to the right', setup: 'align' }, { id: 21, cat: 'structural', photo: P.sky, setup: 'text', prompt: 'add a drop shadow to the title' }, { id: 22, cat: 'structural', photo: P.fjord, setup: 'text', prompt: 'add a stroke to the layer' }, { id: 23, cat: 'structural', photo: P.city, prompt: 'add a colour overlay' }, { id: 24, cat: 'structural', photo: P.sky, prompt: 'fill the white area with red' }, { id: 25, cat: 'structural', photo: P.sky, prompt: 'flood fill the sky with blue' }, { id: 26, cat: 'structural', photo: P.hills, prompt: 'add a new layer' }, { id: 27, cat: 'structural', photo: P.fjord, prompt: 'duplicate this layer' }, { id: 28, cat: 'structural', photo: P.city, prompt: 'flatten the image' }, { id: 29, cat: 'structural', photo: P.sky, prompt: 'merge the layer down' }, { id: 30, cat: 'structural', photo: P.hills, prompt: 'delete this layer' }, // ---- looks / adjustments (25) ---- { id: 31, cat: 'looks', photo: P.fjord, prompt: 'make it brighter' }, { id: 32, cat: 'looks', photo: P.hills, prompt: 'make it darker' }, { id: 33, cat: 'looks', photo: P.city, prompt: 'warm it up' }, { id: 34, cat: 'looks', photo: P.portrait, prompt: 'make it cooler' }, { id: 35, cat: 'looks', photo: P.fjord, prompt: 'make it black and white' }, { id: 36, cat: 'looks', photo: P.old, prompt: 'make it sepia' }, { id: 37, cat: 'looks', photo: P.hills, prompt: 'make it punchy' }, { id: 38, cat: 'looks', photo: P.fjord, prompt: 'make it vivid and colourful' }, { id: 39, cat: 'looks', photo: P.city, prompt: 'make it dramatic' }, { id: 40, cat: 'looks', photo: P.hills, prompt: 'make it moody and cinematic' }, { id: 41, cat: 'looks', photo: P.old, prompt: 'make it vintage' }, { id: 42, cat: 'looks', photo: P.old, prompt: 'give it a faded film look' }, { id: 43, cat: 'looks', photo: P.city, prompt: 'increase the contrast' }, { id: 44, cat: 'looks', photo: P.fjord, prompt: 'lower the contrast' }, { id: 45, cat: 'looks', photo: P.hills, prompt: 'sharpen it' }, { id: 46, cat: 'looks', photo: P.portrait, prompt: 'soften it' }, { id: 47, cat: 'looks', photo: P.fjord, prompt: 'blur it slightly' }, { id: 48, cat: 'looks', photo: P.city, prompt: 'add a vignette' }, { id: 49, cat: 'looks', photo: P.hills, prompt: 'dehaze it' }, { id: 50, cat: 'looks', photo: P.fjord, prompt: 'make it HDR' }, { id: 51, cat: 'looks', photo: P.city, prompt: 'auto enhance' }, { id: 52, cat: 'looks', photo: P.hills, prompt: 'give it a teal and orange look' }, { id: 53, cat: 'looks', photo: P.fjord, prompt: 'golden hour' }, { id: 54, cat: 'looks', photo: P.old, prompt: 'clean it up' }, { id: 55, cat: 'looks', photo: P.city, prompt: 'make it look professional' }, // ---- portrait (10) ---- { id: 56, cat: 'portrait', photo: P.portrait, prompt: 'smooth the skin' }, { id: 57, cat: 'portrait', photo: P.portrait, prompt: 'whiten the teeth' }, { id: 58, cat: 'portrait', photo: P.portrait, prompt: 'remove the blemishes' }, { id: 59, cat: 'portrait', photo: P.portrait, prompt: 'brighten the face' }, { id: 60, cat: 'portrait', photo: P.portrait, prompt: 'brighten the eyes' }, { id: 61, cat: 'portrait', photo: P.portrait2, prompt: 'make her look glamorous' }, { id: 62, cat: 'portrait', photo: P.portrait, prompt: 'give it a professional headshot look' }, { id: 63, cat: 'portrait', photo: P.portrait, prompt: 'reduce the shine on the face' }, { id: 64, cat: 'portrait', photo: P.portrait2, prompt: 'warm up the portrait' }, { id: 65, cat: 'portrait', photo: P.portrait, prompt: 'soft smooth skin with a nice glow' }, // ---- generative (20) ---- { id: 66, cat: 'generative', photo: P.city, prompt: 'remove the person on the left' }, { id: 67, cat: 'generative', photo: P.hills, prompt: 'remove the distractions' }, { id: 68, cat: 'generative', photo: P.portrait, prompt: 'put her on a beach' }, { id: 69, cat: 'generative', photo: P.portrait, prompt: 'replace the background with mountains' }, { id: 70, cat: 'generative', photo: P.fjord, prompt: 'add a full moon in the sky' }, { id: 71, cat: 'generative', photo: P.sky, prompt: 'add dramatic clouds' }, { id: 72, cat: 'generative', photo: P.sky, prompt: 'extend the canvas to 16:9 with generative fill' }, { id: 73, cat: 'generative', photo: P.sky, prompt: 'extend the canvas to 9:16' }, { id: 74, cat: 'generative', photo: P.fjord, prompt: 'add a bird flying in the sky' }, { id: 75, cat: 'generative', photo: P.hills, prompt: 'add wildflowers in the foreground' }, { id: 76, cat: 'generative', photo: P.fjord, prompt: 'make it look snowy' }, { id: 77, cat: 'generative', photo: P.hills, prompt: 'make it autumn with orange leaves' }, { id: 78, cat: 'generative', photo: P.city, prompt: 'add rain and wet streets' }, { id: 79, cat: 'generative', photo: P.city, prompt: 'remove the car' }, { id: 80, cat: 'generative', photo: P.city, prompt: 'remove the sign' }, { id: 81, cat: 'generative', photo: P.fjord, prompt: 'change the sky to a sunset' }, { id: 82, cat: 'generative', photo: P.portrait, prompt: 'put sunglasses on her' }, { id: 83, cat: 'generative', photo: P.portrait, prompt: 'add a hat' }, { id: 84, cat: 'generative', photo: P.fjord, prompt: 'add a rainbow' }, { id: 85, cat: 'generative', photo: P.sky, prompt: 'generative fill the empty sky' }, // ---- multi-step (15) ---- { id: 86, cat: 'multistep', photo: P.city, prompt: 'crop to a square, make it warmer and add the title SUMMER' }, { id: 87, cat: 'multistep', photo: P.fjord, prompt: 'make it black and white and add a vignette' }, { id: 88, cat: 'multistep', photo: P.hills, prompt: 'brighten it and sharpen it' }, { id: 89, cat: 'multistep', photo: P.city, setup: 'text', prompt: 'warm it up and add a drop shadow to the title' }, { id: 90, cat: 'multistep', photo: P.portrait, prompt: 'remove the background and make it brighter' }, { id: 91, cat: 'multistep', photo: P.fjord, prompt: 'crop to 16:9 and give it a moody cinematic look' }, { id: 92, cat: 'multistep', photo: P.hills, prompt: 'flip it horizontally and add a vignette' }, { id: 93, cat: 'multistep', photo: P.city, prompt: 'sharpen it and increase the contrast' }, { id: 94, cat: 'multistep', photo: P.fjord, prompt: 'make it punchy and warm it up' }, { id: 95, cat: 'multistep', photo: P.hills, prompt: 'rotate the whole image 90 and add a vignette' }, { id: 96, cat: 'multistep', photo: P.sky, prompt: 'add the title HELLO and a drop shadow' }, { id: 97, cat: 'multistep', photo: P.fjord, prompt: 'select the subject, invert it and blur it' }, { id: 98, cat: 'multistep', photo: P.old, prompt: 'make it black and white then add a title' }, { id: 99, cat: 'multistep', photo: P.city, prompt: 'warm and brighten with a vignette' }, { id: 100, cat: 'multistep', photo: P.hills, prompt: 'crop to a square and make it vintage' }, // ---- v2.1 harder prompts (30): multi-step with generative, poster/text // design, reference looks, and targeted local recolours. ---- // hardmulti (10): compound instructions where at least one step is generative. { id: 101, cat: 'hardmulti', photo: P.city, prompt: 'remove the person on the left and then warm up the photo' }, { id: 102, cat: 'hardmulti', photo: P.portrait, prompt: 'put her on a beach and add a warm sunset' }, { id: 103, cat: 'hardmulti', photo: P.fjord, prompt: 'add a full moon and make the sky more purple' }, { id: 104, cat: 'hardmulti', photo: P.city, prompt: 'remove the sign and add some flowers' }, { id: 105, cat: 'hardmulti', photo: P.portrait, prompt: 'replace the background with mountains and make it cooler' }, { id: 106, cat: 'hardmulti', photo: P.sky, prompt: 'add dramatic clouds then increase the contrast' }, { id: 107, cat: 'hardmulti', photo: P.hills, prompt: 'make it snowy and add a warm glow' }, { id: 108, cat: 'hardmulti', photo: P.street, prompt: 'remove the red car and add a bicycle' }, { id: 109, cat: 'hardmulti', photo: P.sky, prompt: 'extend to 16:9 with generative fill and add a title SUMMER' }, { id: 110, cat: 'hardmulti', photo: P.city, prompt: 'add rain and make it moody' }, // poster (8): title / tagline text design. { id: 111, cat: 'poster', photo: P.canyon, prompt: 'make a movie poster titled THE SUMMIT' }, { id: 112, cat: 'poster', photo: P.fjord, prompt: 'add a bold title "ESCAPE" at the bottom and a tagline' }, { id: 113, cat: 'poster', photo: P.canyon, prompt: 'add large centred title text in white with a drop shadow' }, { id: 114, cat: 'poster', photo: P.fjord, prompt: 'make a travel poster titled VISIT NORWAY' }, { id: 115, cat: 'poster', photo: P.face, prompt: 'add the title "DREAM" in a stylish font and a thin border' }, { id: 116, cat: 'poster', photo: P.canyon, prompt: 'turn it into a vintage travel poster with the text EXPLORE' }, { id: 117, cat: 'poster', photo: P.city, setup: 'text', prompt: 'add a subtitle under the title and align it to the centre' }, { id: 118, cat: 'poster', photo: P.fjord, prompt: 'design a minimalist poster: add the title "SILENCE" and desaturate the background' }, // reference (20): "make it look like