Commit Graph

7 Commits

Author SHA1 Message Date
Benjamin Lu
eaa09fa92c Fix missing model direct download state 2026-05-03 03:41:15 -07:00
jaeone94
b4d209b5f6 feat: refresh missing models through pipeline (#11661)
## Summary

Follow-up to the closed earlier attempt in #11646. This PR keeps the
same user-facing goal, but changes the implementation to reuse the
existing missing model pipeline for refresh instead of maintaining a
separate candidate-only recheck path.

Adds a missing model refresh action in the Errors tab by reusing the
existing missing model pipeline, so users can re-check models after
downloading or manually placing files without reloading the workflow.

## Changes

- **What**:
- Adds `app.refreshMissingModels()` as a reusable refresh entry point
for the current root graph.
- Splits node definition reloading into `app.reloadNodeDefs()` so
missing-model refresh can pull fresh `object_info` without showing the
generic combo refresh success flow.
- Reuses the existing missing model pipeline instead of adding a
separate candidate-only checker. The refresh path serializes the current
graph, reuses active workflow model metadata when available, falls back
to current missing-model metadata, and then reruns the same candidate
discovery/enrichment/surfacing flow used during workflow load.
- Adds missing model refresh state and error handling to
`missingModelStore`.
- Adds a Refresh button next to Download all in the missing model card
action bar.
- Moves Download all from the Errors tab header into the missing model
card, so the Download all and Refresh actions render or hide together.
- Changes Download all visibility from “more than one downloadable
model” to “at least one downloadable model.”
- Keeps the action bar hidden when there are no downloadable missing
models; Cloud still does not render this action area.
- Normalizes active workflow `pendingWarnings` updates so resolved
missing model warnings do not get revived by stale empty warning
objects.
- Adds test IDs and coverage for the new action bar, refresh state,
refresh delegation, pending warning sync, and E2E refresh behavior.
- **Breaking**: None.
- **Dependencies**: None.

## Review Focus

The main design choice is intentionally reusing the missing model
pipeline for refresh instead of implementing a smaller candidate-only
recheck.

The earlier candidate-only approach was cheaper, but it created a
separate source of truth for missing-model resolution and made edge
cases harder to reason about. In particular, it could diverge from the
behavior used when a workflow is loaded, and it did not naturally handle
the case where a model becomes missing after the workflow is already
open. This version pays the cost of refreshing node definitions and
rerunning the missing-model scan for the current graph, but keeps the
refresh behavior aligned with workflow load semantics.

Expected behavior by environment:

- OSS browser:
- The action bar appears when at least one missing model has a
downloadable URL and directory.
  - Download all uses the existing browser download path.
- Refresh reloads `object_info`, refreshes node definitions/combo
values, reruns missing-model detection for the current graph, and clears
the error if the selected model is now available.
- OSS desktop:
- The same action bar appears under the same downloadable-model
condition.
  - Download all uses the existing Electron DownloadManager path.
- Refresh uses the same missing-model pipeline as browser, so manually
placed files or desktop-downloaded files can be rechecked without
reloading the workflow.
- Cloud:
- The action bar remains hidden because model download/import is not
supported in this section for Cloud.

A few boundaries are intentional:

- This PR does not add automatic filesystem watching. Browser OSS cannot
reliably observe local model folder changes, so the user-triggered
Refresh button remains the cross-environment mechanism.
- This PR does not redesign the public `refreshComboInNodes` API beyond
extracting `reloadNodeDefs()` for reuse. Further cleanup of toast
behavior or a more explicit object-info reload API can be follow-up
work.
- This PR keeps refresh scoped to missing-model validation; missing
media and missing nodes continue to use their existing flows.

Linear: FE-417

## Screenshots (if applicable)


https://github.com/user-attachments/assets/2e02799f-1374-4377-b7b3-172241517772


## Validation

- `pnpm format`
- `pnpm lint` (passes; existing unrelated warning remains in
`src/platform/workspace/composables/useWorkspaceBilling.test.ts`)
- `pnpm typecheck`
- `pnpm test:unit`
- `pnpm test:browser:local -- --project=chromium
browser_tests/tests/propertiesPanel/errorsTabMissingModels.spec.ts`
- `pnpm build`
- `NX_SKIP_NX_CACHE=true DISTRIBUTION=desktop USE_PROD_CONFIG=true
NODE_OPTIONS='--max-old-space-size=8192' pnpm exec nx build`
- Manual desktop verification through `~/Projects/desktop` after copying
the desktop build into `assets/ComfyUI/web_custom_versions/desktop_app`:
  - confirmed the FE bundle is built with `DISTRIBUTION = "desktop"`
- confirmed missing model Download uses the desktop download path
instead of browser download
- confirmed Refresh can clear the missing model error after the model is
available
- Push hook: `pnpm knip --cache`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11661-feat-refresh-missing-models-through-pipeline-34f6d73d3650811488defee54a7a6667)
by [Unito](https://www.unito.io)
2026-04-27 18:53:50 +00:00
jaeone94
521019d173 fix: exclude muted/bypassed nodes from missing asset detection (#10856)
## Summary

Muted and bypassed nodes are excluded from execution but were still
triggering missing model/media/node warnings. This PR makes the error
system mode-aware: muted/bypassed nodes no longer produce missing asset
errors, and all error lifecycle events (mode toggle, deletion, paste,
undo, tab switch) are handled consistently.

- Fixes Comfy-Org/ComfyUI#13256

## Behavioral notes

- **Tab switch overlay suppression (intentional)**: Switching back to a
workflow with missing assets no longer re-shows the error overlay. This
reverses the behavior introduced in #10190. The error state is still
restored silently in the errors tab — users can access it via the
properties panel without being interrupted by the overlay on every tab
switch.

## Changes

### 1. Scan filtering

- `scanAllModelCandidates`, `scanAllMediaCandidates`,
`scanMissingNodes`: skip nodes with `mode === NEVER || BYPASS`
- `collectMissingNodes` (serialized data): skip error reporting for
muted/bypassed nodes while still calling `sanitizeNodeName` for safe
`configure()`
- `collectEmbeddedModelsWithSource`: skip muted/bypassed nodes;
workflow-level `graphData.models` only create candidates when active
nodes exist
- `enrichWithEmbeddedMetadata`: filter unmatched workflow-level models
when all referencing nodes are inactive

### 2. Realtime mode change handling

- `useErrorClearingHooks.ts` chains `graph.onTrigger` to detect
`node:property:changed` (mode)
- Deactivation (active → muted/bypassed): remove missing
model/media/node errors for the node
- Activation (muted/bypassed → active): scan the node and add confirmed
errors, show overlay
- Subgraph container deactivation: remove all interior node errors
(execution ID prefix match)
- Subgraph container activation: scan all active interior nodes
recursively
- Subgraph interior mode change: resolve node via
`localGraph.getNodeById()` then compute execution ID from root graph

### 3. Node deletion

- `graph.onNodeRemoved`: remove missing model/media/node errors for the
deleted node
- Handle `node.graph === null` at callback time by using
`String(node.id)` for root-level nodes

### 4. Node paste/duplicate

- `graph.onNodeAdded`: scan via `queueMicrotask` (deferred until after
`node.configure()` restores widget values)
- Guard: skip during `ChangeTracker.isLoadingGraph` (undo/redo/tab
switch handled by pipeline)
- Guard: skip muted/bypassed nodes

### 5. Workflow tab switch optimization

- `skipAssetScans` option in `loadGraphData`: skip full pipeline on tab
switch
- Cache missing model/media/node state per workflow via
`PendingWarnings`
- `beforeLoadNewGraph`: save current store state to outgoing workflow's
`pendingWarnings`
- `showPendingWarnings`: restore cached errors silently (no overlay),
always sync missing nodes store (even when null)
- Preserve UI state (`fileSizes`, `urlInputs`) on tab switch by using
`setMissingModels([])` instead of `clearMissingModels()`
- `MissingModelRow.vue`: fetch file size on mount via
`fetchModelMetadata` memory cache

### 6. Undo/redo overlay suppression

- `silentAssetErrors` option propagated through pipeline →
`surfaceMissingModels`/`surfaceMissingMedia` `{ silent }` option
- `showPendingWarnings` `{ silent }` option for missing nodes overlay
- `changeTracker.ts`: pass `silentAssetErrors: true` on undo/redo

### 7. Error tab node filtering

- Selected node filters missing model/media card contents (not just
group visibility)
- `isAssetErrorInSelection`: resolve execution ID → graph node for
selection matching
- Missing nodes intentionally unfiltered (pack-level scope)
- `hasMissingMediaSelected` added to `RightSidePanel.vue` error tab
visibility
- Download All button: show only when 2+ downloadable models exist

### 8. New store functions

- `missingModelStore`: `addMissingModels`, `removeMissingModelsByNodeId`
- `missingMediaStore`: `addMissingMedia`, `removeMissingMediaByNodeId`
- `missingNodesErrorStore`: `removeMissingNodesByNodeId`
- `missingModelScan`: `scanNodeModelCandidates` (extracted single-node
scan)
- `missingMediaScan`: `scanNodeMediaCandidates` (extracted single-node
scan)

### 9. Test infrastructure improvements

- `data-testid` on `RightSidePanel.vue` tabs (`panel-tab-{value}`)
- Error-related TestIds moved from `dialogs` to `errorsTab` namespace in
`selectors.ts`
- Removed unused `TestIdValue` type
- Extracted `cleanupFakeModel` to shared `ErrorsTabHelper.ts`
- Renamed `openErrorsTabViaSeeErrors` → `loadWorkflowAndOpenErrorsTab`
- Added `aria-label` to pencil edit button and subgraph toggle button

## Test plan

### Unit tests (41 new)

- Store functions: `addMissing*`, `removeMissing*ByNodeId`
- `executionErrorStore`: `surfaceMissing*` silent option
- Scan functions: muted/bypassed filtering, `scanNodeModelCandidates`,
`scanNodeMediaCandidates`
- `workflowService`: `showPendingWarnings` silent, `beforeLoadNewGraph`
caching

### E2E tests (17 new in `errorsTabModeAware.spec.ts`)

**Missing nodes**
- [x] Deleting a missing node removes its error from the errors tab
- [x] Undo after bypass restores error without showing overlay

**Missing models**
- [x] Loading a workflow with all nodes bypassed shows no errors
- [x] Bypassing a node hides its error, un-bypassing restores it
- [x] Deleting a node with missing model removes its error
- [x] Undo after bypass restores error without showing overlay
- [x] Pasting a node with missing model increases referencing node count
- [x] Pasting a bypassed node does not add a new error
- [x] Selecting a node filters errors tab to only that node

**Missing media**
- [x] Loading a workflow with all nodes bypassed shows no errors
- [x] Bypassing a node hides its error, un-bypassing restores it
- [x] Pasting a bypassed node does not add a new error
- [x] Selecting a node filters errors tab to only that node

**Subgraph**
- [x] Bypassing a subgraph hides interior errors, un-bypassing restores
them
- [x] Bypassing a node inside a subgraph hides its error, un-bypassing
restores it

**Workflow switching**
- [x] Does not resurface error overlay when switching back to workflow
with missing nodes
- [x] Restores missing nodes in errors tab when switching back to
workflow

# Screenshots


https://github.com/user-attachments/assets/e0a5bcb8-69ba-4120-ab7f-5c83e4cfc3c5



## Follow-up work

- Extract error-detection computed properties from `RightSidePanel.vue`
into a composable (e.g. `useErrorsTabVisibility`)

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: GitHub Action <action@github.com>
2026-04-13 12:51:19 +00:00
Dante
cdf74c36f7 tool: add layer architecture boundary lint rule (#10109)
## Summary
- Add `import-x/no-restricted-paths` ESLint rule enforcing the `base →
platform → workbench → renderer` layer hierarchy
- Set to `error` with eslint-disable comments on existing violations
(~11 suppressions)
- Consolidate zone definitions using array syntax for `from`/`target`
- Add `layer-audit` Claude skill for auditing violations
- Fix knip false positive for `zod` dependency in ingest-types

## Context
Ref:
https://github.com/Comfy-Org/ComfyUI_frontend/pull/10021#discussion_r2939392141

The codebase is migrating toward a layered architecture. This adds
static enforcement so new violations are caught in PR CI.

### Layer rules
| Layer | Can import from |
|---|---|
| `base/` | nothing |
| `platform/` | `base/` |
| `workbench/` | `platform/`, `base/` |
| `renderer/` | `workbench/`, `platform/`, `base/` |

### Current violations (pre-existing, suppressed with eslint-disable)
| Direction | Count |
|---|---|
| base → platform | 2 |
| platform → workbench | 3 |
| platform → renderer | 5 |
| workbench → renderer | 1 |

## Test plan
- [x] `pnpm lint` passes (0 errors, 0 warnings)
- [x] `pnpm typecheck` passes
- [x] `pnpm knip` passes
- [ ] CI green

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 02:08:25 -07:00
jaeone94
e2ef041170 feat: surface missing models in Error Tab for OSS and remove legacy dialog (#9921)
## Summary
- Surface missing models in the Error Tab for OSS environments,
replacing the legacy modal dialog
- Add Download button per model and Download All button in group header
with file size display
- Move download business logic from `components/dialog/content` to
`platform/missingModel`
- Remove legacy missing models dialog components and composable

## Changes
- **Pipeline**: Remove `isCloud` guard from `scanAllModelCandidates` and
`surfaceMissingModels` so OSS detects missing models
- **Grouping**: Group non-asset-supported models by directory in OSS
instead of lumping into UNSUPPORTED
- **UI**: Add Download button (matching Install Node Pack design) and
Download All header button
- **Store**: Add `folderPaths`/`fileSizes` state with setter methods,
race condition guard
- **Cleanup**: Delete `MissingModelsContent`, `MissingModelsHeader`,
`MissingModelsFooter`, `useMissingModelsDialog`, `missingModelsUtils`
- **Tests**: Add OSS/Cloud grouping tests, migrate Playwright E2E to
Error Tab, improve test isolation
- **Snapshots**: Reset Playwright screenshot expectations since OSS
missing model error detection now causes red highlights on affected
nodes
- **Accessibility**: Add `aria-label` with model name, `aria-expanded`
on toggle, warning icon for unknown category

## Test plan
- [x] Unit tests pass (86 tests)
- [x] TypeScript typecheck passes
- [x] knip passes
- [x] Load workflow with missing models in OSS → Error Tab shows missing
models grouped by directory
- [x] Download button triggers browser download with correct URL
- [x] Download All button downloads all downloadable models
- [x] Cloud environment behavior unchanged
- [x] Playwright E2E: `pnpm test:browser:local -- --grep "Missing models
in Error Tab"`

## Screenshots


https://github.com/user-attachments/assets/12f15e09-215a-4c58-87ed-39bbffd1359c

 


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9921-feat-surface-missing-models-in-Error-Tab-for-OSS-and-remove-legacy-dialog-3236d73d365081f0a9dfc291978f5ecf)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
2026-03-15 22:46:47 +09:00
jaeone94
31a33a0ba2 feat: auto-resolve simple validation errors on widget change and slot connection (#9464)
## Summary

Automatically clears transient validation errors
(`value_bigger_than_max`, `value_smaller_than_min`, `value_not_in_list`,
`required_input_missing`) when the user modifies a widget value or
connects an input slot, so resolved errors don't linger in the error
panel. Also clears missing model state when the user changes a combo
widget value.

## Changes

- **`useNodeErrorAutoResolve` composable**: watches widget changes and
slot connections, clears matching errors via `executionErrorStore`
- **`executionErrorStore`**: adds `clearSimpleNodeErrors` and
`clearSimpleWidgetErrorIfValid` with granular per-slot error removal
- **`executionErrorUtil`**: adds `isValueStillOutOfRange` to prevent
premature clearing when a new value still violates the constraint
- **`graphTraversalUtil`**: adds `getExecutionIdFromNodeData` for
subgraph-aware execution ID resolution
- **`GraphCanvas.vue`**: fixes subgraph error key lookup by using
`getExecutionIdByNode` instead of raw `node.id`
- **`NodeWidgets.vue`**: wires up the new composable to the widget layer
- **`missingModelStore`**: adds `removeMissingModelByWidget` to clear
missing model state on widget value change
- **`useGraphNodeManager`**: registers composable per node
- **Tests**: 126 new unit tests covering error clearing, range
validation, and graph traversal edge cases

## Screenshots



https://github.com/user-attachments/assets/515ea811-ff84-482a-a866-a17e5c779c39



https://github.com/user-attachments/assets/a2b30f02-4929-4537-952c-a0febe20f02e


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9464-feat-auto-resolve-simple-validation-errors-on-widget-change-and-slot-connection-31b6d73d3650816b8afdc34f4b40295a)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 23:49:44 +09:00
jaeone94
2f7f3c4e56 [feat] Surface missing models in Errors tab (Cloud) (#9743)
## Summary
When a workflow is loaded with missing models, users currently have no
way to identify or resolve them from within the UI. This PR adds a full
missing-model detection and resolution pipeline that surfaces missing
models in the Errors tab, allowing users to install or import them
without leaving the editor.

## Changes

### Missing Model Detection
- Scan all COMBO widgets across root graph and subgraphs for model-like
filenames during workflow load
- Enrich candidates with embedded workflow metadata (url, hash,
directory) when available
- Verify asset-supported candidates against the asset store
asynchronously to confirm installation status
- Propagate missing model state to `executionErrorStore` alongside
existing node/prompt errors

### Errors Tab UI — Model Resolution
- Group missing models by directory (e.g. `checkpoints`, `loras`, `vae`)
with collapsible category cards
- Each model row displays:
  - Model name with copy-to-clipboard button
  - Expandable list of referencing nodes with locate-on-canvas button
- **Library selector**: Pick an alternative from the user's existing
models to substitute the missing model with one click
- **URL import**: Paste a Civitai or HuggingFace URL to import a model
directly; debounced metadata fetch shows filename and file size before
confirming; type-mismatch warnings (e.g. importing a LoRA into
checkpoints directory) are surfaced with an "Import Anyway" option
- **Upgrade prompt**: In cloud environment, free-tier subscribers are
shown an upgrade modal when attempting URL import
- Separate "Import Not Supported" section for custom-node models that
cannot be auto-resolved
- Status card with live download progress, completion, failure, and
category-mismatch states

### Canvas Integration
- Highlight nodes and widgets that reference missing models with error
indicators
- Propagate missing-model badges through subgraph containers so issues
are visible at every graph level

### Code Cleanup
- Simplify `surfacePendingWarnings` in workflowService, remove stale
widget-detected model merging logic
- Add `flattenWorkflowNodes` utility to workflowSchema for traversing
nested subgraph structures
- Extract `MissingModelUrlInput`, `MissingModelLibrarySelect`,
`MissingModelStatusCard` as focused single-responsibility components

## Testing
- Unit tests for scan pipeline (`missingModelScan.test.ts`): enrichment,
skip-installed, subgraph flattening
- Unit tests for store (`missingModelStore.test.ts`): state management,
removal helpers
- Unit tests for interactions (`useMissingModelInteractions.test.ts`):
combo select, URL input, import flow, library confirm
- Component tests for `MissingModelCard` and error grouping
(`useErrorGroups.test.ts`)
- Updated `workflowService.test.ts` and `workflowSchema.test.ts` for new
logic

## Review Focus
- Missing model scan + enrichment pipeline in `missingModelScan.ts`
- Interaction composable `useMissingModelInteractions.ts` — URL metadata
fetch, library install, upload fallback
- Store integration and canvas-level error propagation

## Screenshots 


https://github.com/user-attachments/assets/339a6d5b-93a3-43cd-98dd-0fb00681b66f



┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9743-feat-Surface-missing-models-in-Errors-tab-Cloud-3206d73d365081678326d3a16c2165d8)
by [Unito](https://www.unito.io)
2026-03-12 16:21:54 +09:00