mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 06:20:11 +00:00
fix: hide template selector after shared workflow accept (#9913)
Hide the template selector when a first-time cloud user accepts a shared workflow from a share link, so the shared workflow opens without the onboarding template dialog lingering. - **What**: Added shared-workflow loader behavior to close the global template selector on accept actions (`copy-and-open` and `open-only`) while keeping cancel behavior unchanged. - **What**: Added targeted unit tests covering hide-on-accept and no-hide-on-cancel behavior in the shared workflow URL loader. Confirm that share-link accept paths now dismiss the template selector and that cancel still leaves it available. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9913-fix-hide-template-selector-after-shared-workflow-accept-3236d73d365081099c04e350d499fad2) by [Unito](https://www.unito.io) Co-authored-by: Amp <amp@ampcode.com> fix: restore native copy/paste events for image paste support (#9914) - Remove Ctrl+C and Ctrl+V keybindings from the keybinding service defaults so native browser copy/paste events fire - This restores image paste into LoadImage nodes, which broke after PR #9459 moved Ctrl+C/V into the keybinding service, which calls `event.preventDefault()` on keydown. This prevents the browser `paste` event from firing, so `usePaste` (which detects images in the clipboard) never runs. The `PasteFromClipboard` command only reads from localStorage, completely bypassing image detection. **Repro:** Copy a node → copy an image externally → try to paste the image into a LoadImage node → gets old node data from localStorage instead. Remove Ctrl+C and Ctrl+V from `CORE_KEYBINDINGS` in `defaults.ts`. The native browser events now fire as before, and `useCopy`/`usePaste` handle them correctly. Ctrl+Shift+V, Ctrl+A, Delete, and Backspace keybindings remain in the keybinding service. Fixes #9459 (regression) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9914-fix-restore-native-copy-paste-events-for-image-paste-support-3236d73d365081c7ac53f983f316e10f) by [Unito](https://www.unito.io) fix: clear stale widget slotMetadata on link disconnect (#9885) Fixes text field becoming non-editable when a previously linked input is removed from a custom node. When a widget's input was promoted to a slot, connected via a link, and then the input was removed (e.g., by updating the custom node definition), the widget retained stale `slotMetadata` with `linked: true`. This prevented the widget from being editable. In `refreshNodeSlots`, removed the `if (slotInfo)` guard so `widget.slotMetadata` is always assigned — either to valid metadata or `undefined`. This ensures stale linked state is cleared when inputs no longer match widgets. 1. Text field remains editable after promote→connect→disconnect cycle 2. Text field returns to editable state when noodle disconnected 3. No mode switching needed to restore editability - Added regression test: "clears stale slotMetadata when input no longer matches widget" - All existing tests pass (18/18 in affected file) --- **Note: This PR currently contains only the RED (failing test) commit for TDD verification. The GREEN (fix) commit will be pushed after CI confirms the test failure.** ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9885-fix-clear-stale-widget-slotMetadata-on-link-disconnect-3226d73d365081269319c027b42d9f6b) by [Unito](https://www.unito.io) fix: stabilize subgraph promoted widget identity and rendering (#9896) Fix subgraph promoted widget identity/rendering so on-node widgets stay correct through configure/hydration churn, duplicate names, and linked+independent coexistence. - **Subgraph promotion reconciliation**: stabilize linked-entry identity by subgraph slot id, preserve deterministic linked representative selection, and prune stale alias/fallback entries without dropping legitimate independent promotions. - **Promoted view resolution**: bind slot mapping by promoted view object identity (`getSlotFromWidget` / `getWidgetFromSlot`) to avoid same-name collisions. - **On-node widget rendering**: harden `NodeWidgets` identity and dedup to avoid visual aliasing, prefer visible duplicates over hidden stale entries, include type/source execution identity, and avoid collapsing transient unresolved entries. - **Mapping correctness**: update `useGraphNodeManager` promoted source mapping to resolve by input target only when the promoted view is actually bound to that input. - **Subgraph input uniqueness**: ensure empty-slot promotion creates unique input names (`seed`, `seed_1`, etc.) for same-name multi-source promotions. - **Safety fix**: guard against undefined canvas in slot-link interaction. - **Tests/fixtures**: add focused regressions for fixture path `subgraph_complex_promotion_1`, linked+independent same-name cases, duplicate-name identity mapping, dedup behavior, and input-name uniqueness. Validate behavior around transient configure/hydration states (`-1` id to concrete id), duplicate-name promotions, linked representative recovery, and that dedup never hides legitimate widgets while still removing true duplicates. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9896-fix-stabilize-subgraph-promoted-widget-identity-and-rendering-3226d73d365081c8a1e8d0a5a22e826d) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp <amp@ampcode.com> 1.42.5 (#9906) Patch version increment to 1.42.5 **Base branch:** `main` --------- Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com> Co-authored-by: github-actions <github-actions@github.com> fix: skip redundant appScalePercentage updates during zoom/pan (#9403) Add equality check before updating `appScalePercentage` reactive ref. Firefox profiler shows 586 `setElementText` markers from continuous text interpolation updates during zoom/pan. The rounded percentage value often doesn't change between events. Extract `updateAppScalePercentage()` helper with equality guard — compares new rounded value to current before assigning to the ref. Expected: eliminates ~90% of `setElementText` markers during zoom/pan ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9403-fix-skip-redundant-appScalePercentage-updates-during-zoom-pan-31a6d73d3650812db8f2d68ac73c95b0) by [Unito](https://www.unito.io) test: add browser test for textarea right-click context menu in subgraph (#9891) Add E2E test coverage for the textarea widget right-click context menu inside subgraphs. The fix was shipped in #9840 — this PR adds the missing browser test. - Loads a subgraph workflow with a CLIPTextEncode (textarea) node - Navigates into the subgraph - Right-clicks the textarea DOM element - Asserts that the ComfyUI "Promote Widget" context menu option appears - Fixes the test gap from #9840 - Notion ticket: d7a53160-e1e1-42bb-a5ac-c0c2702c629c ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9891-test-add-browser-test-for-textarea-right-click-context-menu-in-subgraph-3226d73d365081a4be51f89b5d505361) by [Unito](https://www.unito.io) feat: expand CDP perf metrics — add DOM nodes, script duration, event listeners (#9887) Expands the performance testing infrastructure to collect 4 additional CDP metrics that are already returned by `Performance.getMetrics` but were not being read. This is a zero-cost expansion — no additional CDP calls, just reading more fields from the existing response. | Metric | CDP Source | What It Detects | |---|---|---| | `domNodes` | `Nodes` | DOM node count delta — widget DOM leaks during node create/destroy | | `jsHeapTotalBytes` | `JSHeapTotalSize` | Total heap delta — combined with `heapDeltaBytes` shows GC pressure | | `scriptDurationMs` | `ScriptDuration` | JS execution time vs total task time — script vs rendering balance | | `eventListeners` | `JSEventListeners` | Listener count delta — detects listener accumulation across lifecycle | - Added 4 fields to `PerfSnapshot` interface - Added 4 fields to `PerfMeasurement` interface - Wired through `getSnapshot()` and `stopMeasuring()` - Added 4 fields to `PerfMeasurement` interface - Expanded `MetricKey` type and `REPORTED_METRICS` array with 3 new reported metrics (`domNodes`, `scriptDurationMs`, `eventListeners`) - `jsHeapTotalBytes` is collected but not in `REPORTED_METRICS` — it's used alongside `heapDeltaBytes` for GC pressure ratio analysis From a gap analysis of all ~30 CDP metrics, these were identified as highest priority for ComfyUI: - **`Nodes`** (P0): ComfyUI dynamically creates/destroys widget DOM. DOM bloat from leaked widgets is a key performance risk, especially for Vue Nodes 2.0. - **`ScriptDuration`** (P1): Separates JS execution from layout/paint. Reveals whether perf issues are script-heavy or rendering-heavy. - **`JSEventListeners`** (P1): Widget lifecycle can leak listeners across node add/remove cycles. - **`JSHeapTotalSize`** (P1): With `JSHeapUsedSize`, the ratio shows GC fragmentation pressure. The `PerfMeasurement` interface is extended (not changed). Old baseline `perf-metrics.json` files without these fields will have `undefined` values, which the report script handles gracefully (shows `—` for missing data). ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9887-feat-expand-CDP-perf-metrics-add-DOM-nodes-script-duration-event-listeners-3226d73d3650818abea1d4a441667c38) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> Co-authored-by: Alexander Brown <drjkl@comfy.org> fix: prevent white flash when opening mask editor (#9860) - Remove hardcoded `bg-white` from mask editor canvas background div to prevent white flash on dialog open - Add a loading spinner while the mask editor initializes (image loading, canvas setup, GPU resources) - Background color is set dynamically by `setCanvasBackground()` after initialization Fixes #9852 https://github.com/user-attachments/assets/7da61e32-671b-4056-b5ec-8cb246fc7689 https://github.com/user-attachments/assets/bfdedc69-f690-42c5-8591-619623c04f55 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9860-fix-prevent-white-flash-when-opening-mask-editor-3226d73d365081de9b7ad4622438e6ed) by [Unito](https://www.unito.io) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> fix: prevent live preview dimension flicker between frames (#9937) Fix "Calculating dimensions" text flickering during live sampling preview in Vue renderer. - **What**: Stop resetting `actualDimensions` to `null` on every `imageUrl` change. Previous dimensions are retained while the new frame loads, eliminating the flicker. Error state is still reset correctly. The watcher on `props.imageUrl` previously reset both `actualDimensions` and `imageError`. Now it only resets `imageError`, since `handleImageLoad` updates dimensions when the new frame actually loads. This means stale dimensions show briefly between frames, which is intentionally better than showing "Calculating dimensions" text. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9937-fix-prevent-live-preview-dimension-flicker-between-frames-3246d73d36508154a676e5996112354f) by [Unito](https://www.unito.io) feat: make Vue nodes (Nodes 2.0) default for new desktop installs (#9947) Makes Vue nodes (Nodes 2.0) the default renderer for new desktop app installs (version ≥1.41.0), matching the behavior already live for cloud new installs. Step 2 of the Nodes 2.0 rollout sequence: 1. ✅ Cloud new installs (≥1.41.0) — DONE 2. 👉 **Desktop app (new installs)** — this PR 3. ⬜ Local installs 4. ⬜ Remove Beta tag 5. ⬜ GTM announcement No forced migration — only changes the default for new installs. Existing users keep their setting. Rollback is a settings flip. In `coreSettings.ts`, the `defaultsByInstallVersion` for `Comfy.VueNodes.Enabled` changes from: ```typescript defaultsByInstallVersion: { '1.41.0': isCloud }, ``` to: ```typescript defaultsByInstallVersion: { '1.41.0': isCloud || isDesktop }, ``` - M2 perf target (≥52 FPS on 245-node workflow) — layer merge landed, likely met - M-DevRel migration docs (blocks Beta tag removal, not this flip) Draft PR — ceremonial, to be merged when M2 checkpoint passes. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9947-feat-make-Vue-nodes-Nodes-2-0-default-for-new-desktop-installs-3246d73d365081b280dfff932c7aa016) by [Unito](https://www.unito.io) fix: fix perf CI pipeline — z-score baselines, force-push staleness, baseline storage (#9886) Fixes three critical issues with the CI performance reporting pipeline that made perf reports useless on PRs (demonstrated by PR #9248 — deep watcher removal merged without useful perf signal). **Root cause:** PR #9305 added z-score statistical analysis code to `perf-report.ts`, but the historical data download step was placed in the wrong workflow file. The report is generated in `pr-perf-report.yaml` (a `workflow_run`-triggered job), but the historical download was in `ci-perf-report.yaml` (the test runner) — different runners, different filesystems. **Fix:** Implement `perf-data` orphan branch storage: - On push to main: save `perf-metrics.json` to `perf-data` branch with timestamped filename - On PR report: fetch last 5 baselines from `perf-data` branch into `temp/perf-history/` - Rolling window of 20 baselines, oldest pruned automatically - Same pattern used by `github-action-benchmark` (33.7k repos) **Root cause:** `cancel-in-progress: true` kills the perf test run before it uploads artifacts. The downstream report workflow only triggers on `conclusion == 'success'` — cancelled runs are ignored, so the comment from the first successful run goes stale. **Fix:** - Change `cancel-in-progress: false` — with GitHub's queue depth of 1, rapid pushes (A,B,C,D) run A and D, skipping B and C - Add SHA validation in `pr-perf-report.yaml` — before posting, check if the workflow_run's head SHA still matches the PR's current head. Skip posting stale results. - `contents: write` on CI job (needed for pushing to perf-data branch) - `actions: read` on both workflows (needed for artifact/baseline access) After merging, create the `perf-data` orphan branch: ```bash git checkout --orphan perf-data git rm -rf . echo '# Performance Baselines' > README.md mkdir -p baselines git add README.md baselines git commit -m 'Initialize perf-data branch' git push origin perf-data ``` The first 2 pushes to main after setup will build up variance data, and z-scores will start appearing in PR reports (threshold is `historical.length >= 2`). - YAML validated with `yaml.safe_load()` - `perf-report.ts` `loadHistoricalReports()` already reads from `temp/perf-history/<index>/perf-metrics.json` — no code changes needed - All new steps use `continue-on-error: true` for graceful degradation ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9886-fix-fix-perf-CI-pipeline-z-score-baselines-force-push-staleness-baseline-storage-3226d73d365081538424c7945e71f308) by [Unito](https://www.unito.io) draft: add red-green-fix skill for verified bug fix workflow (#9954) - Add a Claude Code skill (`/red-green-fix`) that enforces the red-green commit pattern for bug fixes - Ensures a failing test is committed first (red CI), then the fix is committed separately (green CI) - Gives reviewers proof that the test actually catches the bug - Includes `reference/testing-anti-patterns.md` with common mistakes contextualized to this codebase ``` .claude/skills/red-green-fix/ ├── SKILL.md # Main skill definition └── reference/ └── testing-anti-patterns.md # Anti-patterns guide ``` - [ ] Invoke `/red-green-fix <bug description>` in Claude Code and verify the two-step workflow - [ ] Confirm PR template includes red-green verification table - [ ] Review anti-patterns reference for completeness ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9954-draft-add-red-green-fix-skill-for-verified-bug-fix-workflow-3246d73d365081339a83dc09263b0f33) by [Unito](https://www.unito.io) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: GitHub Action <action@github.com> test: add large-graph perf test with 245-node workflow (backlog N5) (#9940) Adds a 245-node workflow asset and two `@perf` tests to establish a baseline for large-graph performance regressions (Tier 6 in the performance backlog). Backlog item N5: we need CI regression detection for compositor layer management, GPU texture count, and transform pane cost at 245+ nodes. This is PR1 of 2 — establishes baseline metrics on main. Future optimization PRs will show improvement deltas against this baseline. - **`large graph idle rendering`** — 120 frames idle with 245 nodes, measures style recalcs, layouts, task duration, heap delta - **`large graph pan interaction`** — middle-click pan across 245 nodes, stresses compositor layer management and transform recalculation `browser_tests/assets/large-graph-workflow.json` — 245 nodes (49 pipelines of CheckpointLoader → 2× CLIPTextEncode → KSampler + EmptyLatentImage), 294 links. Minimal structure focused on node count. - [x] `pnpm typecheck:browser` passes - [x] `pnpm lint` passes (eslint on changed file) - [x] All link references in JSON validated programmatically ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9940-test-add-large-graph-perf-test-with-245-node-workflow-backlog-N5-3246d73d365081f6b5d8ddb9a85e6ad0) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> feat: add Ingest API codegen with Zod schema generation (#9932) - Add `packages/ingest-types/` package that auto-generates TypeScript types and Zod schemas from the Ingest service OpenAPI spec - Uses `@hey-api/openapi-ts` with built-in Zod plugin (Zod v3 compatible) - Filters out overlapping endpoints shared with the local ComfyUI Python backend - Generates **493 TypeScript types** and **256 Zod schemas** covering cloud-only endpoints - Configure knip to ignore generated files The cloud repo pushes generated types to this repo (push model, no private repo cloning). See: Comfy-Org/cloud#2858 Codegen targets are controlled by the **exclude list** in `packages/ingest-types/openapi-ts.config.ts`. Everything in the Ingest `openapi.yaml` is included **except** overlapping endpoints that also exist in the local ComfyUI Python backend: **Excluded (overlapping with ComfyUI Python):** `/prompt`, `/queue`, `/history`, `/object_info`, `/features`, `/settings`, `/system_stats`, `/interrupt`, `/upload/*`, `/view`, `/jobs`, `/userdata`, `/webhooks/*`, `/internal/*` **Included (cloud-only, codegen targets):** `/workspaces/*`, `/billing/*`, `/secrets/*`, `/assets/*`, `/tasks/*`, `/auth/*`, `/workflows/*`, `/workspace/*`, `/user`, `/settings/{key}`, `/tags`, `/feedback`, `/invite_code/*`, `/experiment/models/*`, `/global_subgraphs/*` This PR only sets up the codegen infrastructure. A follow-up PR should replace manually maintained types with imports from `@comfyorg/ingest-types`: | File | Lines | Current | Replace with | |------|-------|---------|-------------| | `src/platform/workspace/api/workspaceApi.ts` | ~270 | TS interfaces | `import type { ... } from '@comfyorg/ingest-types'` | | `src/platform/secrets/types.ts` | ~32 | TS interfaces | `import type { ... } from '@comfyorg/ingest-types'` | | `src/platform/assets/schemas/assetSchema.ts` | ~125 | Zod schemas | `import { ... } from '@comfyorg/ingest-types/zod'` | | `src/platform/assets/schemas/mediaAssetSchema.ts` | ~50 | Zod schemas | `import { ... } from '@comfyorg/ingest-types/zod'` | | `src/platform/tasks/services/taskService.ts` | ~70 | Zod schemas | `import { ... } from '@comfyorg/ingest-types/zod'` | | `src/platform/workspace/workspaceTypes.ts` | ~6 | TS interface | `export type { ... } from '@comfyorg/ingest-types'` | - [x] `pnpm generate` in `packages/ingest-types/` produces `types.gen.ts` and `zod.gen.ts` - [x] `pnpm typecheck` passes - [x] Pre-commit hooks pass (lint, typecheck, format) - [x] Generated Zod schemas validate correct data and reject invalid data - [x] No import conflicts with existing code (generated types are isolated in separate package) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: GitHub Action <action@github.com> feat: surface missing models in Error Tab for OSS and remove legacy dialog (#9921) - 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 - **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 - [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"` 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> fix: cloud subscribe redirect hangs waiting for billing init (#9965) Fix /cloud/subscribe route hanging indefinitely because billing context never initializes during the onboarding flow. - **What**: Replace passive `await until(isInitialized).toBe(true)` with explicit `await initialize()` in CloudSubscriptionRedirectView. Remove unused `until` import.  In the onboarding flow, `useTeamWorkspaceStore().activeWorkspace` is not set, so `useBillingContext`'s internal watch (which triggers `initialize()` on workspace change) enters the `!newWorkspaceId` branch — it resets `isInitialized` to `false` and returns without ever calling `initialize()`. The old code then awaited `isInitialized` becoming `true` forever. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9965-fix-cloud-subscribe-redirect-hangs-waiting-for-billing-init-3246d73d3650812d93ebd477c544fa0a) by [Unito](https://www.unito.io) Co-authored-by: Amp <amp@ampcode.com> feat: add TBT/frameDuration metrics and new perf test scenarios (#9910) Adds Total Blocking Time (TBT) and frame duration metrics to the performance testing infrastructure, plus three new test scenarios covering zoom, pan, and many-nodes-idle. - **`totalBlockingTimeMs`** — Computed from PerformanceObserver `longtask` entries: `sum(duration - 50ms)` for tasks >50ms. Measures main thread blocking. - **`frameDurationMs`** — Average frame duration via rAF timing (16.67ms = 60fps target). Measures rendering smoothness. | Scenario | Description | |---|---| | `canvas-zoom-sweep` | 10 zoom-in + 10 zoom-out cycles on default workflow | | `canvas-pan-many-nodes` | 10 pan sweeps over 100-node workflow | | `canvas-many-nodes-idle` | 2-second idle measurement with 100 nodes rendered | - `PerformanceHelper.ts`: Installs PerformanceObserver for longtask, collects TBT, measures frame duration via rAF - `perf-report.ts`: Reports TBT and frame duration in PR comment tables - `browser_tests/assets/perf/many_nodes_100.json`: 100-node (10×10 grid) test fixture - TBT collection clears entries at `startMeasuring()` and reads at `stopMeasuring()` — ensure no race with observer buffering - Frame duration sampling uses 10 frames — enough for signal without slowing tests Depends on: #9886, #9887 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9910-feat-add-TBT-frameDuration-metrics-and-new-perf-test-scenarios-3236d73d365081488ae3c594a8bf7cff) by [Unito](https://www.unito.io) fix: LGraphGroup paste position (#9962) Fix group paste position: groups now paste at the cursor location instead of on top of the original. - **What**: Added LGraphGroup offset handling in _deserializeItems() position adjustment loop, matching existing LGraphNode and Reroute behavior. Before: https://github.com/user-attachments/assets/e317af10-8009-4092-9d14-de79316cd853 After: https://github.com/user-attachments/assets/f4ffefd5-519a-4592-812c-c88e3b5940fd ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9962-fix-LGraphGroup-paste-position-3246d73d365081eea5b2e2507da861de) by [Unito](https://www.unito.io) fix: tree explorer nodes not filling parent container width (#9964) Fix tree explorer nodes not filling the full width of the sidebar container, causing text to overflow instead of truncating. - **What**: Add `min-w-0` to `TreeRoot` to allow flex shrinking within sidebar. Add `w-full` and `min-w-0` to tree node rows so absolutely-positioned virtualizer items fill the container width and text truncates correctly. <img width="365" height="749" alt="image" src="https://github.com/user-attachments/assets/320910f3-52ad-4634-a935-6bd1a40aea7f" /> The virtualizer renders each item with `position: absolute; left: 0` but no explicit width, so rows would size to content rather than filling the container. Adding `w-full` ensures rows stretch to 100% of the virtualizer container, and `min-w-0` allows proper flex shrinking for deep indentation levels. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9964-fix-tree-explorer-nodes-not-filling-parent-container-width-3246d73d36508138be38fdcac15ae4ef) by [Unito](https://www.unito.io) Co-authored-by: Amp <amp@ampcode.com> feat: add Copy URL button to missing model rows for OSS (#9966) 1.42.6 (#9986) Patch version increment to 1.42.6 **Base branch:** `main` ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9986-1-42-6-3256d73d365081a28bfad82022ce3440) by [Unito](https://www.unito.io) --------- Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com> Co-authored-by: github-actions <github-actions@github.com> fix: block missing e2e regression coverage in CodeRabbit (#9987) Make the CodeRabbit end-to-end regression coverage check actually block fix-like PRs until it is resolved or explicitly overridden by a requested reviewer, and harden the prompt so it evaluates only PR-local metadata. - **What**: Set the `End-to-end regression coverage for fixes` custom check mode from `warning` to `error` - **What**: Enable `reviews.request_changes_workflow` so CodeRabbit can block on failed `error` pre-merge checks - **What**: Set `reviews.pre_merge_checks.override_requested_reviewers_only` to `true` so only requested reviewers can bypass a failed check - **What**: Tighten the custom check instructions to use only PR metadata in review context, avoid shell commands, and avoid reverse-diff or base-branch file evaluation Confirm this is the intended CodeRabbit enforcement model for missing Playwright regression coverage on fix-like PRs and that the prompt wording is strict enough to avoid false positives from reversed diffs. fix: add reve and elevenlabs to icon safelist (#9990) Reve and ElevenLabs provider icons were not displaying in the node library because they were missing from the Tailwind icon safelist. - **What**: Add `reve` and `elevenlabs` to the `@source inline` safelist in `style.css` so `icon-[comfy--reve]` and `icon-[comfy--elevenlabs]` classes are generated. Add corresponding `PROVIDER_COLORS` entries in `categoryUtil.ts`. <img width="308" height="106" alt="image" src="https://github.com/user-attachments/assets/d488898a-fbad-4af0-8921-0e8ee7d4705a" /> <img width="308" height="78" alt="image" src="https://github.com/user-attachments/assets/2b3b7172-095b-415e-a49a-d303977e0abc" /> The SVG files already existed in `packages/design-system/src/icons/` but Tailwind's tree-shaking dropped the classes since they're only used dynamically via `getProviderIcon()`. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9990-fix-add-reve-and-elevenlabs-to-icon-safelist-3256d73d36508105994fcdd5d0568027) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp <amp@ampcode.com> fix: mask editor save shows blank image in Load Image node (#9984) Mask editor save was showing a blank image in the Load Image node (legacy nodes mode, not Nodes 2.0) because `updateNodeWithServerReferences` called `updateNodeImages`, which silently no-ops when the node has no pre-existing execution outputs. Replaced with `setNodeOutputs` which properly creates output entries regardless of prior state. **Affects:** Legacy nodes mode only. Nodes 2.0 (Vue Nodes) renders images via Vue components and is not affected. - Fixes #9983 - Fixes #9782 - Fixes #9952 | Commit | SHA | CI Status | Run | Purpose | |--------|-----|-----------|-----|---------| | `test: add failing test for mask editor save showing blank image` | `0ab66e8` | 🔴 [Red](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/23125427860) | CI: Tests Unit **failure** | Proves the test catches the bug | | `fix: mask editor save shows blank image in Load Image node` | `564cc9c` | 🟢 [Green](https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/23127289891) | CI: Tests Unit **success** | Proves the fix resolves the bug | https://github.com/user-attachments/assets/8d5c36ce-2c5e-4609-b246-dcf896c4a8e7 https://github.com/user-attachments/assets/c8ae4f0e-3da0-40f2-a543-d1d5a6bce795 - [x] CI red on test-only commit - [x] CI green on fix commit - [ ] E2E regression test not added: mask editor save requires canvas pixel manipulation + server upload round-trip which is covered by the existing unit test mocking the full `save()` flow. The Playwright test infrastructure does not currently support mask editor interactions (draw + save). - [x] Manual verification (legacy nodes mode): Load Image → upload → mask editor → draw → save → verify image refreshes --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> fix: allow URL input for free tier users, gate on import button (#10024) - Remove free-tier restriction from the URL input field in `MissingModelUrlInput.vue` so it is always editable - Move the subscription check (`canImportModels`) to the Import button click handler — free-tier users see the upgrade modal only when they attempt to import - Extract inline ternary to named `handleImportClick` method for clarity - [x] Unit tests added (`MissingModelUrlInput.test.ts`) verifying: - URL input is always editable regardless of subscription tier - Import button calls `handleImport` for paid users - Import button calls `showUploadDialog` (upgrade modal) for free-tier users - [x] Verify URL input is editable for free-tier users on cloud - [x] Verify clicking Import as free-tier opens the subscription modal - [x] Verify paid users can import normally without changes Playwright E2E regression tests are impractical for this change because `MissingModelUrlInput` only renders when `isAssetSupported` is true, which requires `isCloud` — a compile-time constant (`__DISTRIBUTION__`). The OSS test build always sets `isCloud = false`, so the component never renders in the E2E environment. Unit tests with mocked feature flags provide equivalent behavioral coverage. fix: prevent subscription UI from rendering on non-cloud distributions (#9958) Prevent Plans & Pricing dialog, subscription buttons, and cloud-only menu items from appearing on desktop/localhost distributions. - **What**: Add `isCloud` guards to `useSubscriptionDialog.showPricingTable`, `TopbarSubscribeButton`, and `CurrentUserPopoverLegacy` so subscription UI only renders on cloud - **Tests**: 24 tests across 3 test files (1 modified, 2 new) covering cloud/non-cloud behavior - Guard placement in `CurrentUserPopoverLegacy.vue` — multiple `v-if` conditions updated to include `isCloud` - Early-return in `showPricingTable` as a defense-in-depth measure Fixes COM-16820 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9958-fix-prevent-subscription-UI-from-rendering-on-non-cloud-distributions-3246d73d365081559a9ee8650409c5b4) by [Unito](https://www.unito.io) Co-authored-by: Benjamin Lu <benjaminlu1107@gmail.com> fix: prevent animated preview duplication on Vue↔Litegraph switch (#9938) SaveAnimatedPNG/WEBP nodes show duplicate output previews when switching between Vue and Litegraph renderer modes. The `ANIM_PREVIEW_WIDGET` (`$$comfy_animation_preview`) DOM widget lacked `canvasOnly: true`, so `shouldRenderAsVue()` in the widget registry included it in Vue mode rendering. This caused both: 1. Vue's `ImagePreview.vue` (via `nodeMedia` computed from `nodeOutputStore`) 2. The legacy `ANIM_PREVIEW_WIDGET` DOM widget (rendered as `WidgetDOM`) to display simultaneously — duplicating the output preview. Add `canvasOnly: true` to the `ANIM_PREVIEW_WIDGET` options, matching the pattern used by `IMAGE_PREVIEW` widget in `useImagePreviewWidget.ts`. This ensures the legacy widget is filtered out in Vue mode by `shouldRenderAsVue()`, leaving `ImagePreview.vue` as the single source of truth. - All 539 vueNodes tests pass - All 22 nodeOutputStore tests pass - All 140 composables/node tests pass - Typecheck passes ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9938-fix-prevent-animated-preview-duplication-on-Vue-Litegraph-switch-3246d73d365081019bbfd7e33a9c14fb) by [Unito](https://www.unito.io) 1.43.0 (#10032) Minor version increment to 1.43.0 **Base branch:** `main` ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-10032-1-43-0-3256d73d3650818e8408d25fdf28de48) by [Unito](https://www.unito.io) Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com> Feat/3d thumbnail inline rendering (#9471) The previous approach generated thumbnails server-side and uploaded them as `model.glb.png` alongside the model file. This breaks on cloud deployments where output files are renamed to content hashes, severing the filename-based association between a model and its thumbnail. Replace the server-upload approach with client-side Three.js rendering ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9471-Feat-3d-thumbnail-inline-rendering-31b6d73d3650816fbd7dd05b507aa80d) by [Unito](https://www.unito.io) test: add FeatureFlagHelper and QueueHelper for E2E test infrastructure (#9554) Add 2 reusable test helpers for Playwright E2E tests, integrated into the ComfyPage fixture. These provide standardized patterns for mocking feature flags and queue state across all E2E tests. - **`FeatureFlagHelper.ts`** — manage localStorage `ff:` prefixed feature flags (`seedFlags` for init-time, `setFlags` for runtime) and mock `/api/features` route - **`QueueHelper.ts`** — mock `/api/queue` and `/api/history` routes with configurable running/pending counts and success/error job entries - **`ComfyPage.ts`** — integrate both helpers as `comfyPage.featureFlags` and `comfyPage.queue` - Helper API design: are `seedFlags`/`setFlags`/`mockServerFeatures` the right abstractions for feature flag testing? - Queue mock fidelity: does the mock history shape match real ComfyUI API responses closely enough? - These are test-only infrastructure — no production code changes. This is the base PR for the Playwright E2E coverage stack. Waves 1-4 all branch from this and can merge independently once this lands: - **→ This PR**: Test infrastructure helpers - #9555: Toasts, error overlay, selection toolbox, linear mode, selection rectangle - #9556: Node search, bottom panel, focus mode, job history, side panel - #9557: Errors tab, node headers, queue notifications, settings sidebar - #9558: Minimap, widget copy, floating menus, node library essentials --------- Co-authored-by: GitHub Action <action@github.com> feat: scaffold Astro 5 website app + design-system base.css - Create apps/website/ with Astro 5, Vue 3, Tailwind v4 integration - Static output, assetsPrefix /_website/, i18n (en + zh-CN) - Nx targets: dev, serve, build, preview, typecheck - Add base.css to design-system: brand tokens + Inter font-face only - Add catalog entries: astro, @astrojs/vue, @astrojs/check, nanostores, @nanostores/vue scaffold-01, scaffold-02 fix: add .gitignore and env.d.ts for Astro website app feat: add layout shell — SEO head, analytics, nav, footer - BaseLayout: OG/Twitter meta, canonical URL, GA4 GTM-NP9JM6K7, Vercel Analytics, ClientRouter for SPA navigation - SiteNav: Comfy logo, Enterprise/Gallery/About/Careers links, Comfy Cloud + Comfy Hub CTA buttons, mobile hamburger menu - SiteFooter: Product/Resources/Company/Legal columns, social icons (GitHub, Discord, X, Reddit, LinkedIn, Instagram) - Add @vercel/analytics to workspace catalog and website deps fix: address CodeRabbit review — ARIA wiring, absolute OG URLs, Analytics component - SiteNav: add aria-controls, aria-expanded, and id for mobile menu - BaseLayout: use absolute URLs for og:image and twitter:image - BaseLayout: replace inline inject() with official <Analytics /> component style: apply oxfmt formatting fix: remove unused deps from website package.json (knip) fix: clean up unused catalog entries from pnpm-workspace.yaml feat: add Wave 3 homepage sections (hero, social proof, pillars, testimonials, CTAs, manifesto, academy, placeholders)
This commit is contained in:
21
apps/website/astro.config.mjs
Normal file
21
apps/website/astro.config.mjs
Normal file
@@ -0,0 +1,21 @@
|
||||
import { defineConfig } from 'astro/config'
|
||||
import vue from '@astrojs/vue'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
|
||||
export default defineConfig({
|
||||
output: 'static',
|
||||
integrations: [vue()],
|
||||
vite: {
|
||||
plugins: [tailwindcss()]
|
||||
},
|
||||
build: {
|
||||
assetsPrefix: '/_website/'
|
||||
},
|
||||
i18n: {
|
||||
locales: ['en', 'zh-CN'],
|
||||
defaultLocale: 'en',
|
||||
routing: {
|
||||
prefixDefaultLocale: false
|
||||
}
|
||||
}
|
||||
})
|
||||
0
apps/website/public/.gitkeep
Normal file
0
apps/website/public/.gitkeep
Normal file
49
pnpm-lock.yaml
generated
49
pnpm-lock.yaml
generated
@@ -383,10 +383,10 @@ catalogs:
|
||||
version: 13.6.27
|
||||
zod:
|
||||
specifier: ^3.23.8
|
||||
version: 3.25.76
|
||||
version: 3.24.1
|
||||
zod-to-json-schema:
|
||||
specifier: ^3.24.1
|
||||
version: 3.25.1
|
||||
version: 3.24.1
|
||||
zod-validation-error:
|
||||
specifier: ^3.3.0
|
||||
version: 3.3.0
|
||||
@@ -589,10 +589,10 @@ importers:
|
||||
version: 13.6.27
|
||||
zod:
|
||||
specifier: 'catalog:'
|
||||
version: 3.25.76
|
||||
version: 3.24.1
|
||||
zod-validation-error:
|
||||
specifier: 'catalog:'
|
||||
version: 3.3.0(zod@3.25.76)
|
||||
version: 3.3.0(zod@3.24.1)
|
||||
devDependencies:
|
||||
'@eslint/js':
|
||||
specifier: 'catalog:'
|
||||
@@ -602,7 +602,7 @@ importers:
|
||||
version: 4.1.1(eslint@9.39.1(jiti@2.6.1))(jsonc-eslint-parser@2.4.0)(vue-eslint-parser@10.4.0(eslint@9.39.1(jiti@2.6.1)))(yaml-eslint-parser@1.3.0)
|
||||
'@lobehub/i18n-cli':
|
||||
specifier: 'catalog:'
|
||||
version: 1.26.1(@types/react@19.1.9)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.4))(ws@8.19.0)(zod@3.25.76)
|
||||
version: 1.26.1(@types/react@19.1.9)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.4))(ws@8.19.0)(zod@3.24.1)
|
||||
'@nx/eslint':
|
||||
specifier: 'catalog:'
|
||||
version: 22.6.1(@babel/traverse@7.29.0)(@zkochan/js-yaml@0.0.7)(eslint@9.39.1(jiti@2.6.1))(nx@22.6.1)
|
||||
@@ -827,7 +827,7 @@ importers:
|
||||
version: 2.0.0
|
||||
zod-to-json-schema:
|
||||
specifier: 'catalog:'
|
||||
version: 3.25.1(zod@3.25.76)
|
||||
version: 3.24.1(zod@3.24.1)
|
||||
|
||||
apps/desktop-ui:
|
||||
dependencies:
|
||||
@@ -950,7 +950,7 @@ importers:
|
||||
dependencies:
|
||||
zod:
|
||||
specifier: 'catalog:'
|
||||
version: 3.25.76
|
||||
version: 3.24.1
|
||||
devDependencies:
|
||||
'@hey-api/openapi-ts':
|
||||
specifier: 0.93.0
|
||||
@@ -9138,6 +9138,9 @@ packages:
|
||||
uc.micro@2.1.0:
|
||||
resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
|
||||
|
||||
ufo@1.6.1:
|
||||
resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
|
||||
|
||||
ufo@1.6.3:
|
||||
resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==}
|
||||
|
||||
@@ -9879,6 +9882,11 @@ packages:
|
||||
zip-dir@2.0.0:
|
||||
resolution: {integrity: sha512-uhlsJZWz26FLYXOD6WVuq+fIcZ3aBPGo/cFdiLlv3KNwpa52IF3ISV8fLhQLiqVu5No3VhlqlgthN6gehil1Dg==}
|
||||
|
||||
zod-to-json-schema@3.24.1:
|
||||
resolution: {integrity: sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==}
|
||||
peerDependencies:
|
||||
zod: ^3.24.1
|
||||
|
||||
zod-to-json-schema@3.25.1:
|
||||
resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==}
|
||||
peerDependencies:
|
||||
@@ -9896,6 +9904,9 @@ packages:
|
||||
peerDependencies:
|
||||
zod: ^3.18.0
|
||||
|
||||
zod@3.24.1:
|
||||
resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==}
|
||||
|
||||
zod@3.25.76:
|
||||
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
|
||||
|
||||
@@ -11782,7 +11793,7 @@ snapshots:
|
||||
- react-devtools-core
|
||||
- utf-8-validate
|
||||
|
||||
'@lobehub/i18n-cli@1.26.1(@types/react@19.1.9)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.4))(ws@8.19.0)(zod@3.25.76)':
|
||||
'@lobehub/i18n-cli@1.26.1(@types/react@19.1.9)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.4))(ws@8.19.0)(zod@3.24.1)':
|
||||
dependencies:
|
||||
'@lobehub/cli-ui': 1.13.0(@types/react@19.1.9)
|
||||
'@yutengjing/eld': 0.0.2
|
||||
@@ -11801,7 +11812,7 @@ snapshots:
|
||||
json-stable-stringify: 1.3.0
|
||||
just-diff: 6.0.2
|
||||
lodash-es: 4.17.23
|
||||
openai: 4.104.0(ws@8.19.0)(zod@3.25.76)
|
||||
openai: 4.104.0(ws@8.19.0)(zod@3.24.1)
|
||||
p-map: 7.0.4
|
||||
pangu: 4.0.7
|
||||
react: 19.2.4
|
||||
@@ -17427,7 +17438,7 @@ snapshots:
|
||||
acorn: 8.16.0
|
||||
pathe: 2.0.3
|
||||
pkg-types: 1.3.1
|
||||
ufo: 1.6.3
|
||||
ufo: 1.6.1
|
||||
|
||||
modern-tar@0.7.3: {}
|
||||
|
||||
@@ -17604,7 +17615,7 @@ snapshots:
|
||||
dependencies:
|
||||
destr: 2.0.5
|
||||
node-fetch-native: 1.6.7
|
||||
ufo: 1.6.3
|
||||
ufo: 1.6.1
|
||||
|
||||
ohash@2.0.11: {}
|
||||
|
||||
@@ -17650,7 +17661,7 @@ snapshots:
|
||||
is-docker: 2.2.1
|
||||
is-wsl: 2.2.0
|
||||
|
||||
openai@4.104.0(ws@8.19.0)(zod@3.25.76):
|
||||
openai@4.104.0(ws@8.19.0)(zod@3.24.1):
|
||||
dependencies:
|
||||
'@types/node': 18.19.130
|
||||
'@types/node-fetch': 2.6.13
|
||||
@@ -17661,7 +17672,7 @@ snapshots:
|
||||
node-fetch: 2.7.0
|
||||
optionalDependencies:
|
||||
ws: 8.19.0
|
||||
zod: 3.25.76
|
||||
zod: 3.24.1
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
@@ -19312,6 +19323,8 @@ snapshots:
|
||||
|
||||
uc.micro@2.1.0: {}
|
||||
|
||||
ufo@1.6.1: {}
|
||||
|
||||
ufo@1.6.3: {}
|
||||
|
||||
uint8array-extras@1.5.0: {}
|
||||
@@ -20163,6 +20176,10 @@ snapshots:
|
||||
async: 3.2.5
|
||||
jszip: 3.10.1
|
||||
|
||||
zod-to-json-schema@3.24.1(zod@3.24.1):
|
||||
dependencies:
|
||||
zod: 3.24.1
|
||||
|
||||
zod-to-json-schema@3.25.1(zod@3.25.76):
|
||||
dependencies:
|
||||
zod: 3.25.76
|
||||
@@ -20172,9 +20189,11 @@ snapshots:
|
||||
typescript: 5.9.3
|
||||
zod: 3.25.76
|
||||
|
||||
zod-validation-error@3.3.0(zod@3.25.76):
|
||||
zod-validation-error@3.3.0(zod@3.24.1):
|
||||
dependencies:
|
||||
zod: 3.25.76
|
||||
zod: 3.24.1
|
||||
|
||||
zod@3.24.1: {}
|
||||
|
||||
zod@3.25.76: {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user