Spaces:
Running
Running
Commit History
19 days ago
-
rebrand: Whyx-PROptimizer -> ART-PROMPtimizer, owner Whyx/Whyxeo -> ArtShumov
Ownership and name change announced 2026-10-10. Mechanical pass over 74 tracked files (~1240 hits): Whyx-PROptimizer / Whyx-PROmpTea -> ART-PROMPtimizer everywhere it was shown or documented (app title, extension buttons and locales, READMEs, manifest.toml, HF card); the whyx-prompttea slug family -> art-promptimizer (zip/xpi filenames, gecko id, updates json key); WHYX_ constants, env vars and message types -> ART_; whyx- classes, whyx_ vars and camel whyxHud -> art- equivalents; download root whyx/ -> art/ (the old tree stays on disk untouched); theme module whyx_theme.py -> art_theme.py (ArtTheme); updates route /updates/whyx.json -> /updates/art.json; old owner handle Whyxeo -> ArtShumov where it appears. Data is never broken by the rename: every ART_* env read keeps a WHYX_* twin so secrets already deployed under the old names keep working (pinned by test_legacy_env_fallback.py, an AST scan of src+scripts); the history store artHistory adopts the legacy whyxHistory key on first l…2ca6a54
24 days ago
-
Tagger: the result panel was eighteen identical grey blocks
Caption and tags now read as three zones instead of one undifferentiated column of interchangeable boxes. The natural-language caption is the only output meant to be pasted as-is, so it gets the only card with an accent edge and body-sized text. It used to share a single CSS rule with every piece of metadata around it -- that is exactly how it came to look like one more box among eighteen. Tag sections become pills under a header carrying the number of rows it renders. Four of those sections (camera, action, face-retag, caption-bridge) had no CSS at all and drew as bare text beside their six boxed neighbours; one rule now styles every section, and the count badge is what makes eighteen sections scannable. The badge counts what is on screen rather than what the source list held, because characters truncate at six and the general list at fourteen. The rating tier labels were an accessibility defect, not a matter of taste: the chip painted --muted onto --ok/--amber/--danger, which meas…d411591
26 days ago
-
Tagger: the browser caption had no progress at all
The private path spends every second of its wait in this page's own fetch() to the provider, which runs before Gradio's event reaches the server -- and Gradio's progress only ever covers the server half of the event. So the button with the longest wait was the one with nothing on screen, while the extension next door was counting seconds. Add a clock of its own beside that button: the extension's HUD, ported. A ticking elapsed readout and a bar, started and stopped by the caption script itself (window.whyxHud, installed by the head script) rather than guessed at from the DOM. It starts after the cheap refusals -- no key, unreachable provider, bad model, no image -- so an obvious mistake cannot flash a timer over its own error, and it stops inside envelope() and refusal(), the only two ways out of that script, so the bar cannot outlive its result. Wrapping the body in a finally was not an option: those exact shape contracts (one named async function expression, outer returns of the one…fe33aad -
Tagger: dropdowns opened off-screen, Google offered one model, 503 stopped there
All three came from the extension 0.9.8 report. Option lists on the Tagger jumped below the fold or to mid-screen while the Generate tab looked fine. .whyx-tree-node carried backdrop-filter, which per spec makes it the containing block for its position:fixed descendants; Gradio anchors ul.options with position:fixed and a bottom solved against the viewport, so inside the card that bottom resolved against ~1200px of card instead. Forcing backdrop-filter off on the real node moved top from 1065.28px to 742.48px and listY from 1354 (viewport 886) onto the screen with flags: []. Drop the blur from the two host components that can hold Gradio components; keep it on the HTML-only boxes, which can never contain one. test_ui_assets now asserts the fix instead of requiring the trap. "No model selection in NVIDIA NIM or any other cloud mode" was two faults. Google had a single hardcoded entry, so there was nothing to choose from, and the dropdown was seeded with that one entry until a provider…79de953
-
Polish Space UI: fit text, untangle header, unify button wording
Layout (src/ui/studio.css) - .whyx-segment stacked column-wise and the inset frame moved onto the choices row: the fieldset used to sit side by side with its own label and info, so in a 482px column the pills were squeezed to 158px and every label ellipsised. Labels are now flex: 1 1 160px, never clipped. - #whyx-panel-tagger-mode choices became an auto-fit grid (minmax(210px, 1fr)): the 6 model chips rendered as 5 staggered rows of one/two; they are now 3 rows of two, with labels allowed to wrap. - .tabs .tab-container: min-height 34px + overflow visible. The bar was 32px under 34px pills with overflow forced off `visible`, clipping each tab 1px top and bottom. - The header no longer scrolls sideways or hides the subtitle: .whyx-head-side/.whyx-controls drop their 640px floor and flex:none for flex: 0 1 auto (1015px min-content -> 1119px page scroll under any narrower viewport), and .whyx-head-main keeps min-width: auto so it reserves .whyx-brand's 313px instead …1f8bc92 -
Cloud VLM: a private path where the key never reaches this server
The Tagger's cloud mode had one call site: the browser posted the API key to the Space and the Space forwarded it to the provider. That is unavoidable on that path -- the process making the HTTP call is the one that must read the key -- so the key sits in this process's memory for the duration of the call, and on a public Space the owner can see it in a log. This adds the other arrangement. src/ui/direct_caption.py emits page JavaScript that calls the provider itself: the key is read from the field in the page, the image is fetched from the Space as a same-origin blob, downscaled on a canvas and posted straight to the provider, and only the finished caption comes back for the existing blacklist filter and result rendering. In this mode the Space holds the caption, not the credential. A "where" switch in the cloud accordion picks the call site, and it defaults to private. The switch is not cosmetic: the key field is an input of the private button so page JS can read it, and it is deli…49b58db
-
fix(header): wrap at 860px, not 1023px, and give the theme picker a full row
The previous fix wrapped the header from 1023px down, which cost ~100px of sticky header on any 1000px window even though the brand (313px floor) and the switcher column (640px) still fit on one line there. Below 860px they genuinely do not fit, so that is the breakpoint. Also: the theme and language clusters are flex siblings sharing the row equally (flex 1 1 0), leaving the theme picker 317px for 653px of chips and stacking them three deep. On a narrow viewport it now claims a full row with the language picker beneath, and the chips tighten slightly. Verified on the live page: 1296px viewport gives a 117px header, wordmark inside its frame, no horizontal overflow.cb17b61 -
fix(header): wrap the header on narrow viewports instead of crushing the brand
Caught on the deployed Space, where the browser viewport is 704px: the sticky header is a non-wrapping row and .whyx-head-side asks for 640px, so .whyx-head-main was squeezed until the framed brand measured 26px wide and the nowrap wordmark spilled out of its own frame. Below 1023px the header now wraps and the switcher column takes its own full-width row; .whyx-brand gets a 313px floor (logo 38 + gap 11 + the widest wordmark 240 + padding 24) so the wordmark can never be crushed. Verified at 1000px: title stays inside the frame, no horizontal overflow.7bba21b -
docs: point studio.css at theme/space.css, not the retired tokens.css
4dc14a1 -
Space: extension palette, framed header, key hardening
Visual identity, per the maintainer's direction: the Space now uses the browser extension's five themes (indigo/emerald/sunset/mist/cream) with the extension's exact colour values, so both products read as one. The layout work from the logo redesign is kept: compact header, framed brand block, framed theme/language switchers, two-column cards. Palette coupling is inverted rather than removed. extension/theme.css used to be GENERATED from theme/tokens.css by scripts/build_theme.py with a CI --check. The extension ships as a static MV3 bundle that a Space build must not rewrite, so the generator, its CI job and theme/tokens.css are deleted; theme/space.css is hand-owned and tests/test_ui_assets.py now compares the two palettes token by token (with the CSS cascade applied) so a colour change still cannot reach one surface and miss the other. Three real defects found and fixed while verifying: - The wordmark's two-tone gradient was invisible. Gradio resets the "background" shorthand o…cac61d9 -
feat(ui): compact header, real columns, matte finish
Redesign of the Space layout, measured and screenshotted rather than inferred. Three of the defects were invisible to computed-style checks. **The wordmark was invisible.** `.whyx-title` relied on background-clip:text, and Gradio cleared the background image, so `-webkit-text-fill-color: transparent` left "Whyx-PROmpTea" unpainted -- only its subtitle showed. It is now a solid colour, which also suits the matte direction. **The header was 507px of near-empty space.** The controls column was `scale=0, min_width=0`, so it collapsed to 0px wide and stacked 8 radio labels vertically. It now has a real width (430px), wraps to at most two rows, and the bar is ~90px. A logo mark was added, matching the extension. **Bright teal pills behind field labels.** Gradio's default sets `--block-label-background-fill` and `--block-title-background-fill` to a solid #0891B2. The bridge covered the *text* colours of those blocks but not the backgrounds, so every labelled field with an info tooltip ("Ge…a595971 -
fix(ui): make the columns work, flatten the categories card, align tabs
The Generate tab was a single 704px stack with one card 4225px tall, and buttons sat at mismatched heights. Four separate causes, all found by measuring the live DOM rather than reading the CSS. 1. Category grid never applied. Gradio wraps gr.Column children in a div.form, so `.whyx-cat-grid` had exactly one child and the 28 checkboxes were never grid items -- they stacked as 28 full-width rows. The grid is now declared on `.whyx-cat-grid > .form`. The card went 4225px -> 992px and cells became a uniform 107px (they were ragged 126-179px, because each one rendered its full `info` description). 2. Descriptions clamped to two lines with an ellipsis, which is what actually keeps the cells equal height. Field help text also got one shared line-height and colour, so it stops reading as a different kind of text from the panel notes above it. 3. Gradio caps its own `.main.fillable` at 768px. Setting max-width on `.gradio-container` alone did nothing, because the …3a3e5b7 -
feat(tagger): viewfinder, telemetry, chip filter and a segmented format switch
Brings the Tagger tab up to the extension's panel, so the two surfaces feel like one product rather than sharing only a palette. - Viewfinder: HUD corners plus a thirds grid over the preview, injected as siblings because Gradio owns that DOM. Click a corner to toggle the grid. - Telemetry: a mono readout of image state, both thresholds, tag mode and output format, painted from the live DOM with no backend round-trip (same approach as the existing live HUD). - Chip filter: typing hides non-matching chips client-side, so filtering never re-runs inference. Reuses the .whyx-cat-search idiom already in the Generate tab. - The two-way prompt/raw switch became a joined .whyx-segment instead of two loose pills, matching the extension's format control. Two bugs worth recording, both found by running it rather than reading it: - The first telemetry draft drove a body-wide MutationObserver and wrote innerHTML unconditionally. The write re-triggered the observer, which wrote aga…716dc85 -
feat(aurora): port the extension's glass depth cues to the Space
The extension's panels read as physical glass; the Space had flat cards. This ports the primitives that create that, so the two surfaces share a visual language rather than just a palette. - Specular edge: a 1px gradient rim on every card, masked to the border only (mask-composite: exclude) so cards catch light instead of wearing a flat outline. Hosts get position:relative, without which the absolutely positioned ::before would anchor to the viewport and paint one huge gradient over the page. - Noise texture: feTurbulence overlay driven by --noise, sitting under the content (z-index 0) next to the existing radial glows. - Glass: blur + saturate from --panel-blur / --glass-sat on cards and the action bar, replacing the two hand-picked blur(12px)/blur(16px) values. - Sticky HUD header, mirroring the extension's .topbar.sticky-hud, so the brand row stays put while three long tabs scroll under it. - New building blocks for the Tagger work in the next phase: .whyx-segment (…4a62592 -
feat(theme): five themes on the Space, painted by the shared tokens
The header offered dark/light while the extension offered five themes, and the two defined colours independently. The app now uses the same five palettes from theme/tokens.css and switches them the same way. - src/ui/studio.css rewritten onto the shared token vocabulary (--panel/--muted/--radius/--accent-2/--amber/--danger instead of --surface/--dim/--r-lg/--violet/--warn/--err). Every hard-coded rgba() is gone -- literals are what made a theme switch look half-applied, since they ignore every body[data-theme] block. A test now rejects any colour literal in this file. - Gradio variable bridge: Gradio bakes its own palette into ~40 CSS variables and paints most framework widgets from those, so a theme switch used to restyle our elements only. The bridge maps them onto the tokens and is declared on body (not :root) so var(--text) resolves against the *active* theme. `color` is set explicitly as well, because Gradio 6 hard-codes #E2E8F0 on body.dark and #CBD5E1 on .gr…739781b -
fix(ui): restore missing stylesheet, repair corrupted cloud_caption, add asset guard
The working tree could not start: a WIP layout refactor had deleted WHYX_CSS from src/ui/assets.py while app.py still imported it, so `import app` raised ImportError and the whole Space was down. - src/ui/studio.css: the stylesheet restored as a real CSS file instead of a 326-line Python string literal; assets.py loads it from disk and raises a clear error if it is ever missing again. - src/cloud_caption.py: drop a stray unreachable block pasted into validate_cloud_model (duplicated tail of _post_chat_completions, F821 on undefined req/timeout). Already committed in HEAD, so CI was red. - src/api.py: drop a no-op .format() whose message has no {provider}. - scripts/eval_emotion_tagging.py: drop an unused import. - tests/test_ui_assets.py: pin the asset contract -- a missing or truncated stylesheet, a renamed selector or a UTF-8 BOM all survive the rest of the suite silently. The BOM guard exists because the restored file was written with one. - app.py / src/ui/generate_t…a628f7d