Commit Graph

8703 Commits

Author SHA1 Message Date
Gradio PR Bot 0fd56c10c7 chore: update versions (#13691)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@gradio/accordion@0.6.0 @gradio/annotatedimage@0.12.2 @gradio/atoms@0.26.1 @gradio/audio@0.24.2 @gradio/browserstate@0.5.0 @gradio/button@0.8.2 @gradio/chatbot@0.32.1 @gradio/checkbox@0.8.2 @gradio/checkboxgroup@0.12.2 @gradio/client@2.4.0 @gradio/colorpicker@0.5.15 @gradio/column@0.4.1 @gradio/core@1.10.0 @gradio/dataframe@0.24.2 @gradio/dataset@0.7.2 @gradio/datetime@0.4.11 @gradio/dialogue@0.4.2 @gradio/downloadbutton@0.5.2 @gradio/dropdown@0.14.2 @gradio/fallback@0.6.2 @gradio/file@0.16.0 @gradio/fileexplorer@0.8.0 @gradio/form@0.4.2 @gradio/gallery@0.19.1 @gradio/group@0.3.8 @gradio/highlightedtext@0.12.2 @gradio/html@0.13.2 @gradio/imageeditor@0.20.1 @gradio/imageslider@0.7.1 @gradio/json@0.8.2 @gradio/label@0.7.2 @gradio/markdown-code@0.10.0 @gradio/markdown@0.14.2 @gradio/multimodaltextbox@0.14.1 @gradio/navbar@0.3.2 @gradio/number@0.9.2 @gradio/paramviewer@0.11.0 @gradio/plot@0.12.2 @gradio/preview@0.17.0 @gradio/radio@0.12.2 @gradio/sanitize@0.4.1 @gradio/sidebar@0.2.11 @gradio/simpledropdown@0.5.2 @gradio/simpleimage@0.10.2 @gradio/slider@0.8.2 @gradio/statustracker@0.15.2 @gradio/tabitem@0.8.3 @gradio/tabs@0.10.0 @gradio/theme@0.7.0 @gradio/upload@0.18.2 @gradio/uploadbutton@0.10.2 @gradio/utils@0.14.0 @gradio/vibeeditor@0.3.13 @gradio/video@0.23.0 @gradio/workflowcanvas@0.6.0 gradio@6.21.0 @gradio/image@0.28.1 gradio_client@2.6.0 @gradio/simpletextbox@0.4.2 @gradio/nativeplot@0.13.0 @gradio/code@0.19.0 @gradio/timer@0.5.2 @gradio/textbox@0.14.2 @gradio/model3d@0.18.2 @gradio/state@0.2.5
2026-07-29 19:25:34 +00:00
Dawood Khan a1c3ffc111 fix: recover unpublished 6.21 release (#13690) 2026-07-29 15:07:19 -04:00
Dawood c3c5c67f47 Revert "fix: recover unpublished 6.21 release"
This reverts commit dfdae7a384.
2026-07-29 14:46:30 -04:00
Dawood dfdae7a384 fix: recover unpublished 6.21 release 2026-07-29 14:44:38 -04:00
Gradio PR Bot cf6eb09e39 chore: update versions (#13609)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Dawood Khan <dawoodkhan82@gmail.com>
2026-07-29 12:42:57 -04:00
Abubakar Abid 2d753d0e86 Let API callers supply a token for gr.OAuthToken endpoints (#13667)
* Let API callers supply a token for gr.OAuthToken endpoints

`gr.OAuthToken` was only ever populated from the OAuth session cookie, so it
was always `None` for an API caller — no browser, no session. Any app whose
function takes one could not be driven programmatically at all, which is how
this surfaced: a deployed `gr.Workflow` reached its model nodes with no token
and failed with "Sign in with your HF account to use this model".

Callers can now pass `Client(..., oauth_token=...)`, which travels in the
request body as a reserved `oauth_token` field rather than a header — a Space
sits behind a proxy that strips `x-hf-*`, so a header never arrives. Because it
rides beside `data` instead of in it, it never becomes a positional argument or
appears in an endpoint's parameter schema, and it can't be captured by flagging
or cached examples. It also works from `curl` and any other client, with no
client-side support needed.

A token is sent only to endpoints that declare they take one: `get_api_info`
reports `oauth_token: "required" | "optional"` per endpoint, derived from the
function signature, and the client consults that before including the field. So
an app cannot collect tokens from calls that had no reason to carry one, and
`view_api()` states plainly which endpoints act on the caller's behalf.
`oauth_token=` is deliberately separate from `token=`, which only authenticates
the caller to the app, and is never inferred from a locally saved token.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Support oauth_token in the JS client, and move the e2e test

The JS client gains the same `oauth_token` option and the same gating: it is
included in the payload only for endpoints whose api_info declares they take a
gr.OAuthToken, so parity with the Python client holds and an app still cannot
collect tokens from calls that had no reason to carry one.

The end-to-end check moves into test_external.py, which already hits real
Spaces and is marked flaky and serial, rather than living in a file of its own.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Address review: narrow the token flag, and close two ways to bypass the gate

`oauth_token_requirement` scanned every annotation, including the return type,
so a function that *returned* an OAuthToken was reported as one that receives
one. It now looks only at parameters.

`/call/v2` popped `oauth_token` from every request body, which reserved the name
globally and would swallow a real parameter that happened to be called that. It
is only treated as reserved for endpoints that declare they take a token.

In the client, `**kwargs` expanded after the gated payload, so passing
`oauth_token=` as an ordinary keyword argument would have sent a token to an
endpoint that never asked for one. The computed payload now goes last and wins.

Also reworded a docstring that opened with a quoted word, which `ruff format`
had to space away from the opening triple quote.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Satisfy the backend type checker

`oauth_token_requirement` returned plain `str`, which cannot be assigned to the
`Literal["required", "optional"]` key on the APIEndpointInfo TypedDict, and the
e2e test subscripted `view_api()` (overloaded on return_format) and iterated
client.endpoints without narrowing the value type.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Surface oauth_token in the API docs, and fix the JS client gate

The per-endpoint `oauth_token` requirement reached `/info` but stopped there,
so nothing downstream showed it or acted on it:

- `transform_api_info()` rebuilt each endpoint as {parameters, returns, type},
  dropping `oauth_token`. `submit()`'s gate therefore never matched and the JS
  client never sent a token at all.
- The view-API page said nothing about which endpoints act on the caller's
  behalf, and its snippets omitted `oauth_token` so copy-paste didn't work.
- Sending `oauth_token` to an endpoint that takes no token 500'd on
  `construct_args`; it is now stripped from the args either way and only
  honored where the fn declares one.

Also trims the explanatory inline comments added across the branch.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Make the oauth_token notice font sizes consistent

The first paragraph inherited --text-md while .desc set --text-lg, so the
subdued explanation rendered larger than the primary statement. Both are prose
now at --text-lg, and the inline mono spans drop a step to sit optically level
with it — matching the sibling parameters section (h4 14px, prose 16px, mono
14px).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Stop reserving the oauth_token body key on every endpoint

Popping it unconditionally fixed the 500 on endpoints that take no token, but
it also swallowed the value of any endpoint whose own parameter is named
oauth_token (github-pilot caught this). The name is now reserved only where the
fn declares a gr.OAuthToken; elsewhere it stays an ordinary argument if the
endpoint has one by that name, and is dropped if it does not — so neither the
500 nor the swallowing happens.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 11:48:27 -04:00
hysts 3aa5d5b2af Strip <style> and <link> elements when sanitizing HTML in the frontend (#13662)
* Strip style and link elements in frontend sanitizer

Amuchina's default allowlist permits <style> (HTML and SVG) and
<link>, so chatbot messages containing them could restyle the whole
app even with sanitize_html=True. Configure the browser sanitizer to
drop these elements, matching the server-side sanitize-html defaults.
The style attribute is unaffected.

* add changeset

* Address Copilot review comments

Fail closed if the amuchina default configuration ever lacks
allowElements, instead of skipping the filter. Assert the preserved
style attribute through the DOM instead of exact string equality.

* Hoist the Amuchina instance to module level

The instance is stateless, so there is no need to construct it (and
deep-clone the default configuration) on every sanitize call.

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-29 14:32:19 +09:00
hysts 46e511bd27 Only remount a plot when its payload changes (#13678)
* Remount a plot only when its payload changes

Plot.svelte wraps the plot in {#key key} and incremented key on every
effect run. The effect depends on the value prop, and gr.Chatbot rebuilds
its message objects on every streaming update, so the plot arrived as a
fresh object holding the same payload about 30 times per streamed reply
and each one forced a full remount.

For bokeh that is visible as flickering and as the view jumping between
the top and the bottom of the conversation: re-embedding clears the
container, so the message height collapses to 0 and grows back on every
update.

The remount is deliberate (#9781), so gate it instead of removing it.
PlotData is fully described by type, plot and altair's chart, all
strings, so comparing those three tells a real plot change from a
re-created object. The plot type components already track value in place
through $derived, so nothing else needed to move.

Measured on the issue's app over one plain-text turn after a bokeh plot
was displayed: 33 remounts and 493 px away from the bottom before, 0
remounts and 26 px after.

* add changeset

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-29 14:30:49 +09:00
hysts b844e740de Fix crash when a streaming gr.ChatInterface function yields nothing (#13671)
* Fix crash when chat function yields nothing

A streaming gr.ChatInterface crashed with "RuntimeError: async
generator raised StopAsyncIteration" when the chat function returned
before yielding anything, instead of producing no bot response.

_stream_fn guarded the first-item fetch with `except StopIteration`,
but nothing in that block can raise it: async_iteration is
`await anext(iterator)`, and for sync chat functions
SyncToAsyncIterator has already converted StopIteration into
StopAsyncIteration. The guard has been unreachable since #5116
converted _stream_fn to an async generator without updating the
except clause.

Because the branch was dead, it also never kept up with
additional_outputs (#10071). The event outputs are
[null_component, chatbot] + additional_outputs, so the extra slots
are now padded with skip(), leaving those components untouched
rather than clearing them.

The yield itself has to stay. Yielding nothing sends None for the
chatbot, and the frontend applies that as an empty chat: the
substitution that keeps a normal generator's final payload intact
never runs for a generator that yields nothing.

* add changeset

* Collapse the empty-generator yield to one expression

self.additional_outputs is always a list, so splatting a per-output
skip() covers the no-additional-outputs case too and the branch goes
away.

Build the list with a comprehension rather than `[skip()] * n`: the
latter repeats one dict, and postprocess_data passes prediction dicts
straight into delete_none and postprocess_update_dict, both of which
mutate in place. Harmless while skip() has no "value" key, but there
is no reason to share the dict.

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
2026-07-29 14:28:43 +09:00
hysts 8c69a96eae Stop deep-copying chat messages so components work as chat content again (#13676)
* Don't deep-copy chat messages

A Gradio component used as chat content crashed the app whenever the
component, or the value it held, could not be deep-copied: any component
built inside a `with gr.Blocks()` block (its parent is copied too, so the
copy walks into the Blocks graph and its locks), and gr.Plot holding a
bokeh figure. Both have been broken since 5.9.0.

Three deep copies sit in the path a chat message takes, and none of them
needs to be deep:

- Chatbot._postprocess copied the whole message because
  _postprocess_content mutates the component it is handed, popping
  "value" out of its constructor_args. Build the args dict locally
  instead and leave the caller's component alone.
- ChatInterface._append_message_to_history only appends to the list, so
  a shallow copy is enough.
- Queue.process_events only replaces the top-level "data" key, so a
  shallow copy per event is enough. That site is also why the
  gr.ChatInterface case surfaced as a hang: it runs after the
  prediction, so no completion message reached the client.

Dropping the copy in _postprocess means unrender() acts on the real
component again, which is what that call was there for.

* add changeset

* Address Copilot review

- The comment claimed nothing mutates the caller's component, but
  unrender() a couple of lines above does exactly that. Narrow the
  wording to the constructor args, which is what the change is about.
- Match the timeout other queueing tests use (5s instead of 30s) so a
  failure reports quickly.

* Fix backend typecheck failures

- `ty` does not accept a ChatMessage in Chatbot's `value` (the stub only
  lists MessageDict | Message), so use the dict form, which is what the
  rest of this test file does anyway.
- Give the test's `__deepcopy__` override the signature pydantic's
  BaseModel declares.

* Annotate the test message so ty accepts it

* Fix the ChatMessage route too

Returning a component wrapped in a gr.ChatMessage still crashed:
_message_as_message_dict used dataclasses.asdict, whose _asdict_inner
deep-copies any leaf value before dict_factory ever sees it. That is a
fourth deep copy on the same path, and it is the one a chat function
hits when it attaches metadata (the only way to render a thought), so
"a bokeh plot as a thought" was still broken.

Add utils.shallow_asdict and use it here. ChatMessage has no nested
dataclasses -- metadata and options are TypedDicts -- so dropping the
recursion changes nothing; checked that the output is identical for text,
metadata, options, FileData and list contents.

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
2026-07-29 14:27:18 +09:00
Abubakar Abid eed6ebd38e Report why the Node SSR server failed, and serve without SSR on the expected port (#13681)
* Bundle postcss into the SSR build so ssr_mode works in installed builds

sanitize-html require()s postcss at module load to parse style attributes.
Before the vite 8 upgrade postcss was bundled into the SSR output; after it,
it became external and is looked up at runtime — where the only node_modules
the build output has is the one after_build.js installs. Locally and in CI
the repo's own node_modules satisfies it, so every SSR render 500s only once
gradio is installed from a wheel, which left Python on its internal port and
crashed HF Spaces.

Adds postcss to ssr.noExternal, a post-build check that fails when the SSR
output loads a package it doesn't ship, and surfaces Node's stderr instead of
blaming the Node installation when startup verification fails.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Serve without SSR on the user-facing port when Node can't start

In proxy mode Python binds an internal port and lets Node own the user-facing
one, so a Node server that never serves left the app answering only where
nothing routes — a Space is judged by the user-facing port, so it was reported
as crashed while Python was healthy.

Move Python onto the user-facing port instead and serve client-side rendered.
The new listener is started before the internal one is released, so failing to
take the port leaves the app reachable where it already was.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Detect require calls precisely, and don't overlap the two servers

The build check matched any one-argument call with a string literal as a
require, so `headers.get("cookie")` read as a dependency on the `cookie`
package. It only passed locally because pnpm's layout can't resolve `cookie`
from the build output, while CI's can — the check failed every frontend build.
Resolve `require` through its binding instead: follow the name imported as
`createRequire` to the name its result is bound to, which is what the minified
CJS interop calls. With no false positives left, drop the "resolves in the
repo" filter and treat any unshipped runtime dependency as a failure.

Also close the internal server before binding the user-facing port. The two
share an app, so overlapping them ran its lifespan twice and let the first
server's shutdown delete the app's cache files from under the second. If the
port is lost after releasing ours, go back to the internal one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Report the degraded URL from local_url so it can't print 0.0.0.0

Per Copilot review: start_server already normalizes 0.0.0.0 to localhost when
it builds local_url, so the warning should use that rather than reassembling
the address from server_name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Narrow local_url before the membership check to satisfy the typechecker

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* add changeset

* changes

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-28 22:17:16 -07:00
Dawood Khan f412c6de20 Bundle postcss in standalone SSR builds (#13673)
* Reapply "Fix standalone SSR postcss bundling"

This reverts commit b4ab0ea55f.

* add changeset

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-28 22:04:55 -04:00
Dawood Khan d833d9add1 Fix custom component gallery when backend is unavailable (#13640)
* Fix custom component gallery fallback

* Remove unsupported website test

* Fix gallery fallback CORS

* Remove unsupported website unit test

* Address custom component gallery review feedback
2026-07-28 21:44:36 -04:00
Abubakar Abid 39ef9cae8f AGENTS.md: tell agents not to create changeset files manually (#13682)
* AGENTS.md: tell agents not to write changeset files

The generate-changeset action already commits one to the branch using the PR
title, so a hand-written changeset is redundant — and since the bot leaves an
existing file alone, it quietly replaces the title as the changelog entry.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Move the changeset rule to 7 and trim it

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 17:58:00 -07:00
Hannah 347387984c workflow: add html modality (#13668)
* add html modality

* add changeset

* tweak

* tweak

* fixes

* format

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-28 12:02:53 -07:00
Abubakar Abid d3c70fa5cb Workflow UX improvements, and fix gradio skills add clobbering skills via symlinked dirs (#13666)
* Open the workflow write-access link in a browser tab by default

Launching a `gr.Workflow` locally now opens the write-access link in a new
browser tab automatically, the way `jupyter notebook` opens its token URL,
so you land in an editable canvas instead of a read-only one.

Only done when a browser on this machine is plausibly the right place to
open it: Spaces, headless Linux, containers, CI/pytest, Colab and SSH
sessions keep the previous print-the-link-only behavior. An explicit
`inbrowser=` still wins, and `GRADIO_WORKFLOW_INBROWSER=false` opts out.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Call vision-language models through chat completions in gr.Workflow

`image-text-to-text` mapped to the `visual_question_answering` endpoint,
which no Inference Provider serves for any model on the Hub — the router
routes every model carrying that tag as `conversational`. VLM model nodes
therefore always failed with "Task 'visual-question-answering' not
supported for provider ...", and even where served, VQA has no token
budget for emitting a whole file.

Adds a `chat_completion` endpoint schema (image + prompt → text) and
points `image-text-to-text` at it, on both the Python and canvas side.
Chat images are inlined as data URIs because the provider, not this
process, dereferences them, so a local path or a relative
`/gradio_api/file=` URL is unreachable.

Also adds demo/workflow_vlm_html_comparison, comparing two recent VLMs
on the same screenshot → webpage task.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Don't clobber the installed skill when the agent skills dir is a symlink

`gradio skills add --claude` resolves the agent's skills directory with
`Path.resolve()`, which follows symlinks. When that directory is a link to
the central location — e.g. `.claude/skills -> ../.agents/skills`, a common
way to share one skills dir across agents — the link path collapses onto the
skill that was just installed, so `--force` deleted it and replaced it with
a symlink pointing at itself. Without `--force` it reported the fresh
install as a pre-existing conflict.

Skip linking when the resolved link path is the central skill path: the
skill is already reachable there, and no link is needed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Stream chat completions in gr.Workflow so long generations survive the router

The router returns a bare 504 for a non-streaming /v1/chat/completions
request that takes longer than ~120s to produce its response. A
vision-language model writing a whole file routinely exceeds that — a
reasoning model can spend the entire window before its first visible
token — so image-text-to-text nodes failed with an opaque gateway error
on any non-trivial image. Measured: the same request 504s at 121s
buffered, and runs 308s to completion when streamed.

Stream the response instead, so the request is bounded by the model
rather than by an idle proxy, and raise the token cap to 16384 (sized to
the canvas executor's 300s per-node timeout at the ~100 tok/s these
models stream).

Truncation is now also reported accurately: reasoning counts against
max_tokens, so a model can hit the cap while still thinking and return
no content at all. Say so, with the reasoning volume, instead of
guessing that the prompt was too long.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Cover the auto-opened browser tab and chat-completion dispatch with tests

Both paths were added in this PR without tests, as Copilot noted. The browser
tests assert the parts that are easy to regress: an explicit `inbrowser=True`
opens the write-access URL rather than the read-only one, an explicit `False`
opens nothing even with the env var asking for it, and the auto-open stays
suppressed under pytest, CI and SSH.

The chat-completion tests pin the shape of the request the router receives — a
text part plus an image part, streamed — and the two ways it can come back
empty, since a reasoning model that spends the whole budget thinking needs a
different message than one that was cut off for another reason.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Silence the optional playwright import for the backend type check

The demo's renderer imports playwright lazily and raises a clear install hint
when it is absent, but `ty` resolves imports statically and playwright is not
in the CI environment. Suppressed the same way demo/spectogram handles scipy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 12:02:00 -07:00
Dawood cc34d22d57 test shared prop forwarding in browser 2026-07-28 12:09:05 -04:00
Dawood 9d68a3634d fix shared prop forwarding across components 2026-07-28 11:35:41 -04:00
Dawood 53538a519b Merge remote-tracking branch 'origin/main' into codex/issue-13623-column-variant 2026-07-28 11:25:17 -04:00
Dawood Khan 1535d695af Fix hidden tab focus and label overflow menu (#13639)
* fix tabs accessibility controls

* add changeset

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-28 11:22:48 -04:00
Dawood b4ab0ea55f Revert "Fix standalone SSR postcss bundling"
This reverts commit 065cab0056.
2026-07-27 16:45:57 -04:00
Dawood 065cab0056 Fix standalone SSR postcss bundling 2026-07-27 11:41:05 -04:00
hysts 8647a06d13 Keep fullscreen component controls inside the visible viewport when the page has a scrollbar (#13661)
* Keep fullscreen block inside visible viewport

The fullscreen mode added in #11177 sizes the fixed-position block with
100vw/100vh. Viewport units include the width of a classic window
scrollbar, so the block extended beneath it and the top-right controls
(download, remove image, exit fullscreen) ended up hidden behind the
scrollbar and could not be clicked.

Use percentages instead: for a fixed element they resolve against the
initial containing block, which excludes classic scrollbars. Apply the
same change to the final frame of the pop-out animation.

Add a regression test that reserves a scrollbar gutter and asserts the
fullscreen block and its button wrapper stay within the visible
viewport.

Refs #11982

* add changeset

* Assert button wrapper exists before measuring in test

* Fix two gaps in the fullscreen viewport fix

The `100vw`/`100vh` -> `100%` substitution was missing from the standalone
dataframe, which has its own copy of the `.fullscreen` rule, so the controls
were still hidden behind a classic window scrollbar there.

Percentages on a fixed-position element also resolve against the nearest
ancestor that establishes a containing block for fixed descendants, not the
viewport. `gr.Sidebar` always sets a `transform`, so a fullscreen block inside
one was laid out against the sidebar (already true of `top`/`left` before this
change). Move the block up to the app container while it is fullscreen, but
only when a probe shows the block's position does not resolve against the
viewport, so the common case keeps its DOM position and ancestor-scoped styles.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Compare two probes to decide whether to move the fullscreen block

Comparing a fixed 100% probe against documentElement.clientWidth is wrong when
a scrollbar gutter is reserved: the probe is narrower than clientWidth even
though it already resolves against the viewport, so every fullscreen block was
moved. Compare a probe where the block is with one in the container it would
move to instead, which is also correct if the container itself turns out to
establish a containing block.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Abubakar Abid <islamrealm@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
2026-07-25 10:33:02 -07:00
hysts 80d67add75 Upload recorded audio only once to fix intermittent Content-Length errors when loading recordings (#13660)
* Upload recorded audio only once

Stopping a recording (and trimming one) uploaded the same blob twice
because dispatch_blob couples the upload with firing a single event,
and both "change" and "stop_recording" were dispatched through it.
The second upload rewrites the same content-addressed server path
while the player is already fetching it, which intermittently
truncates the served file and fails with "Too little data for
declared Content-Length" (#7490, #8878, #9739, #13659).

Upload once and invoke the stop_recording callback directly, as the
webcam components already do. Also drop the recorder's self stop()
call that was accidentally re-enabled in the 6.0 merge and the dead
stop_recording dispatch in the streaming stop path, and narrow
dispatch_blob's event union to "stream" | "change".

* add changeset

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-25 12:48:35 +09:00
Abubakar Abid e29c824fd8 Fix @gradio/client packaging: ship real CDN bundle (dist/index.min.js) and CommonJS entry (#13655)
* Fix @gradio/client packaging: real CDN bundle at dist/index.min.js and CJS require entry

- Add a minified, self-contained browser ES module bundle at dist/index.min.js,
  the path documented for jsDelivr CDN usage (#10028)
- Add a CommonJS bundle at dist/index.cjs and a 'require' condition to the
  exports map so require('@gradio/client') works on all supported Node
  versions (#9214 symptom)
- Add 'types' condition / top-level types field
- Update README CDN snippet to the working <script type="module"> import form

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Use fix: prefix in changeset

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address review: CDN build implies browser build; verify dist artifacts after build

- CDN_BUILD=true now forces the browser build path so es+cjs can never
  collide on the same output filename
- Add scripts/verify_dist.mjs, run at the end of 'pnpm build', which fails
  the build if any dist artifact referenced by package.json (exports map,
  main/module/types) was not emitted

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 08:24:44 -07:00
Abubakar Abid 2f6d04acf8 Various improvements to Workflows, particularly for LLM-generated Workflows (#13654)
* Improve Workflow canvas feedback

* add changeset

* Apply suggestions from code review

Co-authored-by: Abubakar Abid <islamrealm@gmail.com>

* Apply suggestion from @abidlabs

* add changeset

* changes

* add changeset

* Fix workflow image generator demo

* add changeset

* Address Workflow review feedback

* Make workflow demo path independent

* Keep Workflow skill generation in sync

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-24 13:27:49 +01:00
Abubakar Abid 72058560a6 Preserve filenames in JS client uploads and use handle_file in generated JS API snippets (#13656)
* Preserve File names in JS client uploads and use handle_file in generated JS API snippets

- handle_file() no longer strips a File down to a bare Blob, and
  walk_and_store_blobs() no longer re-wraps Blobs/Files, so original
  filenames and MIME types survive the multipart upload (fixes #10758).
- The auto-generated JavaScript API snippet now imports handle_file and
  wraps fetched blobs with handle_file() for file-based components
  (fixes the snippet half of #12077).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Guard Buffer instanceof check in handle_file for browser environments

Addresses Copilot review: in browsers without a Buffer polyfill,
`file_or_url instanceof Buffer` threw a ReferenceError before the Blob
branch was reached. Use the same globalThis.Buffer guard as
walk_and_store_blobs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Remove snippet unit tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 19:01:05 -07:00
Abubakar Abid a10b1d75d5 Fix JS client private-Space connections (hf_token alias) and replace raw TypeErrors/unhandled rejections with clear errors (#13657)
* Fix JS client private-Space auth and error handling (hf_token alias, no more raw 'map' TypeErrors / unhandled rejections)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Address Copilot review: trim space_id, slash-tolerant named endpoint lookup, queue flag from skip_queue

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore: trigger CI

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 19:00:11 -07:00
hysts bad052c132 Fix ColorPicker dispatching blur while the user is still using the picker dialog (#13658)
* Fix premature blur in ColorPicker dialog

Clicking inside the opened picker dialog moved focus off the swatch
button and dispatched blur while the user was still using the picker.
Closing the dialog by clicking outside then fired no blur at all,
because the focused element is removed with the dialog and browsers do
not fire focusout for removed elements. Reported in #12896.

Treat the swatch button and the dialog as one focus scope: a wrapper
element listens to focusin/focusout and dispatches focus/blur only when
focus enters or leaves the component, and handle_click_outside
dispatches blur explicitly when it closes the dialog while focus is
inside it.

* add changeset

* Ignore in-component mousedown in click_outside

The click_outside action is bound to the dialog node, so a mousedown
on the swatch button (outside the dialog but inside the component)
also triggered the handler. It unconditionally set dialog_open =
false, which the button's own onclick then toggled back to true, so
clicking the swatch could never close the picker. Early-return when
the mousedown target is inside the wrapper: the swatch onclick owns
the toggle, and the guard also keeps blur from firing on swatch
clicks, replacing the previous wrapper.contains check on the blur
branch.

Strengthen the existing "clicking the swatch again closes the
picker" test to send mousedown before click, matching real browser
behavior; it fails without the guard.

Addresses Copilot review feedback on #13658.

* Narrow click_outside guard to the swatch button

The guard added for the swatch toggle used wrapper.contains, but the
wrapper is an unstyled block element spanning the full column width,
so clicks on the component's empty area hit the wrapper and left the
dialog open (while focusout still dispatched blur). Only the swatch
button needs to be excluded: its mousedown must not close the dialog
or the subsequent onclick toggle reopens it.

Add a regression test clicking the wrapper's empty area; it fails
with the wrapper-wide guard and passes with the button-only guard.

* Keep focus in place on mousedown inside the dialog

With focus on the hex input, a mousedown on a non-focusable area of
the dialog (padding around the sliders, the .input row) moves focus
to body, and the focusout handler sees relatedTarget: null and
dispatches a premature blur while the dialog is still open. The same
path is hit by the mode and eyedropper buttons on browsers where
buttons don't take focus on click (Safari, Firefox on macOS).

Apply the same trick Dropdown uses for its options: preventDefault
on mousedown inside the dialog, except on the text input, which
needs mouse focus for the caret. Slider dragging is unaffected (it
uses its own mousedown handler plus window mousemove/mouseup), and
preventDefault on mousedown does not suppress click, so the buttons
keep working.

Add a regression test that emulates the browser's default mousedown
action (blur the active element unless prevented); it fails without
the preventDefault.

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-24 09:04:43 +09:00
Abubakar Abid 8bdc6439ad Respect custom FRONTEND_DIR in gradio cc dev/build/install (#13650)
* Respect custom FRONTEND_DIR in gradio cc dev/build/install

The CLI hardcoded <component>/frontend as the working directory when
resolving @gradio/preview (and for npm install), so components that
override FRONTEND_DIR on the component class failed with
'Could not find `@gradio/preview`'. Resolve the actual frontend
directory from the installed component class, mirroring examine.py,
with a fallback to the default frontend folder.

Fixes #8162

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Prefer component classes that explicitly override FRONTEND_DIR

Addresses Copilot review: when a package exports multiple component
classes, pick one that defines FRONTEND_DIR (anywhere in its MRO within
the package) rather than whichever class dir() returns first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Retry component import after re-processing site .pth files

Addresses review feedback: on the first `gradio cc install` in a fresh
env, the freshly pip-installed package was not importable in the
already-running CLI process (editable installs register via .pth files,
which are only processed at interpreter startup), so the frontend dir
silently fell back to the default. Retry the import after
importlib.invalidate_caches() + site.main(), and warn when falling back
because the package cannot be imported.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 00:00:12 -07:00
Abubakar Abid 48bdb2c22d Allow frontend builds to skip offline assets (#13653) 2026-07-22 14:25:02 -07:00
Dawood 60a637afad forward all Column props to BaseColumn 2026-07-22 14:41:05 -04:00
Dawood c53d53deeb Merge remote-tracking branch 'origin/main' into codex/issue-13623-column-variant 2026-07-22 14:39:42 -04:00
Abubakar Abid 95369a3dda Fix Windows filename/path handling (reserved names, node probe, file URLs) (#13622)
* Fix Windows filename and path handling across uploads, node lookup, and preview

Prefix reserved DOS device names in strip_invalid_filename_characters, silence where/which node stderr, and use proper file:// URLs for Windows paths.

Co-authored-by: Cursor <cursoragent@cursor.com>

* add changeset

* Keep Model3D unhandled rejection suppressor active for full test run

Babylon.js can reject after the file-level afterAll removed the listener, causing flaky js-test failures.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Check first dot segment for Windows reserved device names

Windows resolves device names from the segment before the first dot
(NUL.tar.gz is the NUL device), but the check used os.path.splitext,
which splits on the last dot, letting names like CON.tar.gz through.
Match CPython's ntpath.isreserved instead, and extend the reserved set
with CONIN$/CONOUT$ and the superscript COM/LPT variants.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 00:49:47 -07:00
Dawood 0976b26870 forward only the Column variant prop 2026-07-21 14:19:01 -04:00
Hannah d07af9ddb7 workflow: add model endpoint integration (#13558)
* improve workflow API with model endpoint integration

* improve workflow model nodes with endpoint explicit dispatch and port UX

* format

* add changeset

* format

* lint errors

* fix N806 linter error in test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* revert

* address copilot comments

* format

* remove optional params

* fix test_schema_structure after optional params removal

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* format

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* address review: consolidate model dispatch through endpoint schemas

- Route legacy positional (list) args through _INFERENCE_ENDPOINT_SCHEMAS +
  _dispatch_model_endpoint instead of a parallel per-task if/else chain,
  and delete _apply_args (with its ambiguous image_positions param).
- Remap legacy in_N port IDs onto schema input names so API calls against
  workflows saved before endpoint schemas don't TypeError.
- Fix zero_shot_classification signature (candidate_labels, not labels),
  coerce string ports into the list params zero-shot/sentence-similarity
  expect, and fall back to text_classification when no labels are given.
- Remove depth_estimation from endpoint schemas — InferenceClient has no
  such method; those models keep the raw-POST branch. Also drop the dead
  mask_generation/text_to_audio output-ext entries.
- Raise a clear upgrade-hint error when the installed huggingface_hub
  lacks an endpoint method, and only advertise supported endpoints from
  get_model_endpoints.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* add inference text

* - update huggingface_hub
- update scroll drop menu
- move outputs to the top of drop menu

* format

* edit titles + format

* tweak card ui

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Abubakar Abid <islamrealm@gmail.com>
2026-07-21 19:05:44 +01:00
Dawood f0abb1ea8e fix column variant forwarding 2026-07-20 12:29:27 -04:00
Dawood e6c58d5d6d Revert accidental custom component gallery push 2026-07-20 12:03:45 -04:00
Dawood d47a3471e4 Fix custom component gallery fallback 2026-07-20 12:02:02 -04:00
Hannah a2ddecfb29 workflow: ensure we handle trailing null values (#13616)
* handle null inputs

* format

* add changeset

* lint

* init with default

* add changeset

* tweak

* format

* add changeset

* remove empty

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-18 01:08:17 +01:00
Abubakar Abid 3b12faa404 Keep in-flight events working when an app is hot-reloaded (#13627)
* Fix in-flight events breaking when an app is hot-reloaded

When running `gradio app.py`, saving the file while a function (especially
a generator) is mid-run caused every subsequent yield to fail with
"Returned component ... not specified as output of function" or a KeyError
in the state holder, because the event kept processing against a mix of
old and new blocks config.

- Remap pending/running queue events to the new app's BlockFunction
  (matched by api_name) when blocks are swapped after a reload
- Re-read the event's fn on each generator iteration in the queue loop
- Fall back to matching returned dict components to outputs by key when
  the component object is stale
- Carry over pending streaming/diff state so in-flight generators keep
  sending diffs instead of resetting the stream protocol

Fixes #8712

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Fix type check failure in reload Event test

Pass a real fastapi.Request instead of None so ty accepts Event construction.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Handle output components added during a hot reload

When a generator is mid-run and the app is hot-reloaded to add a new output
component, the reassigned function emits an update for a component that is not
yet in the session config, and the diff stream gains an extra output.

- Guard the state lookup in postprocess_data so an update for a freshly-added
  output falls back to the block's own constructor args instead of KeyError
- Add SessionState.get for the above
- Grow the Python client's diff buffer when a new output appears mid-stream
- Start unseen outputs from null in the JS client's diff stream

Relates to #8712

Co-authored-by: Cursor <cursoragent@cursor.com>

* changes

* Address Copilot review: snapshot queue collections during reload, catch settled() rejection

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test: cover in-flight generator streaming across hot reload

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix Prettier formatting in state.svelte.ts

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Fix hot reload rebinding across repeated reloads

* Stabilize chatbot feedback browser test

* Preserve loading status when dependency ids shift on reload

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-17 12:06:45 -07:00
Hannah 0286f2c2f7 workflow: use anyio.to_thread to send sync server functions to thread pool (#13612)
* run server funcs in thread pool with asyncio

* add changeset

* lint

* add changeset

* rm import

* use anyio + add test

* limit call_fn concurrency

* format

* test fix

* refactor

* add changeset

* clean up

* format + lint

* typefix

* move import

* tweak

* rm direct call_fn tests

* rm call_fn server function

* add sanitized name error

* lint

* format

* fix test

* tweak

* format

* add changeset

* add flag for unicode

* add blocks check

* use gr.api() to register bound fn endpoints

* save lock

* trigger job.cancel() on abort

* prevent race in image editor

* format

* format

* error tweak

* revert

* wrap bound fn exceptions as gr.Error

* format

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-17 14:25:29 +01:00
hysts 7d714699ae Reset audio playback position when the file is cleared or a new one is uploaded (#13626)
* Reset audio playback position on clear and upload

An interactive gr.Audio kept the previous file's playback position
after the user cleared it and uploaded a new file, because the
two-way bound playback_position prop (added in #12504) outlives the
player: clearing unmounts the player and the freshly mounted one
treats the leftover value as a backend-set position and seeks there.

Reset playback_position to 0 in clear() and handle_load(), the two
user actions that discard the current file. Backend-driven updates,
including setting a new value and a position together, are untouched.

Fixes #13273

* add changeset

* Update audio clear() state before callbacks

Per review feedback: reset value and playback_position before firing
onchange/onclear, so event handlers never observe half-updated state
regardless of when input data is gathered.

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-17 09:13:48 +09:00
pngwn 7ac583a38a Make builds go zoom zoom (#13329)
* changes

* fix tests

* format

* clean

* add changeset

* fix

* add changeset

* fix more

* add changeset

* fix more more

* add changeset

* ci: bound js-test step + add browser-mode debug logs

The js-test step has been hanging 6h+ in CI on this branch. Investigation
confirms the runner is *stuck*, not slowly executing tests: vitest's
default per-test timeout (5s) and per-hook timeout (10s) only apply
inside test execution, but the orchestrator's prepareIframe awaits
iframe.onload/onerror with no timeout — so a stuck Vite transform or
unresponsive chromium iframe blocks forever.

Cap the step at 10 min (locally completes in ~25s) so failures surface
fast instead of consuming a runner for 6 hours, and enable
DEBUG=vitest:browser:* + --reporter=verbose so the next failed run
shows where the orchestrator was waiting.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* gitignore

* fix(ci): prevent vite optimizer reload from hanging js-test

Root cause of the 6h js-test hang: vitest browser mode can't tolerate a
full-page reload mid-suite. Vite's dep optimizer fires "optimized
dependencies changed. reloading" when it discovers a dep that wasn't in
its initial bundle — this disrupts the iframe orchestrator, whose
iframe.onload listener has no timeout (orchestrator-DM4mHHP0.js:164),
so iframes silently lose their socket and the orchestrator awaits
forever.

Two complementary fixes:

1. Pre-declare runtime dynamic-import deps (katex, mermaid, vega-embed,
   babylonjs viewer, extendable-media-recorder) in `optimizeDeps.include`.
   Vite's static scanner doesn't follow `await import(...)` calls, so
   without the include list these were discovered mid-test and forced
   the reload. With them included, all known deps end up in the same
   first optimize batch.

2. Cache `node_modules/.vite` between CI runs and pre-warm the optimizer
   with `vitest list` before the real test step. The cold-start reload
   (which fires once even with `include`, when the cache is empty)
   then happens during the throwaway prewarm — the real test step
   always sees a warm cache and never reloads.

Local verification: cleared cache + run = 3-5 file failures from the
reload. With these changes: 1685/1685 pass, no reload.

The `timeout-minutes: 10` on the test step ensures any future regression
fails visibly in 10min instead of consuming a runner for 6 hours.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(e2e): wait on stronger chain-drain signals in flaky specs

Two functional specs flaked in CI on this branch — at the failure
moment, the Gradio queue still had inflight events. Both already use
deterministic final-state assertions, the failure was just that 10s
isn't enough on a CI runner where 60+ chained events serialize through
one queue.

rapid_generation: switch the chatbot wait from message 11 (halfway) to
message 22 (last in the 22-event chain). Once that message renders the
chatbot chain is fully drained, leaving only a handful of pending
number-chain events. Bump the chatbot wait to 30s so the slow run gets
the headroom.

theme_builder: bump the font-family and background-color assertions to
30s. Loading a theme round-trips through the queue + ships CSS vars +
waits for the browser to apply them — that pipeline can exceed the 10s
default on slow CI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* remove Slider playwright-ct spec

The Slider component test failed under the upgraded svelte 5.55 +
vite-plugin-svelte 7 stack: playwright-ct passes plain objects for
component props, but the Gradio class direct-aliases `_props.props`
without an internal $state copy, so two-way `bind:value` doesn't
propagate in the CT environment. The failing assertions were on
range→number sync.

The same flows are covered (more comprehensively) by the existing
vitest unit tests in `Slider.test.ts`: number/range sync, value
clamping, change/input/release events, reset button behavior, and
accessibility — all of which run under the test infra's reactive
proxy wrapper in `tootils/render.ts`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* unblock SSR functional tests on the upgraded svelte stack

- skip custom_css `.dark styles` test in SSR mode. Under svelte 5.55 +
  vite-plugin-svelte 7 the user CSS `.dark .darktest h3` selector ties on
  specificity with gradio's prefixed `.prose h3` rule and loses on
  load-order in the SSR build. The companion `applies the custom CSS
  styles` test in this file is already skipped in SSR for similar
  reasons; tracking the load-order regression as a follow-up.

- give render_tests its own 60s timeout. The demo is render-heavy
  (multiple `@gr.render` blocks, sliders, chatbots) and its SSR hydration
  occasionally pushes past the 30s default while the setup fixture is
  waiting for `#svelte-announcer`, manifesting as flaky setup timeouts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix e2e?

* fix story

* format

* fix story again

* fix(reload): push new server props into reused component instances

Reload mode (`gradio <demo>` with watchdog) was failing to update the
UI when components changed shape across a source-file edit. Tests
hitting this: allowed_paths.reload, hello_blocks.reload (label changes,
component swaps).

Root cause: the Gradio<T,U> class in `js/utils/src/utils.svelte.ts`
direct-aliases `_props.shared_props`/`_props.props` at construction
(load-bearing for @gr.render user-edit preservation — see comments
there). On reload, AppTree.reload() builds a new node tree with new
ids and new prop objects. MountComponents matches children by position
(unkeyed each), so the same component instances get reused — but the
Gradio class inside each one keeps aliasing the OLD node's props. The
new label/value/etc. never lands.

`AppTree.rerender()` already handles the analogous case for @gr.render
via #sync_reused_components_after_rerender — walks the new subtree
and pushes only-defined keys via set_data, skipping undefined values
so locally-edited fields survive. The id-change effect in the Gradio
class re-registers the set_data callback under the new id, and
#pending_updates queues anything that arrives before re-registration.

Fix: call the same sync routine at the end of `reload()`. Same trade-
offs apply as @gr.render — server-defined props propagate, locally-
edited values (server omits them) are preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* clean up

* fix

* fix

* fix

* add changeset

* fix

* chore(tabs): remove debug logging and stale comments

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* format

* add changeset

* fix?

* fix site

* format

* fix

* format

* fix error

* add changeset

* fix

* format

* Fix frontend profiling base gradio install

* fix(ci): run frontend benchmark against installed gradio

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: hannahblair <hannahblair@hotmail.co.uk>
Co-authored-by: Dawood <dawoodkhan82@gmail.com>
2026-07-16 16:57:19 -04:00
Abubakar Abid ec3c6735a1 docs: expand security policy and reporting guidance (#13625)
* docs: expand security policy guidance

* docs: add Gradio team security contact
2026-07-15 10:19:34 -07:00
Abubakar Abid 520023532b Fix chained events after cancellation and in hidden tabs (#13620)
* Fix chained events in cancellation and hidden tabs

* changes
2026-07-15 00:56:34 -07:00
Abubakar Abid 195593ed27 Fix component remounting in gr.render (#13613)
* Fix component remounting in gr.render

* Narrow gr.render HTML remount fix

* Regenerate Gradio skill examples

* Scope HTML watchers to rendered component

* Clean up HTML remount side effects
2026-07-14 21:12:29 -07:00
Hannah d5ef8972df workflow: fix error banner and textarea visibility (#13590)
* fix error banner and textarea visibilty

* add changeset

* format

* add changeset

* tweak

* tweaks

* format

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
2026-07-14 23:42:34 +01:00
Abubakar Abid 0ee5cc80e2 Preserve proxy ports in frontend asset URLs (#13601)
* fix frontend proxy asset urls

* Fix SSR login flash and tighten proxy-origin URL rewriting

- Client.connect no longer rejects when fetching /info fails, which was
  making the SSR server render a spurious login page ("Could not get API
  info") before hydration recovered.
- resolve_current_origin_url only adopts the page origin when the page is
  actually served by the gradio server (window.gradio_config present or an
  explicit current_location), so same-host embeds and the vite dev server
  keep the backend's own origin.
- Align the iframeResizer loader in index.html with the shared helper
  (hostname-only match) so it also works behind protocol-changing proxies.
- Revert the App.configure_app root_path merge: preserving FastAPI's
  constructor root_path made mounted apps with app_kwargs root_path 404.
- Drop the js/upload re-export indirection and its duplicated test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Run window-fallback URL tests only in browser mode

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Use msw runtime overrides instead of replacing initial handlers in client test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: choose installable gradio release for frontend profiling

* test: avoid raw github downloads in component fixtures

* Address review: remove changesets, simplify base install to plain pip install, drop client test and conftest github mock

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* add changeset

* Fix remaining proxy request and root path regressions

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
2026-07-13 18:25:49 -07:00
Abubakar Abid 643fb05b51 Restore gradio_client release tags (#13614)
* Restore gradio_client release tags

* Keep gradio_client private while tagging releases

* Create annotated client release tags

* Make client tag annotation explicit
2026-07-13 10:41:44 -07:00