## Summary
**Problem:** ensureCorrectLayoutScale scales up LG -> Vue. But doesn't
scale down from Vue -> LG.
**Solution:** Bi directional scaling.
**Bonus:** fix edge cases such as subgraphs, groups, and reroutes. Also,
set auto scale: true now that we 'preserve' LG scale.
**IMPORTANT:** useVueNodeResizeTracking.ts sets vue node height -
Litegraph.NODE_TITLE_HEIGHT on workflow load using a resize observer.
Reloading the page (loading a workflow) in Vue mode, will subtract
height each time. This can look like a problem caused by
ensureCorrectLayoutScale. It is not. Need to fix. Here was an attempt by
[removing the Litegraph.NODE_TITLE_HEIGHT
entirely](https://github.com/Comfy-Org/ComfyUI_frontend/pull/6643).
## Review Focus
Full lifecycle of loading workflows and switching between vue and lg.
Race conditions could be present. For example switching the mode using
keybind very fast.
## Screenshots (if applicable)
https://github.com/user-attachments/assets/5576b760-13a8-45b9-b8f7-64e1caf443c1https://github.com/user-attachments/assets/46d6f870-df76-4084-968a-53cb629fc123
---------
Co-authored-by: github-actions <github-actions@github.com>
## Summary
Adds an upload button to the asset browser modal, controlled by the
`model_upload_button_enabled` backend feature flag.
## Changes
- **What**: Added upload button with PrimeVue primary styling to asset
browser header
- **Feature Flag**: Button only appears when backend returns
`model_upload_button_enabled: true`
- **Localization**: Added `assetBrowser.uploadModel` translation key
- **Click Handler**: Currently logs to console (implementation pending)
## Review Focus
- Feature flag integration using `useFeatureFlags` composable
- Button styling matches PrimeVue primary color scheme
- Proper placement in header with flexbox layout
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6665-feat-Add-feature-flagged-upload-button-to-asset-browser-2a96d73d365081c7a05bdc33bed7f7fd)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Adds [Oxc linter](https://oxc.rs/docs/guide/usage/linter) as a dev
dependency
- Creates minimal `.oxlintrc.json` configuration file
- Integrates oxlint into the lint workflow (runs before ESLint)
- Adds `pnpm oxlint` script for standalone usage
- **NEW**: Adds
[eslint-plugin-oxlint](https://github.com/oxc-project/eslint-plugin-oxlint)
to disable redundant ESLint rules
- Updates `CLAUDE.md` documentation with oxlint command
## Motivation
Oxc is a high-performance Rust-based linter that is 50-100x faster than
ESLint. By integrating it into our lint workflow, we get:
- **Faster CI/CD pipelines** (5% improvement in this codebase)
- **Quicker local development feedback**
- **Additional code quality checks** that complement ESLint
- **Reduced duplicate work** by disabling ESLint rules that oxlint
already checks
## Changes
- **package.json**: Added `oxlint` and `eslint-plugin-oxlint` to
devDependencies, integrated into `lint`, `lint:fix`, and `lint:no-cache`
scripts
- **pnpm-workspace.yaml**: Added `eslint-plugin-oxlint` and
`mixpanel-browser` to catalog
- **eslint.config.ts**: Integrated `eslint-plugin-oxlint` to
automatically disable redundant ESLint rules
- **.oxlintrc.json**: Created minimal configuration file with schema
reference
- **CLAUDE.md**: Added `pnpm oxlint` to Quick Commands section
- **.gitignore**: Added `core` dump files
## CI/CD Performance Benchmark
Real-world CI/CD timing from GitHub Actions workflow runs:
### Baseline (ESLint only) - [Run
#18718911051](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/18718911051)
- Run ESLint with auto-fix: **125s**
- Final validation (lint + format + knip): **16s**
- **Total: 141s**
### With Oxlint (oxlint + ESLint) - [Run
#18719037963](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/18719037963)
- Run ESLint with auto-fix (includes oxlint): **118s**
- Final validation (includes oxlint + lint + format + knip): **16s**
- **Total: 134s**
### Results
✅ **7 seconds faster (5.0% improvement)** despite running an additional
linting pass
### Analysis
The oxlint integration actually **improves** CI/CD performance by ~5%.
This unexpected improvement is likely because:
1. **Oxlint catches issues early**: Some code that would have slowed
down ESLint's parsing/analysis is caught by oxlint first
2. **ESLint cache benefits**: The workflow uses `--cache`, and oxlint's
fast execution helps populate/validate the cache more efficiently
3. **Parallel processing**: Modern CI runners can overlap some of the
I/O operations between oxlint and ESLint
Even if oxlint added overhead, the value proposition would still be
strong given its additional code quality checks and local development
speed benefits. The fact that it actually speeds up the pipeline is a
bonus.
## eslint-plugin-oxlint Performance Impact
Benchmark comparing ESLint performance with and without
eslint-plugin-oxlint:
### Baseline (ESLint without plugin) - [Run
#18723242157](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/18723242157)
- Run ESLint with auto-fix: **122s** (2m 2s)
- Final validation: **17s**
### With eslint-plugin-oxlint - [Run
#18723675903](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/18723675903)
- Run ESLint with auto-fix: **129s** (2m 9s)
- Final validation: **12s**
### Results
**Performance: +7 seconds ESLint, -5 seconds validation (net +2
seconds)**
The eslint-plugin-oxlint integration has a **minimal performance
impact** (+2 seconds total). The slight increase in ESLint time is
likely due to the additional plugin configuration overhead, while the
validation step is faster because fewer redundant lint warnings need to
be processed.
### Benefits
The small performance cost is outweighed by important benefits:
1. **Prevents duplicate work**: Disables ~50 ESLint rules that oxlint
already checks (e.g., `no-constant-condition`, `no-debugger`,
`no-empty`, etc.)
2. **Reduces noise**: Eliminates redundant lint warnings from two tools
checking the same thing
3. **Cleaner workflow**: One authoritative source for each type of lint
check
4. **Best practice**: Recommended by the Oxc project for ESLint + oxlint
integration
5. **Consistent results**: Ensures both tools don't conflict or give
contradictory advice
## Usage
```bash
# Run oxlint standalone
pnpm oxlint
# Run full lint workflow (oxlint + ESLint)
pnpm lint
pnpm lint:fix
```
## Notes
- Oxlint now runs as part of the standard `pnpm lint` workflow
- The configuration uses minimal rules by default (Oxc's philosophy is
"catch erroneous or useless code without requiring any configurations by
default")
- Oxlint provides fast feedback while ESLint provides comprehensive
checks
- eslint-plugin-oxlint automatically manages rule conflicts between the
two tools
- Both tools complement each other in the linting pipeline
🤖 Generated with [Claude Code](https://claude.com/claude-code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6197-chore-Add-Oxc-linter-to-project-2946d73d3650818cbb55ef9c0abdb9b9)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: DrJKL <DrJKL0424@gmail.com>
This pull request adds persistent filter and sort settings to the
template library, allowing users' filter choices and sort preferences to
be saved and restored across sessions. The main changes include
integrating the settings store with the template filtering composable,
updating the schema and core settings, and ensuring filter changes are
saved efficiently.
**Template Library Filter Persistence:**
*
[`src/composables/useTemplateFiltering.ts`](diffhunk://#diff-a1ec9d65962033526942cbcabeac8538ef3cd723e2e9e889cf668ccf6270d167L1-R32):
The filter state (`selectedModels`, `selectedUseCases`,
`selectedRunsOn`, and `sortBy`) is now initialized from the settings
store and changes are persisted back using debounced watchers. This
ensures user preferences are saved and restored.
[[1]](diffhunk://#diff-a1ec9d65962033526942cbcabeac8538ef3cd723e2e9e889cf668ccf6270d167L1-R32)
[[2]](diffhunk://#diff-a1ec9d65962033526942cbcabeac8538ef3cd723e2e9e889cf668ccf6270d167R259-R291)
*
[`src/platform/settings/constants/coreSettings.ts`](diffhunk://#diff-9fb7e2cdcdc60a92bdb54698fb49909bd2a84a50ffb69e2b60529a948eeb9756R1056-R1083):
Added new hidden settings for template filter selections and sort
preference, with sensible defaults.
*
[`src/schemas/apiSchema.ts`](diffhunk://#diff-b769532e74f826ca909951c0c34331b9246efb3f6901ff95a856ecf01ad826beR504-R514):
Updated the settings schema to include the new template filter and sort
settings, ensuring type safety and validation.
**Default Behavior Adjustment:**
*
[`src/composables/useTemplateFiltering.ts`](diffhunk://#diff-a1ec9d65962033526942cbcabeac8538ef3cd723e2e9e889cf668ccf6270d167L200-R209):
Changed the default sort order when clearing filters to `'newest'` to
match the new default in settings.
https://github.com/user-attachments/assets/259e87e6-20b3-4c91-b1bf-4b7d70649878
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6657-Persist-template-filters-2a86d73d3650818ca46fda23a6528391)
by [Unito](https://www.unito.io)
## Summary
Implements a cloud-specific dialog to warn users when loading workflows
with unsupported custom nodes in Comfy Cloud. The new dialog follows the
visual style of the node conflict dialog and provides appropriate
messaging and actions.
## Changes
- Add `CloudMissingNodesHeader`, `CloudMissingNodesContent`, and
`CloudMissingNodesFooter` components
- Add `showCloudLoadWorkflowWarning` to dialogService
- Update app.ts to show cloud dialog when in cloud environment
- Add `cloud.missingNodes` translations
## Screenshots
The dialog displays:
- Warning icon and title
- Description of the issue
- List of missing nodes
- "Learn more" link and "Ok, got it" button
## Test plan
1. Load a workflow with custom nodes in cloud environment
2. Verify cloud-specific dialog appears with appropriate styling
3. Verify "Learn more" button opens cloud documentation
4. Verify "Ok, got it" button closes dialog
## Notes
- Two unused i18n keys (`cloud.missingNodes.cannotRun` and
`cloud.missingNodes.missingNodes`) are included for future PR that will
add breadcrumb warning icons and run button disable functionality
<img width="1367" height="988" alt="스크린샷 2025-11-12 오후 4 33 38"
src="https://github.com/user-attachments/assets/75a6fced-959f-4e93-9b82-4e61b53a9ee4"
/>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6659-Add-cloud-specific-missing-nodes-warning-dialog-2a96d73d36508161ae55fe157f55cd17)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Fixes the janky UX when loading templates via URL query parameters by
moving the loading logic earlier in the app lifecycle (from
GraphView.onGraphReady to
useWorkflowPersistence.restorePreviousWorkflow). The saved workflow now
loads first as a background tab, then the template loads as the active
tab, eliminating the visual flash where the saved workflow briefly
appears before being replaced. After loading, the template and source
query parameters are removed from the URL using router.replace to
prevent the template from re-loading on page refresh. This preserves
user work by keeping both workflows open in separate tabs and matches
the existing behavior when clicking templates from the dialog. All 15
tests pass including 3 new tests for URL cleanup.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6593-fix-improve-template-URL-loading-UX-and-prevent-re-triggering-2a26d73d36508137a0cae6cf92c842fc)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Christian Byrne <c.byrne@comfy.org>
## Summary
we need to add root div to avoid warning
> Extraneous non-props attributes (data-v-inspector) were passed to
> component but could not be automatically inherited because component
renders fragment or text or teleport root
> nodes.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6650-fix-warning-log-2a86d73d365081a89c5af0c60cdaa618)
by [Unito](https://www.unito.io)
This pull request introduces a new extensible system for adding custom
action bar buttons to the top menu, and demonstrates its use by adding a
cloud feedback button. The changes include defining a new
`ActionBarButton` type, updating the extension system to support action
bar buttons, creating a Pinia store to aggregate buttons from
extensions, and updating the UI to render these buttons in the top menu.
The cloud feedback button is now conditionally loaded for cloud
environments.
**Extensible Action Bar Button System**
* Defined a new `ActionBarButton` interface in `comfy.ts` for describing
buttons (icon, label, tooltip, class, click handler) and added an
`actionBarButtons` property to the `ComfyExtension` interface to allow
extensions to contribute buttons.
[[1]](diffhunk://#diff-c29886a1b0c982c6fff3545af0ca
<img width="1134" height="437" alt="Screenshot 2025-11-07 at 01 07 36"
src="https://github.com/user-attachments/assets/36b6145a-0b82-4f7d-88e8-f2ea350a359b"
/>
8ec269876c2cf3948f867d08c14032c04d66R60-R82)
[[2]](diffhunk://#diff-c29886a1b0c982c6fff3545af0ca8ec269876c2cf3948f867d08c14032c04d66R128-R131)
* Created a Pinia store (`actionBarButtonStore.ts`) that collects all
action bar buttons from registered extensions for use in the UI.
**UI Integration**
* Added a new `ActionBarButtons.vue` component that renders all action
bar buttons using the store, and integrated it into the top menu section
(`TopMenuSection.vue`).
[[1]](diffhunk://#diff-d6820f57cde865083d515ac0c23e1ad09e6fbc6792d742ae948a1d3b772be473R1-R28)
[[2]](diffhunk://#diff-45dffe390927ed2d5ba2426a139c52adae28ce15f81821c88e7991944562074cR10)
[[3]](diffhunk://#diff-45dffe390927ed2d5ba2426a139c52adae28ce15f81821c88e7991944562074cR28)
**Cloud Feedback Button Extension**
* Implemented a new extension (`cloudFeedbackTopbarButton.ts`) that
registers a "Feedback" button opening the Zendesk feedback page, and
ensured it loads only in cloud environments.
[[1]](diffhunk://#diff-b84a6a0dfaca19fd77b3fae6999a40c3ab8d04ed22636fcdecc65b385a8e9a98R1-R24)
[[2]](diffhunk://#diff-236993d9e4213efe96d267c75c3292d32b93aa4dd6c3318d26a397e0ae56bc87R32)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6626-Cloud-feedback-Extension-2a46d73d36508170bd07f582ccfabb3c)
by [Unito](https://www.unito.io)
Fixes a race causing “No auth header available for session creation”
during sign‑in, by skipping the initial token refresh event, and
wrapping extension auth hooks with async error handling.
Sentry:
https://comfy-org.sentry.io/issues/6990347926/?alert_rule_id=1614600&project=4509681221369857
Context
- Error surfaced as an unhandled rejection when session creation was
triggered without a valid auth header.
- Triggers: both onAuthUserResolved and onAuthTokenRefreshed fired
during initial login.
- Pre‑fix, onIdTokenChanged treated the very first token emission as a
“refresh” as well, so two concurrent createSession() calls ran
back‑to‑back.
- One of those calls could land before a Firebase ID token existed, so
getAuthHeader() returned null → createSession threw “No auth header
available for session creation”.
Exact pre‑fix failure path
- src/extensions/core/cloudSessionCookie.ts
- onAuthUserResolved → useSessionCookie().createSession()
- onAuthTokenRefreshed → useSessionCookie().createSession()
- src/stores/firebaseAuthStore.ts
- onIdTokenChanged increments tokenRefreshTrigger even for the initial
token (treated as a refresh)
- getAuthHeader() → getIdToken() may be undefined briefly during
initialization
- src/platform/auth/session/useSessionCookie.ts
- createSession(): calls authStore.getAuthHeader(); if falsy, throws
Error('No auth header available for session creation')
What this PR changes
1) Skip initial token “refresh”
- Track lastTokenUserId and ignore the first onIdTokenChanged for a
user; only subsequent token changes count as refresh events.
- File: src/stores/firebaseAuthStore.ts
2) Wrap extension auth hooks with async error handling
- Use wrapWithErrorHandlingAsync for
onAuthUserResolved/onAuthTokenRefreshed/onAuthUserLogout callbacks to
avoid unhandled rejections.
- File: src/services/extensionService.ts
Result
- Eliminates the timing window where createSession() runs before
getIdToken() returns a token.
- Ensures any remaining errors are caught and reported instead of
surfacing as unhandled promise rejections.
Notes
- Lint and typecheck run clean (pnpm lint:fix && pnpm typecheck).
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6563-Fix-session-cookie-creation-race-dedupe-calls-skip-initial-token-refresh-wrap-extensio-2a16d73d365081ef8c22c5ac8cb948aa)
by [Unito](https://www.unito.io)
- Hide "*" indicator in the browser tab title when autosave is enabled
(Comfy.Workflow.AutoSave === 'after delay').
- Refactor: extract readable computed values
(`shouldShowUnsavedIndicator`, `isActiveWorkflowModified`,
`isActiveWorkflowPersisted`).
- Aligns with workflow tab behavior; also hides while Shift is held
(matches in-app tab logic).
Files touched:
- src/composables/useBrowserTabTitle.ts
Validation:
- Ran `pnpm lint:fix` and `pnpm typecheck` — both passed.
Manual test suggestions:
- With autosave set to 'after delay': modify a workflow → browser tab
should not show `*`.
- With autosave 'off': modify or open non-persisted workflow → browser
tab shows `*`.
- Hold Shift: indicator hidden while held (consistent with workflow
tab).
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6568-Hide-browser-tab-star-when-autosave-is-enabled-refactor-title-logic-2a16d73d365081549906e9d1fed07a42)
by [Unito](https://www.unito.io)
This PR cleans up the base-layer utilities so they no longer pull
renderer or workbench code. The renderer-only `isPrimitiveNode` guard
now lives in `src/renderer/utils/nodeTypeGuards.ts`, and the node
help/model/ordering helpers have moved into `src/workbench/utils`. All
affected services, stores, scripts, and tests were updated to import
from the new locations.
The idea is to reduce the number of Base→Renderer/Base→Workbench edges
(higher scoped base/common utils should not import from
renderer/workbench layers).
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6621-refactor-move-renderer-dependent-utils-into-workbench-scope-2a36d73d36508167aff0fc8a22202d7f)
by [Unito](https://www.unito.io)
Add user email and ID as URL parameters when opening the Contact Support
link to improve support experience. Only includes user data when logged
in.
## Summary
Enhanced the Contact Support command to automatically pre-fill user
email and ID in Zendesk support tickets, streamlining the support
request process for authenticated users.
## Changes
- **What**:
- Added `useCurrentUser` composable to access authenticated user data in
`useCoreCommands.ts`
- Modified `Comfy.ContactSupport` command to append user email
(`tf_anonymous_requester_email` and `tf_40029135130388`) and user ID
(`tf_42515251051412`) as URL parameters when available
- Maintained backward compatibility by only adding user parameters when
user is logged in
- Preserved existing `tf_42243568391700` parameter for distribution type
(oss/ccloud)
## Review Focus
- Verify that the URL parameters are correctly appended only when user
is authenticated
- Confirm that non-authenticated users still get the base support URL
with just the distribution type parameter
- Check that both Firebase auth and API key auth users have their
information properly included
Example URLs generated when you press on help locally (it will change
automatically to ccloud on Cloud):
- **Logged out**:
`https://support.comfy.org/hc/en-us/requests/new?tf_42243568391700=oss`
- **Logged in**:
`https://support.comfy.org/hc/en-us/requests/new?tf_42243568391700=ccloud&tf_anonymous_requester_email=user@example.com&tf_40029135130388=user@example.com&tf_42515251051412=abc123xyz`
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6586-feat-pre-fill-user-info-in-Zendesk-support-link-2a26d73d36508171b428c634b310f68b)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: bymyself <cbyrne@comfy.org>
## Summary
1. Add a `getOptionLabel` option to `ComboWidget` so users of it can map
of custom labels to widget values. (e.g., `"My Photo" ->
"my_photo_1235.png"`).
2. Utilize this ability in Cloud environment to map user uploaded
filenames to their corresponding input asset.
3. Copious unit tests to make sure I didn't (AFAIK) break anything
during the refactoring portion of development.
4. Bonus: Scope model browser to only show in cloud distributions until
it's released elsewhere; should prevent some undesired UI behavior if a
user accidentally enables the assetAPI.
## Review Focus
Widget code: please double check the work there.
## Screenshots (if applicable)
https://github.com/user-attachments/assets/a94b3203-c87f-4285-b692-479996859a5a
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6585-Feat-input-mapping-2a26d73d365081faa667e49892c8d45a)
by [Unito](https://www.unito.io)
This pull request updates the design system color tokens and refactors
node and widget component styles throughout the codebase to use new,
more consistent CSS variables. The changes ensure that node and widget
components are styled using unified design tokens, improving
maintainability and theme support for both light and dark modes.
**Design System Token Updates**
* Added new component and node-related CSS variables for background,
border, foreground, and widget states in both light and dark themes in
`style.css`.
[[1]](diffhunk://#diff-71b6b57a56095b04e47c797a5016149b76b27971cab04b93f033f1f846e0f5a0R246-R256)
[[2]](diffhunk://#diff-71b6b57a56095b04e47c797a5016149b76b27971cab04b93f033f1f846e0f5a0R354-R364)
* Introduced `--color-graphite-400` and adjusted several existing color
assignments for better palette consistency.
[[1]](diffhunk://#diff-71b6b57a56095b04e47c797a5016149b76b27971cab04b93f033f1f846e0f5a0R76)
[[2]](diffhunk://#diff-71b6b57a56095b04e47c797a5016149b76b27971cab04b93f033f1f846e0f5a0L304-R316)
* Updated semantic CSS variables to reference the new component/node
tokens for easier usage in components.
* Changed `--secondary-background-hover` to match
`--secondary-background` for improved hover consistency.
**Component Refactoring: Node and Widget Styles**
* Refactored Vue component classes and inline styles to use the new CSS
variables for node backgrounds, borders, and widget states, replacing
legacy variables like `bg-node-component-surface` and
`border-node-component-border` with `bg-component-node-background` and
`border-component-node-border`.
[[1]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2L11-R14)
[[2]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2L39-R39)
[[3]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2L384-R384)
[[4]](diffhunk://#diff-19537a67677431ecdc9aec43877d28814e37edf0e45b0b0b484ea08832cad299L5-R13)
* Updated widget dropdowns, select, and input components to use
`text-component-node-foreground-secondary` for icons and foregrounds,
and new background variables for buttons and inputs.
[[1]](diffhunk://#diff-489229f88dfdfd5d883a3ef7fad6effa0790a18a831d5a9d84642dfb246962a2L29-R29)
[[2]](diffhunk://#diff-489229f88dfdfd5d883a3ef7fad6effa0790a18a831d5a9d84642dfb246962a2L100-R100)
[[3]](diffhunk://#diff-661a09de2721335e118a693b25d09922ada0ccbd0a51284691ed784fbe18874eL13-R13)
[[4]](diffhunk://#diff-2856391d03b0d38db1ed922b5034a05bc32e978c51f8175057d84cf82399d986L13-R13)
[[5]](diffhunk://#diff-4ee47848821aff71b6da0a1bb7fb8976e7879d706f71ff2ab3c5b046f5ef528cL10-R10)
[[6]](diffhunk://#diff-8b7ed2ce6194a262fb1e950294699cb8722630920362143a765802b602ae5fc8L106-R113)
[[7]](diffhunk://#diff-8b7ed2ce6194a262fb1e950294699cb8722630920362143a765802b602ae5fc8L119-R123)
[[8]](diffhunk://#diff-597a77456bf4b0c2d390fc46a930f37156b2f26ca030259b6703e5d39ff6b20eL37-R53)
[[9]](diffhunk://#diff-29348fa2e5b8cec1301a99bdec241379aeefc1747cceeb0c39b7df452ca635ffL7-R7)
**Service Layer Updates**
* Updated the color palette service mapping to use the new CSS variable
names for node and widget colors, ensuring consistency across the
application.
*
https://github.com/user-attachments/assets/d9535f9a-b459-49bf-b2fe-ed872916fa4e
These changes collectively modernize the styling approach for node and
widget components, making it easier to maintain and extend theme
support.
---------
Co-authored-by: github-actions <github-actions@github.com>
This pull request introduces several improvements to Vue reactivity and
user experience in the graph node and widget system. The main focus is
on ensuring that changes to node and widget data reliably trigger
updates in Vue components, improving drag-and-drop support for nodes,
and enhancing widget value handling for better compatibility and
reactivity.
**Vue Reactivity Improvements:**
* In `useGraphNodeManager.ts`, node data updates now create a completely
new object and add a timestamp (`_updateTs`) to force Vue's reactivity
system to detect changes. Additionally, node data is re-set on the next
tick to guarantee component updates.
[[1]](diffhunk://#diff-f980db6f42cef913c3fe92669783b255d617e40b9ccef9a1ab9cc8e326ff1790L272-R280)
[[2]](diffhunk://#diff-f980db6f42cef913c3fe92669783b255d617e40b9ccef9a1ab9cc8e326ff1790R326-R335)
* Widget value composables (`useWidgetValue` and related helpers) now
accept either a direct value or a getter function for `modelValue`, and
always normalize it to a getter. Watches are updated to use this getter
for more reliable reactivity.
[[1]](diffhunk://#diff-92dc3c8b09ab57105e400e115196aae645214f305685044f62edc3338afa0911L13-R14)
[[2]](diffhunk://#diff-92dc3c8b09ab57105e400e115196aae645214f305685044f62edc3338afa0911R49-R57)
[[3]](diffhunk://#diff-92dc3c8b09ab57105e400e115196aae645214f305685044f62edc3338afa0911L82-R91)
[[4]](diffhunk://#diff-92dc3c8b09ab57105e400e115196aae645214f305685044f62edc3338afa0911L100-R104)
[[5]](diffhunk://#diff-92dc3c8b09ab57105e400e115196aae645214f305685044f62edc3338afa0911L117-R121)
[[6]](diffhunk://#diff-92dc3c8b09ab57105e400e115196aae645214f305685044f62edc3338afa0911L140-R144)
[[7]](diffhunk://#diff-0c43cefa9fb524ae86541c7ca851e97a22b3fd01f95795c83273c977be77468fL47-R47)
* In `useImageUploadWidget.ts`, widget value updates now use a new
array/object to ensure Vue detects the change, especially for batch
uploads.
**Drag-and-Drop Support for Nodes:**
* The `LGraphNode.vue` component adds drag-and-drop event handlers
(`dragover`, `dragleave`, `drop`) and visual feedback (`isDraggingOver`
state and highlight ring) for improved user experience when dragging
files onto nodes. Node callbacks (`onDragOver`, `onDragDrop`) are used
for custom validation and handling.
[[1]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2L26-R27)
[[2]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2R47-R49)
[[3]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2R482-R521)
**Widget and Audio Upload Handling:**
* In `uploadAudio.ts`, after uploading an audio file, the widget's
callback is manually triggered to ensure Vue nodes update. There is also
a commented-out call to mark the canvas as dirty for potential future
refresh logic.
[[1]](diffhunk://#diff-796b36f2cafb906a5e95b5750ca5ddc1bf57a304d4a022e0bdaee04b4ee5bbc4R61-R65)
[[2]](diffhunk://#diff-796b36f2cafb906a5e95b5750ca5ddc1bf57a304d4a022e0bdaee04b4ee5bbc4R190-R191)
These changes collectively improve the reliability and responsiveness of
UI updates in the graph node system, especially in scenarios involving
external updates, drag-and-drop interactions, and batch widget value
changes.
https://github.com/user-attachments/assets/8e3194c9-196c-4e13-ad0b-a32177f2d062
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6514-Drag-vuenodes-input-29e6d73d3650817da1b7ef96b61b752d)
by [Unito](https://www.unito.io)
## Summary
- Resolves multiple cloud environment issues when accessing
`/cloud/user-check` directly
- Fixes API routing problems that caused 304 Not Modified errors and
JSON parsing failures
- Maintains compatibility with subpath deployments for OSS users
## Root Cause
The `api_base` was incorrectly calculated as `/cloud` on cloud SPA
routes, causing API calls to use wrong paths like `/cloud/api/user`
instead of `/api/user`.
## Issues Fixed
- ❌ `/cloud/user-check` direct access resulted in infinite loading
- ❌ JSON parsing errors: `Unexpected token '<', "<!DOCTYPE "... is not
valid JSON`
- ❌ 304 Not Modified responses on `/cloud/api/user`,
`/cloud/api/settings/onboarding_survey`, `/cloud/api/system_stats`
## Solution
Added conditional `api_base` calculation in `ComfyApi` constructor:
- **Cloud SPA routes** (`/cloud/*`): Use empty `api_base` → API calls
use `/api/*` paths
- **Regular deployments**: Keep existing logic → Supports subpath
deployments
## Test Plan
- [x] Verify `/cloud/user-check` direct access works without infinite
loading
- [x] Verify all API calls return 200 instead of 304
- [x] Verify OSS subpath deployment compatibility unchanged
- [x] Test authentication flow completion
🤖 Generated with [Claude Code](https://claude.ai/code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6572-Fix-cloud-routing-issues-caused-by-incorrect-api_base-calculation-2a16d73d36508163aeb2cbf6347b427d)
by [Unito](https://www.unito.io)