This pull request makes a small change to the
`.github/workflows/pr-update-playwright-expectations.yaml` file,
removing the unconditional `if: always()` condition from the
`merge-and-commit` job. This means the job will now only run if its
dependencies succeed, rather than always running regardless of previous
job outcomes.
This pull request significantly refactors the Playwright expectations
update workflow to improve reliability, efficiency, and maintainability.
The workflow is now split into three coordinated jobs—setup, sharded
snapshot updates, and merge/commit—enabling parallel test execution and
artifact management. Key improvements include sharding Playwright
snapshot updates, robust caching and artifact handling, and more
reliable PR context handling.
**Workflow Restructuring and Sharding:**
* The workflow is split into three jobs: `setup` (prepares environment
and caches it), `update-snapshots-sharded` (runs Playwright snapshot
updates in four parallel shards), and `merge-and-commit` (merges results
and commits updates). This enables faster, more reliable snapshot
updates.
[[1]](diffhunk://#diff-0289f4b5962314fa2d58937651c3d2a0f2c6f76e26c95d6a04d43c18b3449917L15-R15)
[[2]](diffhunk://#diff-0289f4b5962314fa2d58937651c3d2a0f2c6f76e26c95d6a04d43c18b3449917R27-R175)
**Caching and Artifact Management:**
* The setup job builds and caches the entire workspace, which is then
restored by each shard for consistent environments. Each shard uploads
its updated snapshots and test reports as artifacts, which are later
downloaded and merged in the final job.
**Improved PR Context Handling:**
* PR number, branch, and comment IDs are now reliably extracted and
passed between jobs using outputs, ensuring correct association with the
PR throughout the workflow (e.g., for commenting, reactions, and pushing
updates).
[[1]](diffhunk://#diff-0289f4b5962314fa2d58937651c3d2a0f2c6f76e26c95d6a04d43c18b3449917R27-R175)
[[2]](diffhunk://#diff-0289f4b5962314fa2d58937651c3d2a0f2c6f76e26c95d6a04d43c18b3449917L92-R199)
**Job and Step Renaming/Cleanup:**
* The main job is renamed from `test` to `setup`, and redundant or
unnecessary steps (such as the old branch SHA extraction) are removed
for clarity and maintainability.
[[1]](diffhunk://#diff-0289f4b5962314fa2d58937651c3d2a0f2c6f76e26c95d6a04d43c18b3449917L15-R15)
[[2]](diffhunk://#diff-0289f4b5962314fa2d58937651c3d2a0f2c6f76e26c95d6a04d43c18b3449917R27-R175)
**Comment and Label Automation Improvements:**
* Automated GitHub comment reactions and label removals now use the
correct PR context, ensuring that feedback and status updates are
reliably posted to the right place.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6100-Shard-Update-Test-Expectations-PR-28f6d73d36508109bcd8d382c942d44d)
by [Unito](https://www.unito.io)
---------
Co-authored-by: sno <snomiao@gmail.com>
Note for reviewers: the code changes in src/* is because I've upgraded
prettier to latest.
the @prettier/plugin-oxc it self only improve performance and doesnt
affect format rules
## Summary
Integrates `@prettier/plugin-oxc` to improve Prettier performance by
~20%.
The oxc plugin provides a faster parser written in Rust, significantly
speeding up formatting operations across the codebase.
## Changes
- Added `@prettier/plugin-oxc` as dev dependency
- Updated `.prettierrc` to use oxc plugin alongside existing
sort-imports plugin
- Added `scripts/benchmark-prettier.js` to measure performance
improvements
- Updated `knip.config.ts` to ignore the oxc plugin
- Updated `eslint.config.ts` to ignore the benchmark script
## Benchmark Results
Ran 3 benchmarks comparing formatting performance on the entire
codebase:
**Without oxc:**
- Median: 32.76s
- Average: 32.89s
- Min: 32.49s
- Max: 33.43s
**With oxc:**
- Median: 26.13s
- Average: 26.35s
- Min: 25.24s
- Max: 27.69s
**Improvement: 20.26% faster (6.64s saved)**
## Testing
The benchmark script can be run with:
```bash
node scripts/benchmark-prettier.js
```
This will:
1. Test formatting performance without oxc plugin
2. Test formatting performance with oxc plugin
3. Display comparison results
4. Restore original configuration
🤖 Generated with [Claude Code](https://claude.com/claude-code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6088-feat-Add-prettier-plugin-oxc-for-faster-formatting-28e6d73d365081aabb24d3af98c11bb0)
by [Unito](https://www.unito.io)
---------
Co-authored-by: DrJKL <DrJKL0424@gmail.com>
Co-authored-by: GitHub Action <action@github.com>
## Summary
Fixes the .gitignore pattern for Linux core dump files from `./core` to
`/core`.
## Problem
The pattern `./core` in .gitignore doesn't work as expected. Git
interprets the `./` prefix literally, looking for a path named `./core`
rather than matching `core` at the repository root.
## Solution
Change to `/core` which is the correct gitignore syntax to ignore
files/directories named `core` at the repository root only.
## Why This Matters
- Linux systems can generate core dump files named `core` when programs
crash
- These files shouldn't be tracked in version control
- The previous pattern wasn't actually ignoring these files
## Testing
The new pattern will properly ignore `core` files at the root while not
affecting subdirectories (e.g., `src/core/` would still be tracked).
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6201-fix-Update-gitignore-to-properly-ignore-Linux-core-dumps-2946d73d365081059e57d9919d03a501)
by [Unito](https://www.unito.io)
## Summary
Fix hover state on Vue node number widget incremenet/decrement buttons.
The problem was in `useNumberWidgetButtonPt.ts`, the button hover styles
were using `var(--color-node-component-surface-hovered)` which
references a Tailwind theme color created by the `@theme` inline
directive. This theme color doesn't properly inherit the `.dark-theme`
class overrides, so it was showing the light mode color (white) even in
dark mode.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6121-fix-Vue-node-number-widget-inc-dec-buttons-hover-state-style-2906d73d36508144b91aec3490e32d28)
by [Unito](https://www.unito.io)
---------
Co-authored-by: DrJKL <DrJKL0424@gmail.com>
`Comfy.Canvas.NavigationMode` and `Comfy.Canvas.LeftMouseClickBehavior`
introduce a circular dependency where setting the value of one will set
the value of the other.
This is solved by having `NavigationMode` skip changing other settings
when `oldValue` is undefined.
- Note that `oldValue` is only undefined during initial load. When a
user changes the value for the first time, oldValue will be the default
value.
In the unlikely event desync occurs (a user manually editing the backing
json?), the registration of the subsequent `LeftMouseClickBehavior` will
still correct `NavigationMode` back to custom
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6184-Fix-circular-dependency-in-setting-registration-2936d73d365081809aa5d8bff0bf2333)
by [Unito](https://www.unito.io)
## Summary
Removes broken terminal toggle button that causes UX issues during
desktop installation.
## Changes
- **What**: Removes "Show Terminal" button from ServerStartView during
install flow
- **Breaking**: None (removes broken functionality)
## Review Focus
Cherry-picked from feb3c078f (v1.27.9). The button causes broken UX when
clicked during install. The working "Show Logs" button remains and takes
users directly to the log directory. This patch was written directly for
the release, in a rush to fix issues. The fix was not PR'd into main as
well (due to timing), so the original issue has now resurfaced.
## Summary
Removes duplicate tarball creation from desktop-ui publish workflow -
`pnpm publish` handles this internally.
## Changes
- **What**: Removes `npm pack` step and GitHub Actions artifact upload
- **Breaking**: None - workflow behavior unchanged, publish still works
identically
## Review Focus
The `npm pack` + artifact upload was creating a duplicate of what `pnpm
publish` generates and uploads to npm anyway. Verified
`publish-frontend-types.yaml` follows this same pattern (no pack step,
direct publish).
## Summary
Removes "Desktop" suffix from the desktop app window title.
## Changes
- **What**: Changes window title from "ComfyUI Desktop" to "ComfyUI"
## Review Focus
Fixes title regression introduced during desktop UI separation.
## Summary
Fixes regression where desktop UI GPU picker images failed to load due
to incorrect absolute path resolution.
## Changes
- **What**: Converts absolute image paths to relative paths with `./`
prefix in GpuPicker component
- **Breaking**: None
## Review Focus
ESLint rule incorrectly flagged relative paths as errors, leading to use
of absolute paths that don't resolve correctly in desktop app context.
The change is just adding `.` to the start of two lines. ESLint rules
reorganised the rest.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6178-Fix-asset-path-resolution-in-desktop-GPU-picker-2936d73d3650814e9d0df9faf8e28733)
by [Unito](https://www.unito.io)
Some virtual nodes (like get/set nodes) perform link redirection at
prompt resolution. The prior implementation incorrectly tried to return
the source of the virtual link after resolution, but this causes things
to break when the source of the virtual link is a subgraph IO.
Instead, this PR changes the code section to restart resolution from the
destination of the virtual link so that the existing subgraph boundary
resolution code is applied.
Also fix a bug with reconnection of complex/any types on
conversion to subgraph.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6135-Fix-link-resolution-of-virtual-nodes-2916d73d36508183b891ef6eb39bad4c)
by [Unito](https://www.unito.io)
## Summary
- Fixed issue where enabling a disabled pack incorrectly triggered
installation instead of using the dedicated enable endpoint
- Added proper `enablePack` method in the manager service layer
- Updated store and component to use the correct API call
## Problem
When users toggled a disabled pack to enable it via `PackEnableToggle`
component, the system was incorrectly calling the install endpoint with
full installation parameters instead of the simpler enable endpoint that
only requires the pack ID.
## Solution
1. **Added dedicated `enablePack` method in `comfyManagerService.ts`**:
- Uses the `'enable'` task kind with `EnablePackParams`
- Only requires `cnr_id` parameter (simpler than install)
2. **Updated `comfyManagerStore.ts`**:
- Created proper `enablePack` function that queues an enable task
- Removed the incorrect aliasing where `enablePack` was pointing to
`installPack`
3. **Simplified `PackEnableToggle.vue`**:
- Now calls `enablePack` with only required parameters (id, version)
- Removed unnecessary installation-specific parameters
## Test plan
- [x] Enable a disabled pack and verify it uses the enable endpoint (not
install)
- [x] Confirm the pack is properly enabled after the operation
- [x] Check that the task queue shows "Enabling" message (not
"Installing")
- [x] Verify existing install/uninstall functionality still works
Fixes#6154
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6157-bugfix-Fix-enable-pack-functionality-to-use-proper-API-endpoint-2926d73d3650819fa4caf1b848f99735)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Added Service Worker to inject Firebase auth headers into browser-native
`/api/view` requests (img, video, audio tags) for cloud distribution.
## Changes
- **What**: Implemented [Service
Worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)
to intercept and authenticate media requests that cannot natively send
custom headers
- **Dependencies**: None (uses native Service Worker API)
## Implementation Details
**Tree-shaking**: Uses compile-time `isCloud` constant - completely
removed from localhost/desktop builds (verified via bundle analysis).
Verify yourself by building the app and `grep -r
"registerAuthServiceWorker\|setupAuth" dist/`
**Caching**: 50-minute auth header cache with automatic invalidation on
login/logout to prevent redundant token fetches.
**Message Flow**:
```mermaid
sequenceDiagram
participant IMG as Browser
participant SW as Service Worker
participant MT as Main Thread
participant FB as Firebase Auth
IMG->>SW: GET /api/view/image.png
SW->>SW: Check cache (50min TTL)
alt Cache miss
SW->>MT: REQUEST_AUTH_HEADER
MT->>FB: getAuthHeader()
FB-->>MT: Bearer token
MT-->>SW: AUTH_HEADER_RESPONSE
SW->>SW: Cache token
end
SW->>IMG: Fetch with Authorization header
Note over SW,MT: On login/logout: INVALIDATE_AUTH_HEADER
```
## Review Focus
- **Same-origin mode**: Service Worker uses `mode: 'same-origin'` to
allow custom headers (browser-native requests default to `no-cors` which
strips headers)
- **Request deduplication**: Prevents concurrent auth header requests
from timing out
- **Build verification**: Confirm `register-*.js` absent in localhost
builds, present (~3.2KB) in cloud builds
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6139-auth-add-service-worker-on-cloud-distribution-to-attach-auth-header-to-browser-native--2916d73d3650812698dccd07d943ab3c)
by [Unito](https://www.unito.io)
## Summary
This code is entirely excluded from open-source, local, and desktop
builds. During minification and dead-code elimination, the Mixpanel
library is fully tree-shaken -- meaning no telemetry code is ever
included or downloaded in those builds. Even the inline callsites are
removed during the build (because `isCloud` becomes false and the entire
block becomes dead code and is removed). The code not only has no
effect, is not even distributed in the first place. We’ve gone to great
lengths to ensure this behavior.
Verification proof:
https://github.com/user-attachments/assets/b66c35f7-e233-447f-93da-4d70c433908d
Telemetry is *enabled only in the ComfyUI Cloud environment*. Its goal
is to help us understand and improve onboarding and new-user adoption.
ComfyUI aims to be accessible to everyone, but we know the learning
curve can be steep. Anonymous usage insights will help us identify where
users struggle and guide us toward making the experience more intuitive
and welcoming.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6154-add-telemetry-provider-for-cloud-distribution-2926d73d3650813cb9ccfb3a2733848b)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
This PR reverts #5922 which fixed pointer capture behavior on video and
image preview components to prevent unintended node dragging.
## Changes
- Removes `data-capture-node="true"` attribute from `VideoPreview.vue`
and `ImagePreview.vue` components
- Removes pointer event delegation logic from
`useNodePointerInteractions.ts` composable
- Restores previous drag behavior where dragging on preview components
triggers node drag
## Reason for Revert
This changes the behavior from original Litegraph and is generally
annoying. Users would rather be able to drag the node than be able to
drag an image/video out from a node.
Reverts #5922
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6148-Revert-fix-dragging-video-image-components-on-Vue-nodes-triggers-node-drag-5922-2916d73d365081398bb5c20384e26bb8)
by [Unito](https://www.unito.io)
## Summary
- Implement dynamic imports for internationalization (i18n) locale files
to reduce initial bundle size
- Only load English locale eagerly as default/fallback, load other
locales on-demand
- Apply code splitting to both main ComfyUI frontend and desktop-ui
applications
## Technical Details
- **Before**: All locale files (main.json, nodeDefs.json, commands.json,
settings.json) for all 9 languages were bundled in the initial
JavaScript bundle
- **After**: Only English locale files are included in initial bundle,
other locales are loaded dynamically when needed
- Implemented `loadLocale()` function that uses dynamic imports with
`Promise.all()` for efficient parallel loading
- Added locale tracking with `loadedLocales` Set to prevent duplicate
loading
- Updated both `src/i18n.ts` and `apps/desktop-ui/src/i18n.ts` with
consistent implementation
## Bundle Size Impact
This change significantly reduces the initial bundle size by removing ~8
languages worth of JSON locale data from the main bundle. Locale files
are now loaded on-demand only when users switch languages.
## Implementation
- Uses dynamic imports: `import('./locales/[locale]/[file].json')`
- Maintains backward compatibility with existing locale switching
mechanism
- Graceful error handling for unsupported locales
- No breaking changes to the public API
## Test plan
- [x] Verify initial load only includes English locale
- [x] Test dynamic locale loading when switching languages in settings
- [x] Confirm fallback behavior for unsupported locales
- [x] Validate both web and desktop-ui applications work correctly
🤖 Generated with [Claude Code](https://claude.ai/code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6076-feat-implement-dynamic-imports-for-locale-code-splitting-28d6d73d36508189ae0ef060804a5cee)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Added a `manualChunks` strategy in `vite.config.mts` that splits
primevue, tiptap, chart.js, three/@xterm, core Vue/Pinia, and the
remaining dependencies into dedicated vendor bundles. This reduces the
main application chunk size and allows browsers to cache heavy
third-party code across releases, improving load times when those
libraries stay unchanged.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6137-perf-manually-chunk-vendored-code-2916d73d36508140a44ec0de228ef9cc)
by [Unito](https://www.unito.io)
## Summary
Introduces a `GENERATE_SOURCEMAP` environment flag in `vite.config.mts`
that defaults to enabled (`true` unless set to `'false'`). This keeps
source maps on by default, while allowing opt-out for lean production
artifacts.
Allows the choice to be made as part of the distribution pipeline and
changed for different targets.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6134-ci-allow-setting-GENERATE_SOURCEMAP-as-env-var-2916d73d3650815d91b9eff12b6e55fd)
by [Unito](https://www.unito.io)
Summary
Implements cloud subscription management UI and flow for ComfyUI Cloud
users.
Core Features:
- Subscription Status Tracking: Global reactive state management for
subscription status across all components
using shared subscriptionStatus ref
- Subscribe to Run Button: Replaces the Run button in the actionbar with
a "Subscribe to Run" button for users
without active subscriptions
- Subscription Required Dialog: Modal dialog with subscription benefits,
pricing, and checkout flow with video
background
- Subscription Settings Panel: New settings panel showing subscription
status, renewal date, and quick access to
billing management
- Auto-detection & Polling: Automatically polls subscription status
after checkout completion and syncs state
across the application
https://github.com/user-attachments/assets/f41b8e6a-5845-48a7-8169-3a6fc0d2e5c8
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6064-subscription-page-28d6d73d36508135a2a0fe7c94b40852)
by [Unito](https://www.unito.io)
---------
Co-authored-by: GitHub Action <action@github.com>