Commit Graph

601 Commits

Author SHA1 Message Date
Christian Byrne
ffc0bf00ef fix: make SubgraphNode.graph nullable to allow proper cleanup (#8180)
## Summary

Fix `SubgraphNode.graph` property to match `LGraphNode` lifecycle
contract. Previously declared as `override readonly graph` via
constructor parameter promotion, which prevented `LGraph.remove()` from
setting `node.graph = null`.

## Changes

- Remove `readonly` from `SubgraphNode.graph` constructor parameter
- Add `override graph: GraphOrSubgraph | null` as class property  
- Add `NullGraphError` guard in `rootGraph` getter with node ID for
debugging
- Add null guards in `ExecutableNodeDTO.resolveInput` and
`imagePreviewStore.revokeSubgraphPreviews`
- Add test verifying `rootGraph` throws after node removal

## Testing

- Existing subgraph tests pass
- New test confirms `NullGraphError` is thrown when accessing
`rootGraph` on removed node

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-02-03 16:18:48 -08:00
Christian Byrne
278d491030 refactor: move ellipsis and punctuation into i18n translation strings (#8573)
## Summary

Move ellipsis and punctuation characters into i18n translation strings
for proper internationalization support.

## Changes

- Add 12 new translation keys with punctuation included:
- Placeholder keys with trailing ellipsis (e.g.,
`searchNodesPlaceholder: "Search Nodes..."`)
  - `downloadWithSize` with interpolation: `"Download ({size})"`
  - `completedWithCheckmark`: `"Completed ✓"`
- Prompt keys with colons (e.g., `enterNewNamePrompt: "Enter new
name:"`)
- Update 20 files to use new translation keys instead of string
concatenation

## Review Focus

This eliminates string concatenation patterns like `$t('key') + '...'`
that break proper internationalization, since different languages may
use different punctuation or may not need ellipsis/colons in the same
contexts.

Fixes #7333


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Standardized localization across the app: unified search placeholders
and input hints; updated dialog prompt texts for renaming,
saving/exporting, and related prompts.
* **New Features**
  * Download buttons now show file size via localized text.
  * Completed status displays a localized label with a checkmark.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8573-refactor-move-ellipsis-and-punctuation-into-i18n-translation-strings-2fc6d73d365081828ad3f257bcac7799)
by [Unito](https://www.unito.io)
2026-02-03 15:50:18 -08:00
Christian Byrne
32da91ea32 perf: code-split xterm bundle and gate terminal features for cloud (#8528)
## Summary

Code-splits the ~400KB xterm bundle and excludes terminal features from
cloud distribution where they are not needed.

### Changes

- **bottomPanelStore.ts**: Gate terminal tab registration behind
`__DISTRIBUTION__ !== 'cloud'` check with dynamic import, enabling
tree-shaking
- **keybindingService.ts**: Skip logs-terminal keybinding registration
for cloud distribution
- **vite.config.mts**: Add `vendor-xterm` code splitting group

### Bundle Impact

| Distribution | xterm in bundle | Terminal tabs |
|--------------|-----------------|---------------|
| cloud |  No (~400KB saved) | None |
| localhost |  Yes (vendor-xterm chunk) | Logs terminal |
| desktop |  Yes (vendor-xterm chunk) | Logs + Command terminal |

### Verification Script

Run locally to verify xterm exclusion works correctly:

```bash
#!/bin/bash
set -e

echo "=== Verifying xterm bundle exclusion ==="
echo

# Clear Nx cache to ensure fresh builds
pnpm nx reset 2>/dev/null

# Build cloud distribution
echo "Building CLOUD distribution..."
rm -rf dist
DISTRIBUTION=cloud pnpm build --mode production 2>/dev/null

echo "Cloud build - checking for xterm:"
if grep -r "xterm" dist/assets/*.js >/dev/null 2>&1; then
  echo "   FAIL: xterm found in cloud bundle"
  grep -l "xterm" dist/assets/*.js | head -5
else
  echo "   PASS: xterm NOT in cloud bundle"
fi
echo

# Build localhost distribution
echo "Building LOCALHOST distribution..."
pnpm nx reset 2>/dev/null
rm -rf dist
DISTRIBUTION=localhost pnpm build --mode production 2>/dev/null

echo "Localhost build - checking for xterm:"
if grep -r "xterm" dist/assets/*.js >/dev/null 2>&1; then
  echo "   PASS: xterm found in localhost bundle"
  echo "  Files containing xterm:"
  grep -l "xterm" dist/assets/*.js | while read f; do
    size=$(wc -c < "$f")
    echo "    $(basename $f) ($(numfmt --to=iec $size))"
  done
else
  echo "   FAIL: xterm NOT in localhost bundle"
fi
echo

echo "=== Verification complete ==="
```

**Note**: Nx cache must be reset between builds with different
`DISTRIBUTION` values or it may return stale results.

## Test Plan

- [x] Quality gates pass (typecheck, lint, format, tests)
- [x] Cloud build verified: xterm NOT present
- [x] Localhost build verified: xterm present as vendor-xterm chunk

Fixes COM-14129

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8528-perf-code-split-xterm-bundle-and-gate-terminal-features-for-cloud-2fa6d73d365081a093ecc74ca7ce6e7c)
by [Unito](https://www.unito.io)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Refactor**
* Terminal tab declarations adjusted (no user-visible behavior change).
* Bottom panel tabs now load asynchronously; panel toggle falls back to
shortcuts when terminal tabs aren’t loaded.

* **Chores**
* Terminal tabs and related keybindings suppressed in cloud deployments.
  * Core commands wired to a new utility to support widget promotion.

* **Tests**
* E2E tests updated to handle async terminal-tab loading and minor test
cleanup.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2026-02-03 15:15:37 -08:00
Alexander Brown
f2d5bfab73 test(browser): refactor browser tests for reliability and maintainability (#8510)
## Summary

Major refactoring of browser tests to improve reliability,
maintainability, and type safety.

## Changes

### Test Infrastructure Decomposition
- Decomposed `ComfyPage.ts` (~1000 lines) into focused helpers:
- `CanvasHelper`, `DebugHelper`, `SubgraphHelper`,
`NodeOperationsHelper`
- `SettingsHelper`, `WorkflowHelper`, `ClipboardHelper`,
`KeyboardHelper`
- Created `ContextMenu` page object, `BaseDialog` base class, and
`BottomPanel` page object
- Extracted `DefaultGraphPositions` constants

### Locator Stability
- Added `data-testid` attributes to Vue components (sidebar, dialogs,
node library)
- Created centralized `selectors.ts` with test ID constants
- Replaced fragile CSS selectors (`.nth()`, `:nth-child()`) with
`getByTestId`/`getByRole`

### Performance & Reliability
- Removed `setTimeout` anti-patterns (replaced with `waitForFunction`)
- Replaced `waitForTimeout` with retrying assertions
- Replaced hardcoded coordinates with computed `NodeReference` positions
- Enforced LF line endings for all text files

### Type Safety
- Enabled `no-explicit-any` lint rule for browser_tests via oxlint
- Purged `as any` casts from browser_tests
- Added Window type augmentation for standardized window access
- Added proper type annotations throughout

### Bug Fixes
- Restored `ExtensionManager` API contract
- Removed test-only settings from production schema
- Fixed flaky selectors and missing test setup

## Testing
- All browser tests pass
- Typecheck passes


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Tests**
* Overhauled browser E2E test infrastructure with many new
helpers/fixtures, updated test APIs, and CI test container image bumped
for consistency.

* **Chores**
* Standardized line endings and applied stricter lint rules for browser
tests; workspace dependency version updated.

* **Documentation**
* Updated Playwright and TypeScript testing guidance and test-run
commands.

* **UI**
* Added stable data-testids to multiple components to improve
testability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-02-03 12:29:40 -08:00
Christian Byrne
bc3b9585f9 fix: localize node definition filter names and descriptions (#8540)
## Summary

Localizes node definition filter names and descriptions using vue-i18n,
following the project's coding guidelines.

## Changes

- Updated `registerCoreNodeDefFilters()` in `src/stores/nodeDefStore.ts`
to use `t()` function calls
- Added translation keys under `nodeFilters` namespace in
`src/locales/en/main.json`

## Affected Filters

| Filter ID | Name |
|-----------|------|
| `core.deprecated` | Hide Deprecated Nodes |
| `core.experimental` | Hide Experimental Nodes |
| `core.dev_only` | Hide Dev-Only Nodes |
| `core.subgraph` | Hide Subgraph Nodes |

Fixes #8390

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8540-fix-localize-node-definition-filter-names-and-descriptions-2fb6d73d365081f29506ed804c233b5a)
by [Unito](https://www.unito.io)
2026-02-02 11:48:00 -08:00
Comfy Org PR Bot
22daf48748 docs: Weekly Documentation Update (#7849)
# Documentation Audit and Corrections

## Summary

- Fixed incorrect test directory reference in AGENTS.md (`tests-ui/` →
removed)
- Updated outdated timestamps in composables and stores READMEs
- Fixed critical workflow name error in create-frontend-release command
- Removed misleading i18n workflow warnings from release documentation

## Changes Made

### AGENTS.md
- **Line 24**: Removed non-existent `tests-ui/` directory from test file
locations
  - Unit/component tests are located in `src/**/*.test.ts` only
- **Line 267**: Removed `tests-ui` from repository navigation guidance

### src/composables/README.md
- **Line 88**: Updated timestamp from "2025-01-30" to "2026-01-30" to
reflect current state

### src/stores/README.md
- **Line 105**: Updated timestamp from "2025-09-01" to "2026-01-29" to
reflect last modification date

### .claude/commands/create-frontend-release.md
- **Line 394**: Fixed critical workflow name error
  - Changed `version-bump.yaml` → `release-version-bump.yaml`
  - This was causing command failures as the workflow file doesn't exist
- **Lines 446-450**: Removed outdated warning about `update-locales`
workflow adding `[skip ci]`
  - No such workflow exists in the repository
- Current i18n workflows are: `i18n-update-core.yaml`,
`i18n-update-custom-nodes.yaml`, `i18n-update-nodes.yaml`
  - None of these add `[skip ci]` to commits
- **Lines 464-465**: Removed duplicate critical warning about
non-existent `update-locales` workflow

## Review Notes

### Documentation Accuracy Verification Process

Conducted comprehensive fact-checking of all documentation against the
current codebase:

1. **Configuration Files**: Verified all referenced config files exist
(vite.config.mts, playwright.config.ts, eslint.config.ts, .oxfmtrc.json,
.oxlintrc.json)
2. **Package Scripts**: Validated all npm/pnpm commands referenced in
documentation
3. **Directory Structure**: Confirmed project structure matches
documented layout
4. **Extension Documentation**: Verified TypeScript interface paths and
external resource links
5. **Testing Documentation**: Confirmed test file patterns and framework
references
6. **Command Documentation**: Validated workflow names and GitHub CLI
commands

### Known Documentation Gaps (Not Addressed)

These items were identified but not changed as they represent
aspirational guidance or current migration paths:

1. **docs/guidance/vue-components.md**: Documents Vue 3.5 prop
destructuring pattern (`const { prop } = defineProps<>()`) while
codebase still uses `withDefaults()` in many files
   - This is intentional - guidance shows preferred pattern for new code
2. **docs/guidance/playwright.md**: Advises against `waitForTimeout` but
4 test files still use it
   - Existing violations are technical debt
3. **AGENTS.md Line 163**: States "Avoid new usage of PrimeVue
components" but some components still use PrimeVue
   - Guidance is for new code; existing usage being gradually migrated
4. **docs/guidance/typescript.md**: Discourages `as any` but 11
instances exist in codebase
   - Known technical debt

### Additional Findings

- All README files in key directories (composables, stores, services,
extensions, testing) are accurate and comprehensive
- External documentation links (Vue, Tailwind, VueUse, etc.) are valid
- Code examples in documentation are syntactically correct
- i18n structure and paths are correctly documented

## Verification Commands

To verify the fixes:

```bash
# Verify tests-ui directory doesn't exist
ls tests-ui 2>&1 | grep "No such file"

# Verify correct workflow file exists
ls .github/workflows/release-version-bump.yaml

# Verify no workflows add [skip ci]
grep -r "skip ci" .github/workflows/*.yaml || echo "None found (expected)"

# Verify test files are in src/
find src -name "*.test.ts" | wc -l  # Should show many test files
```

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
2026-02-02 01:30:34 -08:00
Christian Byrne
544ef5bb70 fix: dedupe queueStore.update() to prevent race conditions (#8523)
## Summary

Prevents stale API responses from overwriting fresh queue state during
rapid consecutive `update()` calls.

## Problem

When `queueStore.update()` is called multiple times in quick succession
(e.g., during websocket reconnection), responses could resolve
out-of-order. A stale response resolving after a fresh one would
overwrite the current state with outdated data.

## Solution

Added request ID tracking that:
1. Increments a counter on each `update()` call
2. Guards all state mutations with a staleness check
3. Only sets `isLoading=false` for the latest request

This pattern matches the existing approach in `jobOutputCache.ts`.

## Changes

- `src/stores/queueStore.ts`: Added `updateRequestId` counter and
staleness guards
- `src/stores/queueStore.test.ts`: Added tests for deduplication
behavior

## Testing

- All 49 existing tests pass
- Added 3 new tests for race condition handling:
  - Stale responses are discarded
  - isLoading state is correctly managed
  - Stale request failures don't affect latest state

## Fixes COM-12784

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8523-fix-dedupe-queueStore-update-to-prevent-race-conditions-2fa6d73d3650810daa0dc63af359e1ea)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-31 22:01:14 -08:00
Christian Byrne
4f2872460c fix: remove delete account button and direct users to support (#8515)
## Summary
Reverts PR #5216 delete account functionality. The delete button only
removed Firebase accounts without canceling Stripe subscriptions,
causing orphaned accounts and support issues.

## Changes
- Removed delete account button from UserPanel.vue
- Added text directing users to contact support@comfy.org for account
deletion (clickable mailto: link)
- Cleaned up related code: removed `handleDeleteAccount` from
useCurrentUser.ts, `deleteAccount` from useFirebaseAuthActions.ts,
`_deleteAccount` from firebaseAuthStore.ts
- Updated en/main.json locale with `contactSupport` key using {email}
placeholder

## Testing
- Typecheck and lint pass
- Manual verification: user settings panel shows contact support text
instead of delete button

## Related Issues
Fixes COM-14243

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8515-fix-remove-delete-account-button-and-direct-users-to-support-2fa6d73d3650819dbc83efb41c07a809)
by [Unito](https://www.unito.io)

Co-authored-by: Amp <amp@ampcode.com>
2026-01-31 19:14:44 -08:00
Christian Byrne
c4e5fc8dbf fix: update reactive ref after merge in imagePreviewStore (#8479)
## Summary
Fix for COM-14110: Preview image does not display new outputs in
vue-nodes.

## Problem
The merge logic in `setOutputsByLocatorId` updated `app.nodeOutputs` but
returned early without updating the reactive `nodeOutputs.value` ref.
This caused Vue components to never receive merged output updates
because only the non-reactive `app.nodeOutputs` was being updated.

## Solution
Added `nodeOutputs.value[nodeLocatorId] = existingOutput` after the
merge loop, before the return statement.

## Testing
- Added 2 unit tests covering the merge behavior
- All 4076 existing unit tests pass
- Typechecks pass
- Lint passes

## Notes
- Related open PRs touching same files: #8143, #8366 - potential minor
conflicts possible

Fixes COM-14110

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8479-fix-update-reactive-ref-after-merge-in-imagePreviewStore-2f86d73d365081f1a145fa5a9782515f)
by [Unito](https://www.unito.io)

Co-authored-by: Amp <amp@ampcode.com>
2026-01-30 16:49:57 -08:00
Alexander Brown
59c58379fe fix: migrate remaining ECMAScript private fields to TypeScript private (#8495)
Migrates remaining `#field` syntax to `private _field` for Vue
reactivity compatibility.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8495-fix-migrate-remaining-ECMAScript-private-fields-to-TypeScript-private-2f86d73d365081ec87afe2273c0ff6eb)
by [Unito](https://www.unito.io)

Co-authored-by: Amp <amp@ampcode.com>
2026-01-30 13:24:16 -08:00
Christian Byrne
e7d3bc7285 fix: properties panel obscures menus in legacy layout (#8474)
## Summary

Fixes overlap issue where the new menu's node properties panel could
cover the old floating menu.

## Changes

Hide the properties panel when using the legacy menu, so it doesn't
obscure the old menu. The properties panel did not work anyway (empy
content).


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8474-fix-increase-z-index-of-legacy-floating-menu-2f86d73d365081a0ab44db24c2ea6357)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-30 08:16:11 -08:00
Christian Byrne
47113b117e refactor: migrate keybindings to DDD structure (#8369)
## Summary

Migrate keybindings domain to `src/platform/keybindings/` following DDD
principles.

## Changes

- **What**: Consolidate keybinding-related code (types, store, service,
defaults, reserved keys) into a single domain module with flat structure
- Extracted `KeyComboImpl` and `KeybindingImpl` classes into separate
files
- Updated all consumers to import from new location
- Colocated tests with source files
- Updated stores/README.md and services/README.md to remove migrated
entries

## Review Focus

- Verify all import paths were updated correctly
- Check that the flat structure is appropriate (vs nested core/data/ui
layers)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8369-refactor-migrate-keybindings-to-DDD-structure-2f66d73d36508120b169dc737075fb45)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Subagent 5 <subagent@example.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-01-29 18:40:58 -08:00
Johnpaul Chiwetelu
13311a46ea Road to No explicit any: Group 8 (part 7) test files (#8459)
## Summary

This PR removes unsafe type assertions ("as unknown as Type") from test
files and improves type safety across the codebase.

### Key Changes

#### Type Safety Improvements
- Removed improper `as unknown as Type` patterns from 17 test files in
Group 8 part 7
- Replaced with proper TypeScript patterns using factory functions and
Mock types
- Fixed createTestingPinia usage in test files (was incorrectly using
createPinia)
- Fixed vi.hoisted pattern for mockSetDirty in viewport tests  
- Fixed vi.doMock lint issues with vi.mock and vi.hoisted pattern
- Retained necessary `as unknown as` casts only for complex mock objects
where direct type assertions would fail

### Files Changed

Test files (Group 8 part 7 - services, stores, utils):
- src/services/nodeOrganizationService.test.ts
- src/services/providers/algoliaSearchProvider.test.ts
- src/services/providers/registrySearchProvider.test.ts
- src/stores/comfyRegistryStore.test.ts
- src/stores/domWidgetStore.test.ts
- src/stores/executionStore.test.ts
- src/stores/firebaseAuthStore.test.ts
- src/stores/modelToNodeStore.test.ts
- src/stores/queueStore.test.ts
- src/stores/subgraphNavigationStore.test.ts
- src/stores/subgraphNavigationStore.viewport.test.ts
- src/stores/subgraphStore.test.ts
- src/stores/systemStatsStore.test.ts
- src/stores/workspace/nodeHelpStore.test.ts
- src/utils/colorUtil.test.ts
- src/utils/executableGroupNodeChildDTO.test.ts

Source files:
- src/stores/modelStore.ts - Improved type handling

### Testing
- All TypeScript type checking passes (`pnpm typecheck`)
- All affected test files pass (`pnpm test:unit`)
- Linting passes without errors (`pnpm lint`)
- Code formatting applied (`pnpm format`)

Part of the "Road to No Explicit Any" initiative, cleaning up type
casting issues from branch `fix/remove-any-types-part8`.

### Previous PRs in this series:
- Part 2: #7401
- Part 3: #7935
- Part 4: #7970
- Part 5: #8064
- Part 6: #8083
- Part 7: #8092
- Part 8 Group 1: #8253
- Part 8 Group 2: #8258
- Part 8 Group 3: #8304
- Part 8 Group 4: #8314
- Part 8 Group 5: #8329
- Part 8 Group 6: #8344
- Part 8 Group 7: #8459 (this PR)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8459-Road-to-No-explicit-any-Group-8-part-7-test-files-2f86d73d36508114ad28d82e72a3a5e9)
by [Unito](https://www.unito.io)
2026-01-30 03:38:06 +01:00
Christian Byrne
80ccc13659 feat: add Chatterbox model support for Cloud asset browser (#8418)
## Summary

Adds support for creating Chatterbox TTS nodes when clicking Chatterbox
models in the Cloud asset browser.

## Changes

### modelToNodeStore.ts
- Add `findProvidersWithFallback()` helper for hierarchical model type
lookups (e.g., `parent/child` falls back to `parent`)
- Register 4 Chatterbox model directories with empty widget keys:
  - `chatterbox/chatterbox` → `FL_ChatterboxTTS`
  - `chatterbox/chatterbox_turbo` → `FL_ChatterboxTurboTTS`
- `chatterbox/chatterbox_multilingual` → `FL_ChatterboxMultilingualTTS`
  - `chatterbox/chatterbox_vc` → `FL_ChatterboxVC`

### createModelNodeFromAsset.ts
- Skip widget assignment when `provider.key` is empty (for nodes that
auto-load models without a widget selector)

### Tests
- Add tests for hierarchical fallback behavior
- Add tests for empty widget key (auto-load nodes)
- Add Chatterbox node types to mock data

## Notes

- Empty `key` convention: Chatterbox nodes auto-load their models and
don't have a model selector widget, so we register them with `key: ''`
and skip the widget assignment step
- Hierarchical fallback only goes one level deep (`a/b/c` → `a`, not
`a/b`)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8418-feat-add-Chatterbox-model-support-for-Cloud-asset-browser-2f76d73d365081be822bc369b155f099)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Subagent 5 <subagent@example.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: GitHub Action <action@github.com>
2026-01-29 16:26:51 -08:00
Christian Byrne
d9ea36a1d0 refactor: change asset cache from nodeType-keyed to category-keyed (#8433)
## Summary

Refactors the model assets cache in `assetsStore.ts` to be keyed by
category (e.g., 'checkpoints', 'loras') instead of nodeType (e.g.,
'CheckpointLoaderSimple').

## Changes

- Rename `modelStateByKey` to `modelStateByCategory`
- Add `resolveCategory()` helper to translate nodeType to category for
cache lookup
- Multiple node types sharing the same category now share one cache
entry
- Add `invalidateCategory()` method for cache invalidation
- Maintain backwards-compatible public API accepting nodeType
- Update tests for new category-keyed behavior

## Benefits

1. **Deduplication**: Same category = same cache entry = single API call
2. **Simple invalidation**: Delete asset with tag 'checkpoints' then
invalidate cache
3. **Cleaner mental model**: Store to View reactive flow works naturally

## Testing

- All existing tests pass with updates
- Added new tests for category-keyed cache sharing, invalidateCategory,
and unknown node type handling

## Part of Stack

This is **PR 1 of 2** in a stacked PR series:
1. **This PR**: Refactor asset cache to category-keyed (architectural
improvement)
2. **[PR 2
#8434](https://github.com/Comfy-Org/ComfyUI_frontend/pull/8434)**: Fix
deletion invalidation

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8433-refactor-change-asset-cache-from-nodeType-keyed-to-category-keyed-2f76d73d365081999b7fda12c9706ab5)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Subagent 5 <subagent@example.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-29 16:03:29 -08:00
Johnpaul Chiwetelu
cabd08f0ec Road to No explicit any: Group 8 (part 6) test files (#8344)
## Summary

This PR removes unsafe type assertions ("as unknown as Type") from test
files and improves type safety across the codebase.

### Key Changes

#### Type Safety Improvements
- Removed all instances of "as unknown as" patterns from test files
- Used proper factory functions from litegraphTestUtils instead of
custom mocks
- Made incomplete mocks explicit using Partial<T> types
- Fixed DialogStore mocking with proper interface exports
- Improved type safety with satisfies operator where applicable

#### App Parameter Removal
- **Removed the unused `app` parameter from all ComfyExtension interface
methods**
- The app parameter was always undefined at runtime as it was never
passed from invokeExtensions
- Affected methods: init, setup, addCustomNodeDefs,
beforeRegisterNodeDef, beforeRegisterVueAppNodeDefs,
registerCustomNodes, loadedGraphNode, nodeCreated, beforeConfigureGraph,
afterConfigureGraph

##### Breaking Change Analysis
Verified via Sourcegraph that this is NOT a breaking change:
- Searched all 10 affected methods across GitHub repositories
- Only one external repository
([drawthingsai/draw-things-comfyui](https://github.com/drawthingsai/draw-things-comfyui))
declares the app parameter in their extension methods
- That repository never actually uses the app parameter (just declares
it in the function signature)
- All other repositories already omit the app parameter
- Search queries used:
- [init method
search](https://sourcegraph.com/search?q=context:global+repo:%5Egithub%5C.com/.*+lang:typescript+%22init%28app%22+-repo:Comfy-Org/ComfyUI_frontend&patternType=standard)
- [setup method
search](https://sourcegraph.com/search?q=context:global+repo:%5Egithub%5C.com/.*+lang:typescript+%22setup%28app%22+-repo:Comfy-Org/ComfyUI_frontend&patternType=standard)
  - Similar searches for all 10 methods confirmed no usage

### Files Changed

Test files:
-
src/components/settings/widgets/__tests__/WidgetInputNumberInput.test.ts
- src/services/keybindingService.escape.test.ts  
- src/services/keybindingService.forwarding.test.ts
- src/utils/__tests__/newUserService.test.ts →
src/utils/__tests__/useNewUserService.test.ts
- src/services/jobOutputCache.test.ts
-
src/renderer/extensions/vueNodes/widgets/composables/useRemoteWidget.test.ts
-
src/renderer/extensions/vueNodes/widgets/composables/useIntWidget.test.ts
-
src/renderer/extensions/vueNodes/widgets/composables/useFloatWidget.test.ts

Source files:
- src/types/comfy.ts - Removed app parameter from ComfyExtension
interface
- src/services/extensionService.ts - Improved type safety with
FunctionPropertyNames helper
- src/scripts/metadata/isobmff.ts - Fixed extractJson return type per
review
- src/extensions/core/*.ts - Updated extension implementations
- src/scripts/app.ts - Updated app initialization

### Testing
- All existing tests pass
- Type checking passes  
- ESLint/oxlint checks pass
- No breaking changes for external repositories

Part of the "Road to No Explicit Any" initiative.

### Previous PRs in this series:
- Part 2: #7401
- Part 3: #7935
- Part 4: #7970
- Part 5: #8064
- Part 6: #8083
- Part 7: #8092
- Part 8 Group 1: #8253
- Part 8 Group 2: #8258
- Part 8 Group 3: #8304
- Part 8 Group 4: #8314
- Part 8 Group 5: #8329
- Part 8 Group 6: #8344 (this PR)
2026-01-29 11:03:17 -08:00
Christian Byrne
23a5baef43 feat: add category support for blueprints and protect global blueprints (#8378)
## Summary

This PR adds two related features for subgraph blueprints:

### 1. Protect Global Blueprints from Deletion
- Added `isGlobalBlueprint()` helper that distinguishes blueprints by
`python_module` field
- User blueprints have `python_module: 'blueprint'`
- Global (installed) blueprints have `python_module` set to the node
pack name
- Guarded `deleteBlueprint()` to show a warning toast for global
blueprints
- Hidden delete menu in node library for global blueprints

### 2. Category Support for Blueprints
- User blueprints now use category `Subgraph Blueprints/User`
- Global blueprints use `Subgraph Blueprints/{category}` if category is
provided, otherwise `Subgraph Blueprints`
- Extended `GlobalSubgraphData.info` type with optional `category` field
- Added `category` to `zSubgraphDefinition` schema

## Files Changed
- `src/stores/subgraphStore.ts` - Core logic for both features
- `src/stores/subgraphStore.test.ts` - Tests for `isGlobalBlueprint`
- `src/components/sidebar/tabs/nodeLibrary/NodeTreeLeaf.vue` - Hide
delete menu for global blueprints
- `src/scripts/api.ts` - Extended `GlobalSubgraphData` type
- `src/platform/workflow/validation/schemas/workflowSchema.ts` - Added
category to schema
- `src/locales/en/main.json` - Added translation key

## Testing
-  `pnpm typecheck` passed
-  `pnpm lint` passed

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8378-feat-add-category-support-for-blueprints-and-protect-global-blueprints-2f66d73d36508137aa67c2d88c358b69)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Subagent 5 <subagent@example.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: AustinMroz <austin@comfy.org>
2026-01-28 23:30:48 -08:00
Alexander Brown
6ce60a11a4 test: use createTestingPinia instead of createPinia (#8376)
Replace \createPinia\ with \createTestingPinia({ stubActions: false })\
from \@pinia/testing\ across 45 test files for proper test isolation.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8376-test-use-createTestingPinia-instead-of-createPinia-2f66d73d36508137a9f0daffcddc86f7)
by [Unito](https://www.unito.io)

Co-authored-by: Amp <amp@ampcode.com>
2026-01-28 22:21:38 -08:00
Christian Byrne
3b5d124029 fix: use getAuthHeader in createCustomer to support API key auth (#8408)
## Summary

Fixes authentication failure when using API key authentication on
staging server after frontend update to 1.33.10.

<img width="1160" height="709" alt="image"
src="https://github.com/user-attachments/assets/fe56866d-1819-419e-9f53-35a123d764c3"
/>


## Changes

- **What**: Changed `createCustomer()` to use `getAuthHeader()` instead
of `getFirebaseAuthHeader()`, allowing API key users to authenticate
successfully

## Review Focus

- Verify `getAuthHeader()` correctly falls back to API key when no
Firebase token exists
- Backend `/customers` endpoint supports `X-API-KEY` header (per cloud
PR #1766)

Fixes COM-12398

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8408-fix-use-getAuthHeader-in-createCustomer-to-support-API-key-auth-2f76d73d3650819994e3e6d3ed9f3dfa)
by [Unito](https://www.unito.io)

Co-authored-by: Subagent 5 <subagent@example.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-01-28 22:12:28 -08:00
guill
9be853f6b5 feat: support dev-only nodes (#8359)
## Summary

Support `dev_only` property to node definitions that hides nodes from
search and menus unless dev mode is enabled. Dev-only nodes display a
"DEV" badge when visible.

This functionality is primarily intended to support unit-testing nodes
on Comfy Cloud, but also has other uses.

## Changes

- **What**: Nodes flagged as dev_only in the node schema will only
appear in search and menus if Dev Mode is on.

## Screenshots (if applicable)

With Dev Mode off:
<img width="2189" height="1003" alt="image"
src="https://github.com/user-attachments/assets/a08e1fd7-dca9-4ce1-9964-5f4f3b7b95ac"
/>

With Dev Mode on:
<img width="2201" height="1066" alt="image"
src="https://github.com/user-attachments/assets/7fe6cd1f-f774-4f48-b604-a528e286b584"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8359-feat-support-dev-only-nodes-2f66d73d36508102839ee7cd66a26129)
by [Unito](https://www.unito.io)
2026-01-28 19:41:45 -08:00
Benjamin Lu
cbd073f89d Add inline queue progress bar and text summary (#8271)
Add inline queue progress bar and summary per the new designs.

This adds an inline 3px progress bar in the actionbar container (docked
or floating) and a compact summary line below the top menu that follows
when floating, both gated by the QPO V2 flag and hidden while the
overlay is expanded.


https://github.com/user-attachments/assets/da8ec7b7-35f4-4d52-a83b-15c21b484eba

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8271-Add-inline-queue-progress-bar-and-summary-for-QPO-V2-2f16d73d36508132a6dff247f71e11e4)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-28 12:20:13 -08:00
Alexander Brown
e44b411ff6 test: simplify test file mocking patterns (#8320)
Simplifies test mocking patterns across multiple test files.

- Removes redundant `vi.hoisted()` calls
- Cleans up mock implementations
- Removes unused imports and variables

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8320-test-simplify-test-file-mocking-patterns-2f46d73d36508150981bd8ecb99a6a11)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-28 12:17:16 -08:00
Simula_r
34fc28a39d Feat/workspaces 5 auth gate check (#8350)
## Summary

- Fix auth related race conditions with a new WorkspaceAuthGate in
App.vue
- De dup initialization calls 
- Add state machine to track state of refreshRemoteConfig
- Fix websocket not using new workspace jwt
- Misc improvments

## Changes

- **What**: Mainly WorkspaceAuthGate.vue
- **Breaking**: <!-- Any breaking changes (if none, remove this line)
-->
- **Dependencies**: <!-- New dependencies (if none, remove this line)
-->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8350-Feat-workspaces-5-auth-gate-check-2f66d73d365081b1a49afcd418fab3e7)
by [Unito](https://www.unito.io)
2026-01-27 20:28:44 -08:00
pythongosssss
d890e7568a Add asset deletion progress indicator (#7906)
## Summary

Currently the delay between user action and visual response is too long
and it looks like it hasn't worked.
This adds a visual indicator that the action is processing.

## Changes

- add loading indicator while asset is deleting

## Screenshots (if applicable)
(Artifically delayed deletion)


https://github.com/user-attachments/assets/a9a8b9fe-896d-4666-b643-ec8b990f6444

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7906-Add-asset-deletion-progress-indicator-2e26d73d365081ed82b8e770ba3d0615)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: Jin Yi <jin12cc@gmail.com>
2026-01-27 21:21:50 -07:00
Benjamin Lu
2c54b0dab0 Revert/undo-788f5083-ef8657bb (#8353)
This reverts the addition of GTM for 1.38, as it was still present in
the built files.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8353-Revert-undo-788f5083-ef8657bb-2f66d73d365081818d43fcaab220a4ef)
by [Unito](https://www.unito.io)
2026-01-28 03:48:31 +00:00
Alexander Brown
aa5125cef6 Chore: Oxfmt formatting pass (#8341)
## Summary

Expanding the covered files to format. One-time formatting pass. To be
added to the `.git-blame-ignore-revs`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8341-Chore-Oxfmt-formatting-pass-2f56d73d365081f2988fcb7570f9a2a1)
by [Unito](https://www.unito.io)
2026-01-27 17:59:19 -08:00
Alexander Brown
bcb4d6e403 fix: await needsLogin (#8340)
## Summary

Add additional protection for bootstrap order issues.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8340-fix-await-needsLogin-2f56d73d365081c9b3c6d5a091c1eb8d)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-27 14:04:35 -08:00
Alexander Brown
14369c08a3 refactor: parallelize bootstrap and simplify lifecycle with VueUse (#8307)
## Summary

Refactors bootstrap and lifecycle management to parallelize
initialization, use Vue best practices, and fix a logout state bug.

## Changes

### Bootstrap Store (`bootstrapStore.ts`)
- Extract early bootstrap logic into a dedicated store using
`useAsyncState`
- Parallelize settings, i18n, and workflow sync loading (previously
sequential)
- Handle multi-user login scenarios by deferring settings/workflows
until authenticated

### GraphCanvas Refactoring
- Move non-DOM composables (`useGlobalLitegraph`, `useCopy`, `usePaste`,
etc.) to script setup level for earlier initialization
- Move `watch` and `whenever` declarations outside `onMounted` (Vue best
practice)
- Use `until()` from VueUse to await bootstrap store readiness instead
of direct async calls

### GraphView Simplification
- Replace manual `addEventListener`/`removeEventListener` with
`useEventListener`
- Replace `setInterval` with `useIntervalFn` for automatic cleanup
- Move core command registration to script setup level

### Bug Fix
Using `router.push()` for logout caused `isSettingsReady` to persist as
`true`, making new users inherit the previous user's cached settings.
Reverted to `window.location.reload()` with TODOs for future store reset
implementation.

## Testing

- Verified login/logout cycle clears settings correctly
- Verified bootstrap sequence completes without errors

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-27 12:50:13 -08:00
Benjamin Lu
788f50834c feat: add cloud gtm injection (#8311)
## Summary

Add GTM injection for cloud distribution builds and push SPA page view +
signup events.

## Changes

- **What**: Inject GTM script into head-prepend and noscript iframe into
body-prepend for cloud builds
- **What**: Push `page_view` to `dataLayer` on cloud route changes
(page_location + page_title)
- **What**: Push `sign_up` to `dataLayer` after successful account
creation (email/google/github)
- **Dependencies**: None

## Review Focus

- Placement order for head-prepend/body-prepend and cloud-only gating
- Route-change page_view payload shape
- Signup event emission only for new users

## Screenshots (if applicable)

<img width="1512" height="860" alt="Screenshot 2026-01-26 at 11 38
11 AM"
src="https://github.com/user-attachments/assets/03fb61db-5ca4-4432-9704-bbdcc4c6c1b7"
/>

<img width="1512" height="862" alt="Screenshot 2026-01-26 at 11 38
26 AM"
src="https://github.com/user-attachments/assets/6e46c855-a552-4e52-9800-17898a512d4d"
/>
2026-01-27 12:44:15 -08:00
Alexander Brown
6a5b5c968f refactor: replace vi.doMock with vi.mock + vi.hoisted (#8319)
Replace `vi.doMock` with `vi.mock` + `vi.hoisted` pattern for cleaner
test mocking.

- Add ESLint rule to prevent future `doMock` usage
- Refactor `versionUtil.test.ts` and `firebaseAuthStore.test.ts`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8319-refactor-replace-vi-doMock-with-vi-mock-vi-hoisted-2f46d73d365081ae9fccf2fa7471a75b)
by [Unito](https://www.unito.io)

Co-authored-by: Amp <amp@ampcode.com>
2026-01-26 14:08:54 -08:00
Simula_r
4771565486 Workspaces 4 members invites (#8245)
## Summary

  Add team workspace member management and invite system.

## Changes

- Add members panel with role management (owner/admin/member) and member
removal
- Add invite system with email invites, pending invite display, and
revoke functionality
   - Add invite URL loading for accepting invites
  - Add subscription panel updates for member management
  - Add i18n translations for member and invite features

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8245-Workspaces-4-members-invites-2f06d73d36508176b2caf852a1505c4a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-24 15:52:40 -08:00
Alexander Brown
15655ddb76 Updates: More Modal Modification (#8256)
Refactors modal dialog layouts for improved flexibility and consistency.

**Changes:**
- Add dedicated slot for left panel header title with dynamic
content/icons
- Consolidate side panel rendering within `BaseModalLayout`
- Remove redundant `PanelHeader` and `RightSidePanel` components
- Apply `select-none` to text elements to prevent accidental selection

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-23 20:41:35 -08:00
Alexander Brown
4b1a30e330 Updates: Model Management (#8248)
## Summary

Model management improvements: refactored tag API, enhanced UX for
trigger phrases and editing.

## Changes

### API Refactor
- Add `addAssetTags` (POST) and `removeAssetTags` (DELETE) endpoints in
assetService
- `updateAssetTags` now computes diff and calls remove/add serially
- Add `TagsOperationResult` schema; cache syncs with server response

### UX Improvements
- **Trigger phrases**: click to copy individual phrases, copy-all button
in header
- **Display name**: show edit icon on hover instead of relying on
double-click
- **Model type**: show plain text when immutable instead of disabled
select
- **Tags input**: only show edit icon on hover
- **Field labels**: updated styling to use muted foreground color
- **Optimistic update** for model type selection

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-23 00:10:54 +00:00
Simula_r
a08ccb55c1 Workspaces 3 create a workspace (#8221)
## Summary

Add workspace creation and management (create, edit, delete, leave,
switch workspaces).

  Follow-up PR will add invite and membership flow.

  ## Changes

  - Workspace CRUD dialogs
  - Workspace switcher popover in topbar
  - Workspace settings panel
  - Subscription panel for workspace context
  

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8221-Workspaces-3-create-a-workspace-2ef6d73d36508155975ffa6e315971ec)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 14:54:41 -07:00
Alexander Piskun
5c142275ad Move price badges to python nodes (#7816)
## Summary

Backend part: https://github.com/Comfy-Org/ComfyUI/pull/11582

- Move API node pricing definitions from hardcoded frontend functions to
backend-defined JSONata expressions
- Add `price_badge` field to node definition schema containing JSONata
expression and dependency declarations
- Implement async JSONata evaluation with signature-based caching for
efficient reactive updates
- Show one decimal in credit badges when meaningful (e.g., 1.5 credits
instead of 2 credits)

## Screenshots (if applicable)

<!-- Add screenshots or video recording to help explain your changes -->

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7816-Move-price-badges-to-python-nodes-2da6d73d365081ec815ef61f7e3c65f7)
by [Unito](https://www.unito.io)
2026-01-22 09:17:07 -08:00
Benjamin Lu
92357445e4 feat: show active jobs label in top menu (#8169)
Replace the top-menu queue history icon with a localized “N active”
label so active jobs are visible at a glance.

Requested as part of the new
[designs](https://www.figma.com/design/LVilZgHGk5RwWOkVN6yCEK/Queue-Progress-Modal?node-id=3381-6181&m=dev).

I checked all failing snapshots and they are all expected (1 flaky).

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8169-feat-show-active-jobs-label-in-top-menu-2ee6d73d3650812cbf0cda389395c563)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2026-01-21 20:45:29 -07:00
Alexander Brown
93e7a4f9f9 feat(assets): add ModelInfoPanel for asset browser right panel (#8090)
## Summary

Adds an editable Model Info Panel to show and modify asset details in
the asset browser.

## Changes

- Add `ModelInfoPanel` component with editable display name,
description, model type, base models, and tags
- Add `updateAssetMetadata` action in `assetsStore` with optimistic
cache updates
- Add shadcn-vue `Select` components with design system styling
- Add utility functions in `assetMetadataUtils` for extracting model
metadata
- Convert `BaseModalLayout` right panel state to `defineModel` pattern
- Add slide-in animation and collapse button for right panel
- Add `class` prop to `PropertiesAccordionItem` for custom styling
- Fix keyboard handling: Escape in TagsInput/TextArea doesn't close
parent modal

## Testing

- Unit tests for `ModelInfoPanel` component
- Unit tests for `assetMetadataUtils` functions

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
2026-01-21 19:43:56 -08:00
Alexander Brown
482159957e feat: implement progressive pagination for Asset Browser model assets (#8212)
## Summary

Implements progressive pagination for model assets - returns the first
batch immediately while loading remaining batches in the background.

## Changes

### Store (`assetsStore.ts`)
- Adds `ModelPaginationState` tracking (assets Map, offset, hasMore,
loading, error)
- `updateModelsForKey()` returns first batch, then calls
`loadRemainingBatches()` to fetch the rest
- Accessor functions `getAssets(key)`, `isModelLoading(key)` replace
direct Map access

### API (`assetService.ts`)
- Adds `PaginationOptions` interface (`{ limit?, offset? }`)

### Components
- `AssetBrowserModal.vue` uses new accessor API

### Tests
- Updated mocks for new accessor pattern

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8212-feat-implement-progressive-pagination-for-Asset-Browser-model-assets-2ef6d73d36508157af04d1264780997e)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-21 17:59:08 -08:00
Alexander Brown
f1d1747582 feat: add session download tracking to assetDownloadStore (#8213)
## Summary

Add session download tracking to track which assets were downloaded
during the current session. This enables UI features like:
- Badge count on "Imported" nav showing newly downloaded assets
- Visual indicator on asset cards for recently downloaded items

## Changes

- Add `acknowledged` flag to `AssetDownload` interface
- Add `unacknowledgedDownloads` computed for filtering
- Add `sessionDownloadCount` computed for badge display
- Add `isDownloadedThisSession(identifier)` to check individual assets
- Add `acknowledgeDownload(identifier)` to mark assets as seen

## Testing

- 6 new unit tests covering all session tracking functionality
- Run: `pnpm test:unit -- src/stores/assetDownloadStore.test.ts`

## Related

- Part of Asset Browser improvements (#8090)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8213-feat-add-session-download-tracking-to-assetDownloadStore-2ef6d73d365081538045e8544d26bafa)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-01-21 16:32:30 -08:00
Simula_r
66e6f24980 feat: add workspace session, auth, and store infrastructure (#8194)
## Summary
- Add `teamWorkspaceStore` Pinia store for workspace state management
(workspaces, members, invites, current workspace)
- Add `workspaceApi` client for workspace CRUD, member management, and
invite operations
- Update `useWorkspaceSwitch` composable for workspace switching logic
- Update `useSessionCookie` for workspace-aware sessions
- Update `firebaseAuthStore` for workspace aware auth
- Use `workspaceAuthStore` for workspace auth flow

## Test plan
- [x] 59 unit tests passing (50 store tests + 9 switch tests)
- [x] Typecheck passing
- [x] Lint passing
- [x] Knip passing

Note: This PR depends on the `team_workspaces_enabled` feature flag
being available (already in main).

🤖 Generated with [Claude Code](https://claude.ai/code)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8194-feat-add-workspace-session-auth-and-store-infrastructure-2ef6d73d3650814984afe8ee7ba0a209)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 13:18:47 -07:00
Jin Yi
d9e5b07c73 [bugfix] Clear queue button now properly removes initializing jobs from UI (#8203)
## Summary

- Fix: Initializing jobs now properly disappear from UI when cancelled
or cleared
- Add `clearInitializationByPromptIds` batch function for optimized Set
operations
- Handle Cloud vs local environment correctly (use `api.deleteItem` for
Cloud, `api.interrupt` for local)

## Problem

When clicking 'Clear queue' button or X button on initializing jobs, the
jobs remained visible in both AssetsSidebarListView and JobQueue
components until page refresh.

## Root Cause

1. `initializingPromptIds` in `executionStore` was not being cleared
when jobs were cancelled/deleted
2. Cloud environment requires `api.deleteItem()` instead of
`api.interrupt()` for cancellation

## Changes

- `src/stores/executionStore.ts`: Export `clearInitializationByPromptId`
and add batch `clearInitializationByPromptIds` function
- `src/composables/queue/useJobMenu.ts`: Add Cloud branch handling and
initialization cleanup
- `src/components/queue/QueueProgressOverlay.vue`: Fix `onCancelItem()`,
`cancelQueuedWorkflows()`, `interruptAll()`
- `src/components/sidebar/tabs/AssetsSidebarTab.vue`: Add initialization
cleanup to `handleClearQueue()`


[screen-capture.webm](https://github.com/user-attachments/assets/0bf911c2-d8f4-427c-96e0-4784e8fe0f08)


🤖 Generated with [Claude Code](https://claude.com/claude-code)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8203-bugfix-Clear-queue-button-now-properly-removes-initializing-jobs-from-UI-2ef6d73d36508162a55bd84ad39ab49c)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 14:15:58 +09:00
Christian Byrne
54db655a23 feat: make subgraphs blueprints appear higher in node library sidebar (#8140)
## Summary

Changes insertion order so subgraph blueprints are inserted first and
therefore appear highest in node library sidebar (when using default
'original' ordering).

<img width="1003" height="725" alt="image"
src="https://github.com/user-attachments/assets/3f1ea61c-4191-4dd5-8c10-17cd91b6a732"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8140-feat-make-subgraphs-blueprints-appear-higher-in-node-library-sidebar-2ec6d73d3650816f8164f0991b81c116)
by [Unito](https://www.unito.io)
2026-01-17 20:43:24 -07:00
Alexander Brown
de2e37ec8e chore: merge vitest config into vite.config.mts (#8132)
Moves vitest configuration from `vitest.config.ts` into the `test`
section of `vite.config.mts` and deletes the separate vitest config
file.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8132-chore-merge-vitest-config-into-vite-config-mts-2eb6d73d365081ab81b5dca11fadf13a)
by [Unito](https://www.unito.io)
2026-01-17 13:02:55 -08:00
pythongosssss
3bbae61763 Decouple node help between sidebar and right panel (#8110)
## Summary

When the node library is open and you click on the node toolbar info
button, this causes the node library info panel & right panel node info
to show the same details.

## Changes

- Extract useNodeHelpContent composable so NodeHelpContent fetches its
own content, allowing multiple panels to show help independently
- Remove sync behavior from NodeHelpPage that caused left sidebar to
change when selecting different graph nodes since we want to prioritise
right panel for this behavior
- Add telemetry tracking for node library help button to identify how
frequently this is used

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8110-Decouple-node-help-between-sidebar-and-right-panel-2ea6d73d365081a9b3afd25aa51b34bd)
by [Unito](https://www.unito.io)
2026-01-16 22:13:23 -07:00
ric-yu
c0a649ef43 refactor: encapsulate error extraction in TaskItemImpl getters (#7650)
## Summary
- Add `errorMessage` and `executionError` getters to `TaskItemImpl` that
extract error info from status messages
- Update `useJobErrorReporting` composable to use these getters instead
of standalone function
- Remove the standalone `extractExecutionError` function

This encapsulates error extraction within `TaskItemImpl`, preparing for
the Jobs API migration where the underlying data format will change but
the getter interface will remain stable.

## Test plan
- [x] All existing tests pass
- [x] New tests added for `TaskItemImpl.errorMessage` and
`TaskItemImpl.executionError` getters
- [x] TypeScript, lint, and knip checks pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7650-refactor-encapsulate-error-extraction-in-TaskItemImpl-getters-2ce6d73d365081caae33dcc7e1e07720)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
2026-01-15 21:11:22 -07:00
Christian Byrne
6048fab239 feat: add per-tab workspace authentication infrastructure (#8073)
## Summary
Add workspace authentication composables and types for per-tab workspace
isolation. This infrastructure enables users to work in different
workspaces in different browser tabs.

## Changes
- **useWorkspaceAuth composable** - workspace token management
- Exchange Firebase token for workspace-scoped JWT via `POST
/api/auth/token`
  - Auto-refresh tokens 5 minutes before expiry
  - Per-tab sessionStorage caching
- **useWorkspaceSwitch composable** - workspace switching with unsaved
changes confirmation
- **WorkspaceWithRole/WorkspaceTokenResponse types** - aligned with
backend API
- **firebaseAuthStore.getAuthHeader()** - prioritizes workspace tokens
over Firebase tokens
- **useSessionCookie** - uses Firebase token directly (getIdToken())
since getAuthHeader() now returns workspace token

## Backend Dependency
- `POST /api/auth/token` - exchange Firebase token for workspace token
- `GET /api/workspaces` - list user's workspaces

## Related
- https://github.com/Comfy-Org/ComfyUI_frontend/pull/6295

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8073-feat-add-per-tab-workspace-authentication-infrastructure-2e96d73d3650816c8cf9dae9c330aebb)
by [Unito](https://www.unito.io)

---------

Co-authored-by: anthropic/claude <noreply@anthropic.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Simula_r <18093452+simula-r@users.noreply.github.com>
2026-01-15 17:24:48 -08:00
AustinMroz
0d5ca96a2b Further linear fixes (#8074)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8074-Further-linear-fixes-2e96d73d365081efb74bf150982c7a66)
by [Unito](https://www.unito.io)
2026-01-15 14:45:19 -08:00
Terry Jia
45d95728f3 fix: preserve image preview when backend returns null output (#8050)
## Summary

When two LoadImage nodes select the same image, the backend's cache
mechanism returns null output for the second node (same cache
signature). This was overwriting the existing image preview data.

Now skip setting outputs when null/undefined to preserve the preview.

Root cause chain
07f2462eae/execution.py (L421):

1. When two LoadImage nodes select the same image, they have identical
cache signatures (based on IS_CHANGED SHA256 hash + input parameters)
2. First node executes: Actually runs load_image(), caches the result.
But LoadImage's ui field is None (it only produces tensors, no UI
output)
3. Second node executes: Cache hit, directly returns
cached_ui.get("output", None) = null
  4. Frontend receives null and overwrites the existing image preview

## Screenshots (if applicable)
Before


https://github.com/user-attachments/assets/7bd814f6-bf23-42cc-9fc3-fd9fec68b4f6


After


https://github.com/user-attachments/assets/b9cc6160-ea70-424e-8a3d-5dc9f244d0d0

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8050-fix-preserve-image-preview-when-backend-returns-null-output-2e86d73d36508156ab32cb12a7f6b307)
by [Unito](https://www.unito.io)
2026-01-14 15:28:20 -05:00
AustinMroz
25afd39d2b linear v2: Simple Mode (#7734)
A major, full rewrite of linear mode, now under the name "Simple Mode". 
- Fixes widget styling
- Adds a new simplified history
- Adds support for non-image outputs
- Supports right sidebar
- Allows and panning on the output image preview
- Provides support for drag and drop zones
- Moves workflow notes into a popover.
- Allows scrolling through outputs with Ctrl+scroll or arrow keys

The primary means of accessing Simple Mode is a toggle button on the
bottom right. This button is only shown if a feature flag is enabled, or
the user has already seen linear mode during the current session. Simple
Mode can also be accessed by
- Using the toggle linear mode keybind
- Loading a workflow that that was saved in Simple Mode workflow
- Loading a template url with appropriate parameter

<img width="1790" height="1387" alt="image"
src="https://github.com/user-attachments/assets/d86a4a41-dfbf-41e7-a6d9-146473005606"
/>

Known issues:
- Outputs on cloud are not filtered to those produced by the current
workflow.
  - Output filtering has been globally disabled for consistency
- Outputs will load more items on scroll, but does not unload
- Performance may be reduced on weak devices with very large histories.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7734-linear-v2-2d16d73d3650819b8a10f150ff12ea22)
by [Unito](https://www.unito.io)
2026-01-13 20:18:31 -08:00
Rizumu Ayaka
b1b2fd8a4f feat: right side panel favorites, no selection state, and more... (#7812)
Most of the features in this pull request are completed and can be
reviewed and merged.

## TODO

- [x] no selection panel
- [x] group selected panel
- [x] tabs 
  - [x] favorites tab
  - [x] global settings tab
  - [x] nodes tab
- [x] widget actions menu 
  - [x] [Bug]: style bugs
- [x] button zoom to the node on canvas.
- [x] rename widgets on widget actions
  - [ ] [Bug]: the canvas has not been updated after renaming. 
- [x] global settings
  - [ ] setting item: "show advanced parameters"
    - blocked by other things. skip for now.
  - [x] setting item: show toolbox on selection 
  - [x] setting item: nodes 2.0
  - [ ] setting item: "background color"
    - blocked by other things. skip for now.
  - [x] setting item: grid spacing
  - [x] setting item: snap nodes to grid
  - [x] setting item: link shape
  - [x] setting item: show connected links
  - [x] form style reuses the form style of node widgets
- [x] group node cases
  - [x] group node settings
  - [x] show all nodes in group
  - [x] show frame name on nodes when multiple selections are made
  - [x] group multiple selections
- [x] [Bug]: nodes without widgets cannot display the location and their
group
  - [x] [Bug]: labels layout
- [x] favorites
  - [x] the indicator on widgets
  - [x] favorite and unfavorite buttons on widgets
- [x] [Bug]: show node name in favorite widgets + improve labels layout
- [ ] [Bug]: After canceling the like, the like list will not be updated
immediately.
- [x] [Bug]: The favorite function does not work for the project on
Subgraph.
- [x] subgraph
- [x] add the node name from where this parameter comes from when node
is subgraph
  - [x] show and hide directly on Inputs
    - [x] some bugs need to be fixed.
- [x] advanced widgets 
  - [x] button: show advanced inputs
- Clicking button expands the "Advanced Inputs" section on the right
side panel, regardless of whether the panel is open or not
    - [x] [Bug]: style bugs
  - [x] advanced inputs section when node is subgraph
- [x] inputs tab rearranging
  - [x] favorited inputs rearranging
  - [x] subgraph inputs rearranging
- [ ] review and reconstruction to improve complexity and architecture

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7812-feat-right-side-panel-favorites-no-selection-state-and-more-2da6d73d36508134b503d676f9b3d248)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: bymyself <cbyrne@comfy.org>
2026-01-13 20:37:17 -07:00