## Summary
Expands the wait step in `pr-claude-review.yaml` so the
`lewagon/wait-on-check-action` accepts every terminal GitHub conclusion
instead of failing on outcomes like cancelled or failure. After the wait
completes, the `check-status` script still inspects those check runs and
only marks `should-proceed=true` when the tracked jobs finished
successfully.
Fixes what happened here:
https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/18828179272/job/53714488799?pr=6298
## Summary
Updates `SurveyResponses` interface to match actual survey fields 1-to-1
based on analytics requirements.
## Changes
- Remove `team_size` property (no corresponding survey question exists)
- Change `use_case` to `useCase` to match actual survey field name
- Remove `intended_use` property (doesn't exist in actual survey)
- Add `making` field array for content generation type tracking (video,
image, etc.)
This fixes a Mixpanel analytics issue where survey properties weren't
mapping 1-to-1 with actual survey questions, making statistical analysis
difficult.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6314-bugfix-fix-survey-properties-mapping-to-match-actual-survey-data-2996d73d36508158a335e6b73e3e14ef)
by [Unito](https://www.unito.io)
## Summary
Split mask editor structure into smaller files
## Changes
This PR is a prerequisite step for [the issue - refactoring the mask
editor using
Vue](https://github.com/Comfy-Org/ComfyUI_frontend/issues/5956). It
splits the current monolithic maskeditor.ts (about 5700 lines) into
separate files; otherwise, the original single file would be very
difficult to analyze or maintain.
This PR itself does not introduce any Vue, nor should it have any
functional changes or modifications. It's purely a code-level split,
with all related files placed in the maskeditor folder.
The original maskeditor.ts has been renamed to maskeditor.ts.backup for
future reference.
## Review Focus
Since this PR is only for splitting purposes, all logic remains
consistent with the original. Therefore, for any reviewer: any code
logic improvements should happen in the subsequent Vue-based
refactoring, not in this PR.
Following this PR, I will perform a Vue-based refactoring of the mask
editor to align with the frontend's overall Vue architecture and provide
better cloud-related support.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6308-refactor-Split-mask-editor-into-smaller-files-2986d73d36508131937dd43e465a47bd)
by [Unito](https://www.unito.io)
## Summary
Track template metadata in English for analytics regardless of user's
locale to enable consistent statistical analysis.
## Changes
- **What**: Load English [template
index](https://github.com/Comfy-Org/ComfyUI_frontend/tree/main/public/templates)
alongside localized version (cloud builds only)
- **What**: Added `getEnglishMetadata()` method to
`workflowTemplatesStore` that returns English versions of template tags,
category, useCase, models, and license
- **What**: Updated `MixpanelTelemetryProvider` to prefer English
metadata for analytics events, falling back to localized values
## Review Focus
English template fetch only triggers in cloud builds via `isCloud` flag.
Non-cloud builds see no bundle size impact. Method returns null when
English templates unavailable, with fallback to localized data ensuring
analytics continue working in edge cases.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6292-translate-all-analytics-to-English-for-template-metadata-2986d73d365081fdbc21f372aa9bb41e)
by [Unito](https://www.unito.io)
---------
Co-authored-by: github-actions <github-actions@github.com>
## Summary
Backport outputs from new cloud history endpoint
Does:
1. Show history in the Queue
2. Show outputs from prompt execution
Does not:
1. Handle appending latest images generated to queue history
2. Making sure that workflow data from images is available from load
(requires additional API call to fetch)
Most of this PR is:
1. Test fixtures (truncated workflow to test).
2. The service worker so I could verify my changes locally.
## Changes
- Add `history_v2` to `history` adapter
- Add tests for mapping
- Do branded validation for promptIds (suggestion from @DrJKL)
- Create a dev environment service worker so we can view cloud hosted
images in development.
## Review Focus
1. Is the dev-only service work the right way to do it? It was the
easiest I could think of.
4. Are the validation changes too heavy? I can rip them out if needed.
## Screenshots 🎃https://github.com/user-attachments/assets/1787485a-8d27-4abe-abc8-cf133c1a52aa
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6288-Feat-history-v2-outputs-2976d73d365081a99864c40343449dcd)
by [Unito](https://www.unito.io)
---------
Co-authored-by: bymyself <cbyrne@comfy.org>
## Summary
Fixes Pinia initialization error that occurred when the auth service
worker tried to access stores before Pinia was set up.
## Problem
The auth service worker was being imported at the top of `main.ts`,
causing it to register immediately:
```typescript
import '@/platform/auth/serviceWorker' // Runs immediately on import
```
This happened before Pinia was initialized, causing an error when the
service worker setup tried to use stores:
```
Error: [🍍]: "getActivePinia()" was called but there was no active Pinia.
```
## Solution
Moved the service worker registration to after Pinia is set up but
before mounting the app:
```typescript
.use(pinia)
.use(i18n)
.use(VueFire, {
firebaseApp,
modules: [VueFireAuth()]
})
// Register auth service worker after Pinia is initialized (cloud-only)
if (isCloud) {
void import('@/platform/auth/serviceWorker')
}
app.mount('#vue-app')
```
## Benefits
- ✅ Pinia stores are available when service worker setup runs
- ✅ Still tree-shaken for non-cloud builds via dynamic import in `if
(isCloud)`
- ✅ Registers before mounting, so service worker is active from the
start
## Testing
- Verified no Pinia errors in cloud builds
- Verified tree-shaking still works (service worker code not in
localhost builds)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6272-bugfix-fix-service-worker-registration-timing-to-run-after-Pinia-setup-2976d73d365081b998dfd2eded782070)
by [Unito](https://www.unito.io)
## Summary
Removes the checkbox from the sign up form to simplify the user
experience. The "By clicking 'Next' or 'Sign Up'..." notice at the
bottom already covers terms and privacy.
## Changes
- Removed checkbox field from sign up schema
- Updated `SignUpForm.vue` component
- Removed unused `Checkbox` import
## Before/After
**Before:**
Sign up form included a checkbox that users had to check before
submitting
**After:**
Sign up form is cleaner without the checkbox. The existing notice text
covers the same information:
> "By clicking 'Next' or 'Sign Up', you agree to our Terms of Use and
Privacy Policy."
This notice appears on both sign in and sign up modals.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6269-remove-checkbox-from-sign-up-form-2976d73d3650819ab480e4db6685baee)
by [Unito](https://www.unito.io)
## Summary
Fixes CORS errors in HTTPS environments where the auth service worker
blocked cross-origin redirects to Google Cloud Storage.
## Problem
The service worker was using `mode: 'same-origin'` which prevented
following redirects when `/api/view` returns a 302 redirect to GCS:
```
Unsafe attempt to load URL https://storage.googleapis.com/...
from frame with URL https://testcloud.comfy.org/auth-sw.js.
Domains, protocols and ports must match.
```
This only occurred in HTTPS/cloud environments where media is served
from GCS. Localhost/HTTP test environments serve files directly without
redirects, so the issue wasn't caught there.
## Solution
Changed redirect handling from automatic to manual:
1. **Initial request to `/api/view`**: Sends WITH auth headers
(validates user access)
2. **Detect redirect response**: Checks for 301/302/opaqueredirect
3. **Follow redirect to GCS**: Fetches WITHOUT auth headers (signed URL
has built-in auth)
### Key Changes
- Removed `mode: 'same-origin'` (was blocking cross-origin redirects)
- Changed `redirect: event.request.redirect` to `redirect: 'manual'`
- Added manual redirect handling that follows to GCS without Firebase
auth headers
## Why This Works
The two requests have different authentication mechanisms:
- **`/api/view` request**: Uses Firebase auth header (backend validates
user access)
- **GCS request**: Uses signed URL with query params (`Signature=...`,
`GoogleAccessId=...`, `Expires=...`)
The security check still happens on the initial `/api/view` request, but
we allow the redirect to GCS to use its own authentication system.
## Testing
- Typecheck passed
- Should be tested in HTTPS cloud environment with media files stored in
GCS
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6265-bugfix-fix-auth-service-worker-to-handle-cross-origin-redirects-to-GCS-2976d73d365081d0b124db4918f8194e)
by [Unito](https://www.unito.io)
`LLink.disconnect` is intended to cleanup only the link itself. #4800
mistakenly assumed that it would perform all required steps for
disconnection. Later, #5015 would partially resolve this by adding some
of the missing functionality into `LLink.disconnect`, but this still
left output cleanup unhandled and failed to call
`node.onConnectionsChanged`.
This PR instead moves the disconnection code to call the function that
already has robust handling for these items and removes the
no-longer-needed and potentially misleading workaround.
Resolves#6247
Also un-skipped several SubgraphIO tests. They appear to function fine.
I'm assuming the reasons for them being skipped have been resolved.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6258-Fix-disconnection-of-subgraphInput-links-2966d73d36508112ad1fe602cdcf461b)
by [Unito](https://www.unito.io)

Resolves#4887
<details>
<summary>The dirty details</summary>
There's really not a cleaner workaround here. Prime vue is hardcoded to
hide results when a query is received with length 0. With our search
box, we never want completions not to be shown and the sanest, if not
the only viable solution, is to simply block the hiding completely.
Future TODO:
- Completely remove the reFocusInput jank. If we can make the search box
a frame more responsive, we should.
```ts
onInput(event) {
if (this.typeahead) {
if (this.searchTimeout) {
clearTimeout(this.searchTimeout);
}
let query = event.target.value;
if (!this.multiple) {
this.updateModel(event, query);
}
if (query.length === 0) {
this.hide();
this.$emit('clear');
} else {
if (query.length >= this.minLength) {
this.focusedOptionIndex = -1;
this.searchTimeout = setTimeout(() => {
this.search(event, query, 'input');
}, this.delay);
} else {
this.hide();
}
}
}
}
hide(isFocus) {
const _hide = () => {
this.$emit('before-hide');
this.dirty = isFocus;
this.overlayVisible = false;
this.clicked = false;
this.focusedOptionIndex = -1;
isFocus && focus(this.multiple ? this.$refs.focusInput : this.$refs.focusInput?.$el);
};
setTimeout(() => {
_hide();
}, 0); // For ScreenReaders
}
```
</details>
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6231-Show-default-node-list-after-clearing-search-input-2956d73d36508134960df537c7409646)
by [Unito](https://www.unito.io)
This pull request updates the workflow for managing Playwright
expectation snapshots in
`.github/workflows/pr-update-playwright-expectations.yaml`. The main
focus is to improve how changed snapshot files are handled, ensuring
directory structures are correct and only necessary files are processed
and committed. The most important changes are grouped below:
**Snapshot file handling improvements:**
* When copying changed snapshot files, the workflow now strips the
`browser_tests/` prefix to avoid double nesting in the staging
directory. This ensures the directory structure remains correct when
files are merged back.
* During the merging step, the script clarifies that files are already
in the correct structure (without the `browser_tests/` prefix), so they
can be copied directly into `browser_tests/`.
**Workflow and commit logic enhancements:**
* The snapshot artifact download step is renamed for clarity, indicating
that only changed snapshot files are downloaded from shards.
* The commit step is improved to check for actual changes in
`browser_tests/` before attempting to commit and push. It sets an output
variable (`has-changes`) to control subsequent steps, adds more
informative logging, and only pushes when there are changes.
* The "Add Done Reaction" step is now conditional on both the event type
and whether there were changes to commit, preventing unnecessary
reactions.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6252-Hotfix-CI-update-test-expectations-2966d73d36508131968ee5a7f04ff787)
by [Unito](https://www.unito.io)
---------
Co-authored-by: github-actions <github-actions@github.com>
This pull request updates the Playwright snapshot update workflow to
improve efficiency and clarity. The workflow now only uploads and merges
changed snapshot files from each shard, reducing unnecessary artifact
size and processing. It also adds better logging and summaries for
easier debugging and review.
**Snapshot handling improvements:**
* Only changed snapshot files are identified, staged, and uploaded as
artifacts per shard, instead of uploading all snapshot files. This
reduces artifact size and upload time.
* During the merge step, only the changed files from each shard are
merged back into the `browser_tests` directory, preserving directory
structure and avoiding redundant operations.
**Logging and debugging enhancements:**
* Added steps to list downloaded snapshot files and summarize the
changes after merging, making it easier to see what was updated and
debug any issues.
Sample run is here
https://github.com/Myestery/ComfyUI_frontend/actions/runs/18768857441
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6250-Patch-Update-expectations-CI-2966d73d365081b790a0fad66649a10b)
by [Unito](https://www.unito.io)
## Summary
Implements server-side remote configuration to decouple runtime behavior
from build artifacts, enabling dynamic configuration updates without
redeployment.
## Technical Changes
- **Replaced** build-time constants (`__MIXPANEL_TOKEN__`,
`__BUILD_FLAGS__`) with runtime configuration loaded from
`/api/features`
- Configuration now sourced from `window.__CONFIG__` (hydrated from
`/api/features` endpoint)
- **Added** `src/platform/remoteConfig/` service that polls server
configuration every 30 seconds
- **Modified** application bootstrap sequence in `main.ts` to load
remote config before module initialization (required for cloud builds)
- **Removed** global constants: `__BUILD_FLAGS__`, `__MIXPANEL_TOKEN__`.
Runtime subscription enforcement toggle via `subscription_required` flag
- Server health alerts with variant-based severity rendering
(info/warning/error) via topbar badges
## Rationale
- **Build-once-deploy-anywhere**: Single immutable artifact promoted
through environments (staging → production)
- **Zero-downtime configuration**: Update behavior without rebuilding or
redeploying the application
- **Incident response**: Disable features or display alerts dynamically
in response to outages or degraded service
- **Instant rollback**: Revert configuration changes server-side without
artifact redeployment
- **Progressive delivery**: Enable A/B testing, canary releases, and
user/region-based configuration
- **Environment parity**: Eliminate configuration drift between staging
and production builds
- Decouples deployment cadence from configuration changes
- Enables GitOps workflows for configuration management separate from
code deployments
- Supports real-time operational control of client behavior
- Reduces build matrix complexity (no per-environment builds)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6246-change-cloud-feature-flags-to-be-loaded-dynamically-at-runtime-rather-than-set-in-build-2966d73d3650811cbb41c9093961037a)
by [Unito](https://www.unito.io)
When a widget is linked to a subgraph, the subgraph creates a copy of
the widget. The callback used by the asset browser to update the widget
still refers to the widget that lives inside the subgraph, but at time
of execution, this is overwritten by the unchanged value of the copy.
This is fixed by instead updating the value of the caller. It's a little
hacky, and may need future review.
See also #6237
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6240-Fix-asset-browser-on-subgraph-nodes-2956d73d365081b49bd1cd1a7a254763)
by [Unito](https://www.unito.io)
## Summary
Enables Vue nodes to resize from all four corners and consolidated the
interaction pipeline.
## Changes
- **What**: Added four-corner handles to `LGraphNode`, wired them
through the refactored `useNodeResize` composable, and centralized the
math/preset helpers under `interactions/resize/` with cleaner pure
functions and lint-compliant markup.
## Review Focus
Corner-to-corner resizing accuracy (position + size), pinned-node guard
preventing resize start, and snap-to-grid behavior at varied zoom
levels.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6187-allow-Vue-nodes-to-be-resized-from-all-4-corners-2936d73d365081c8bf14e944ab24c27f)
by [Unito](https://www.unito.io)
---------
Co-authored-by: DrJKL <DrJKL@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
## Summary
Centralized all download functionalities across app. Then changed
downloadFile on the cloud distribution to stream assets via blob fetches
while desktop/local retains direct anchor downloads. This fixes issue
where trying to download cross-origin resources opens them in the
window, potentially losing the user's unsaved changes.
## Changes
- **What**: Moved `downloadBlob` into `downloadUtil`, routed all callers
(3D exporter, recording manager, node template export, workflow/palette
export, Litegraph save, ~~`useDownload` consumers~~) through shared
helpers, and changed `downloadFile` to `fetch` first when `isCloud` so
cross-origin URLs download reliably
- `useDownload` is the exception since we simply cannot do model
downloads through blob (forcing user to transfer the entire model data
twice is bad). Fortunately on cloud, the user doesn't need to download
models locally anyway.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6188-refactor-centralize-all-download-utils-across-app-and-apply-special-cloud-specific-behav-2946d73d365081de9f27f0994950511d)
by [Unito](https://www.unito.io)