Skip to content

Conversation

@christian-byrne
Copy link
Contributor

@christian-byrne christian-byrne commented Dec 3, 2025

Renames the shared subscription state export to keep the descriptive name isSubscribedOrIsNotCloud. Previously it was just isSubscribed which led to some misunderstandings and could lie

In some call sites, short-circuit on isCloud earlier, to avoid initializing a cloud-specific module (which can have non-breaking but inadvertant side-effects like network requests) on local. We want that all to be tree-shaken on local

┆Issue is synchronized with this Notion page by Unito

@christian-byrne christian-byrne requested review from a team and pythongosssss as code owners December 3, 2025 06:57
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Dec 3, 2025
@github-actions
Copy link

github-actions bot commented Dec 3, 2025

🎨 Storybook Build Status

Build completed successfully!

⏰ Completed at: 12/06/2025, 11:39:35 PM UTC

🔗 Links


🎉 Your Storybook is ready for review!

@github-actions
Copy link

github-actions bot commented Dec 3, 2025

🎭 Playwright Test Results

⚠️ Tests passed with flaky tests

⏰ Completed at: 12/06/2025, 11:49:20 PM UTC

📈 Summary

  • Total Tests: 496
  • Passed: 483 ✅
  • Failed: 0
  • Flaky: 3 ⚠️
  • Skipped: 10 ⏭️

📊 Test Reports by Browser

  • chromium: View Report • ✅ 474 / ❌ 0 / ⚠️ 3 / ⏭️ 10
  • chromium-2x: View Report • ✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0
  • chromium-0.5x: View Report • ✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0
  • mobile-chrome: View Report • ✅ 6 / ❌ 0 / ⚠️ 0 / ⏭️ 0

🎉 Click on the links above to view detailed test results for each browser configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 3, 2025

📝 Walkthrough

Walkthrough

Renamed subscription flag isActiveSubscriptionisSubscriptionRequirementMet and made subscription checks cloud-aware: non-cloud builds bypass gating while cloud builds lazily obtain useSubscription and enforce isSubscriptionRequirementMet for purchases, dialogs, commands, and UI rendering.

Changes

Cohort / File(s) Change Summary
Subscription Composables
src/platform/cloud/subscription/composables/useSubscription.ts, src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
Public/computed flag and watcher option renamed from isActiveSubscriptionisSubscriptionRequirementMet; introduced isSubscriptionCheckRequired; watcher wiring and require flows updated; useSubscription now returns isSubscriptionRequirementMet (replacing the old property).
Subscription UI Components
src/platform/cloud/subscription/components/SubscribeButton.vue, src/platform/cloud/subscription/components/SubscriptionPanel.vue
Destructuring, template conditions, polling completion, and emitted events updated to reference isSubscriptionRequirementMet instead of isActiveSubscription.
Topbar & Credits UI
src/components/topbar/CurrentUserPopover.vue, src/components/dialog/content/setting/CreditsPanel.vue
useSubscription() invoked only when isCloud; templates and computed bindings replaced isActiveSubscription with a derived isSubscriptionRequirementMet (with fallbacks when subscription is unavailable).
Actionbar Run Button
src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
Button selection logic and template key updated to use isSubscriptionRequirementMet to choose between queue and subscribe actions.
Core Commands & Auth Paths
src/composables/useCoreCommands.ts, src/composables/auth/useFirebaseAuthActions.ts
Introduced cloud-aware gating: when isCloud, dynamically import/use useSubscription() and check isSubscriptionRequirementMet before executing gated commands or purchase flows; non-cloud paths use defaults/noops.
App & Dialog Service
src/scripts/app.ts, src/services/dialogService.ts
Payment-required handling and top-up dialog now branch on isCloud and use isSubscriptionRequirementMet in cloud builds; showTopUpCreditsDialog made async and lazily imports useSubscription in cloud.
Subscription Actions
src/platform/cloud/subscription/composables/useSubscriptionActions.ts
handleAddApiCredits made async and now awaits dialogService.showTopUpCreditsDialog (signature changed to return Promise).
Cloud Remote Config
src/extensions/core/cloudRemoteConfig.ts
Readiness/watch dependency switched from isActiveSubscription to isSubscriptionRequirementMet.
Tests & Mocks
src/components/topbar/CurrentUserPopover.test.ts, tests-ui/tests/composables/useCoreCommands.test.ts, tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts, tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts, tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
Tests and mocks updated to use isSubscriptionRequirementMet (often mocked as { value: ... }); assertions and mock shapes adjusted accordingly.
Misc / Manifest
manifest_file, package.json, other touched tests/scripts
Supporting changes and test updates to align with renaming and async dialog behavior.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant UI as "UI Component\n(CreditsPanel / Run Button)"
  participant Sub as "useSubscription\n(composable)"
  participant Dialog as "dialogService"
  participant Cmd as "Core Command\n/ Queue"

  User->>UI: trigger purchase/run action
  UI->>UI: check isCloud
  alt isCloud == true
    UI->>Sub: dynamic import & get isSubscriptionRequirementMet
    Sub-->>UI: isSubscriptionRequirementMet (computed)
    alt isSubscriptionRequirementMet == true
      UI->>Dialog: call showTopUpCreditsDialog()
      Dialog-->>UI: dialog completes
      UI->>Cmd: proceed with action (queue/run)
      Cmd-->>UI: result
    else isSubscriptionRequirementMet == false
      UI-->>User: show subscription/subscribe dialog
    end
  else isCloud == false
    UI->>Dialog: call showTopUpCreditsDialog() (no subscription gating)
    Dialog-->>UI: dialog completes
    UI->>Cmd: proceed with action (queue/run)
    Cmd-->>UI: result
  end
Loading
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/top-up-local

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1ebdab9 and 8ce0c9e.

📒 Files selected for processing (1)
  • src/platform/cloud/subscription/composables/useSubscription.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/platform/cloud/subscription/composables/useSubscription.ts
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript exclusively; no new JavaScript code

Files:

  • src/platform/cloud/subscription/composables/useSubscription.ts
**/*.{ts,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,vue}: Use camelCase for variable and function names
Indent with 2 spaces (see .prettierrc)
Use single quotes for strings (see .prettierrc)
No trailing semicolons (see .prettierrc)
Maximum line width of 80 characters (see .prettierrc)
Sort and group imports by plugin (run pnpm format before committing)
Never use any type; use proper TypeScript types instead
Never use as any type assertions; fix the underlying type issue instead
Avoid code comments unless absolutely necessary; write expressive, self-documenting code instead
When writing new code, ask if there is a simpler way to introduce the same functionality; if yes, choose the simpler approach
Use refactoring to make complex code simpler
Use es-toolkit for utility functions
Use Vite for fast development and building
Implement proper error handling
Write tests for all changes, especially bug fixes to catch future regressions

Files:

  • src/platform/cloud/subscription/composables/useSubscription.ts
**/composables/**/use*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables with useXyz.ts pattern

Files:

  • src/platform/cloud/subscription/composables/useSubscription.ts
🧠 Learnings (1)
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks

Applied to files:

  • src/platform/cloud/subscription/composables/useSubscription.ts
🧬 Code graph analysis (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (1)
  • useSubscriptionCancellationWatcher (21-129)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: setup
  • GitHub Check: test
🔇 Additional comments (3)
src/platform/cloud/subscription/composables/useSubscription.ts (3)

112-123: Good: cancellation watcher and gating now respect “check required” flag

shouldWatchCancellation now defers to isSubscriptionCheckRequired.value, and requireActiveSubscription early‑returns when the check isn’t required. This:

  • Avoids kicking off cloud cancellation polling when subscription checks are disabled.
  • Prevents unnecessary fetchSubscriptionStatus() calls and dialog openings in non‑cloud or non‑required setups, directly supporting the PR goal of avoiding cloud side‑effects locally.
  • Still ensures cloud builds with subscription_required enabled fetch status and surface the dialog when isSubscriptionRequirementMet is false.

This wiring looks correct and consistent with useSubscriptionCancellationWatcher’s contract.

Also applies to: 129-137


230-247: Public API rename to isSubscriptionRequirementMet is coherent with behavior

Exporting isSubscriptionRequirementMet instead of the previous “isSubscribed*” naming better reflects the actual semantics: it’s true either when subscription checks are not required or when there is an active subscription. That matches how calling sites conceptually gate features (“is the requirement satisfied?”) without having to know about cloud/local config.

Just ensure all dependents have been updated to the new name and understand that “true” now also explicitly covers “no subscription required” scenarios (which seems to be the intent of the PR description and tests).


34-42: Remove the suggested window guard—this is a browser-only SPA

The isSubscriptionCheckRequired and isSubscriptionRequirementMet pairing cleanly encodes the gating logic and aligns with the PR intent to skip subscription checks when not required. The implementation is sound.

The original suggestion to add a typeof window === 'undefined' guard is unnecessary. This codebase is a browser-only SPA (confirmed by vite.config.mts with no SSR setup), and src/main.ts explicitly documents that window.__CONFIG__ is guaranteed to be available during initialization across all cloud builds. Additionally, the same pattern of direct window.__CONFIG__ access without defensive checks already exists in src/platform/settings/composables/useSettingUI.ts in the same directory.

Likely an incorrect or invalid review comment.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/composables/useCoreCommands.ts (1)

66-67: Consider gating useSubscription() to avoid initializing cloud logic on local builds

The new guards using isSubscribedOrIsNotCloud.value and showSubscriptionDialog() look correct and preserve the prior behavior with the renamed flag.

To better match the PR objective of not initializing cloud modules on local, you could avoid calling useSubscription() at module scope and instead gate it, for example:

export function useCoreCommands(): ComfyCommand[] {
  // ...
  const subscription =
    isCloud /* from '@/platform/distribution/types' */ ? useSubscription() : null
  const isSubscribedOrIsNotCloud = subscription?.isSubscribedOrIsNotCloud
  const showSubscriptionDialog = subscription?.showSubscriptionDialog
  // use these in the queue commands, with a null check if needed
}

This would prevent the subscription composable (and its network activity) from being set up when running non‑cloud builds, while keeping the command guards unchanged for cloud.

Also applies to: 468-488, 491-512, 514-557

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6827413 and 79ddb75.

📒 Files selected for processing (16)
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue (2 hunks)
  • src/components/dialog/content/setting/CreditsPanel.vue (3 hunks)
  • src/components/topbar/CurrentUserPopover.test.ts (1 hunks)
  • src/components/topbar/CurrentUserPopover.vue (3 hunks)
  • src/composables/auth/useFirebaseAuthActions.ts (1 hunks)
  • src/composables/useCoreCommands.ts (4 hunks)
  • src/platform/cloud/subscription/components/SubscribeButton.vue (2 hunks)
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue (5 hunks)
  • src/platform/cloud/subscription/composables/useSubscription.ts (2 hunks)
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (2 hunks)
  • src/scripts/app.ts (1 hunks)
  • src/services/dialogService.ts (1 hunks)
  • tests-ui/tests/composables/useCoreCommands.test.ts (1 hunks)
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (3 hunks)
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (3 hunks)
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (23)
**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{vue,ts,tsx}: Leverage VueUse functions for performance-enhancing utilities
Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.json

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • src/services/dialogService.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/components/topbar/CurrentUserPopover.vue
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Use es-toolkit for utility functions

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • src/services/dialogService.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

Use TypeScript for type safety

**/*.{ts,tsx}: Never use any type - use proper TypeScript types
Never use as any type assertions - fix the underlying type issue

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • src/services/dialogService.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
**/*.{ts,tsx,js,vue}

📄 CodeRabbit inference engine (.cursorrules)

Implement proper error handling in components and services

**/*.{ts,tsx,js,vue}: Use 2-space indentation, single quotes, no semicolons, and maintain 80-character line width as configured in .prettierrc
Organize imports by sorting and grouping by plugin, and run pnpm format before committing

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • src/services/dialogService.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/components/topbar/CurrentUserPopover.vue
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use camelCase for variable and setting names in TypeScript/Vue files

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • src/services/dialogService.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/components/topbar/CurrentUserPopover.vue
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,vue}: Use const settingStore = useSettingStore() and settingStore.get('Comfy.SomeSetting') to retrieve settings in TypeScript/Vue files
Use await settingStore.set('Comfy.SomeSetting', newValue) to update settings in TypeScript/Vue files
Check server capabilities using api.serverSupportsFeature('feature_name') before using enhanced features
Use api.getServerFeature('config_name', defaultValue) to retrieve server feature configuration

Enforce ESLint rules for Vue + TypeScript including: no floating promises, no unused imports, and i18n raw text restrictions in templates

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • src/services/dialogService.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/components/topbar/CurrentUserPopover.vue
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Define dynamic setting defaults using runtime context with functions in settings configuration
Use defaultsByInstallVersion property for gradual feature rollout based on version in settings configuration

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • src/services/dialogService.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
tests-ui/**/*.test.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (tests-ui/CLAUDE.md)

tests-ui/**/*.test.{js,ts,jsx,tsx}: Write tests for new features
Follow existing test patterns in the codebase
Use existing test utilities rather than writing custom utilities
Mock external dependencies in tests
Always prefer vitest mock functions over writing verbose manual mocks

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
**/*.{test,spec}.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Unit and component tests should be located in tests-ui/ or co-located with components as src/components/**/*.{test,spec}.ts; E2E tests should be in browser_tests/

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
**/*.vue

📄 CodeRabbit inference engine (.cursorrules)

**/*.vue: Use setup() function for component logic in Vue 3 Composition API
Utilize ref and reactive for reactive state in Vue 3
Implement computed properties with computed() function
Use watch and watchEffect for side effects in Vue 3
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection in Vue 3
Use Vue 3.5 style of default prop declaration with defineProps()
Organize Vue components in <script> <style> order
Use Tailwind CSS for styling Vue components
Implement responsive design with Tailwind CSS
Do not use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage). Use replacements: Select, Popover, DatePicker, ToggleSwitch, Drawer, AutoComplete, Tabs, Stepper, Message respectively
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components in Vue 3
Follow Vue 3 style guide and naming conventions
Never use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage)

Never use :class="[]" to merge class names - always use import { cn } from '@/utils/tailwindUtil' for class merging in Vue templates

**/*.vue: Use TypeScript with Vue 3 Single File Components (.vue files)
Name Vue components in PascalCase (e.g., MenuHamburger.vue)

Files:

  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/services/dialogService.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
**/*.{vue,html}

📄 CodeRabbit inference engine (CLAUDE.md)

Never use dark: or dark-theme: Tailwind variants - instead use semantic values from style.css theme, e.g. bg-node-component-surface

Files:

  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/services/dialogService.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/services/dialogService.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
  • src/services/dialogService.ts
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/services/dialogService.ts
**/composables/use*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables in the format useXyz.ts

Files:

  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
src/components/**/*.{vue,ts,js}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.vue
src/components/**/*.vue

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue components

Files:

  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.vue
src/components/**/*.{vue,css}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package

Files:

  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.vue
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/components/topbar/CurrentUserPopover.vue
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch

Applied to files:

  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Write tests for new features

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Mock external dependencies in tests

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Always prefer vitest mock functions over writing verbose manual mocks

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue OverlayPanel component with Popover

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Prefer emit/event-name for state changes over other communication patterns

Applied to files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
🧬 Code graph analysis (6)
src/composables/useCoreCommands.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (2)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • CloudSubscriptionStatusResponse (23-28)
src/platform/telemetry/types.ts (1)
  • TelemetryProvider (259-328)
src/composables/auth/useFirebaseAuthActions.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/scripts/app.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/services/dialogService.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
🪛 ESLint
src/components/dialog/content/setting/CreditsPanel.vue

[error] 128-128: Unable to resolve path to module '@/platform/distribution/types'.

(import-x/no-unresolved)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: setup
  • GitHub Check: test
  • GitHub Check: collect
  • GitHub Check: lint-and-format
🔇 Additional comments (19)
src/components/topbar/CurrentUserPopover.test.ts (1)

82-88: Subscription mock rename and shape look correct

Mocking isSubscribedOrIsNotCloud as { value: true } matches the composable’s ref-like API and aligns this test with the new subscription flag.

src/services/dialogService.ts (1)

380-399: Cloud‑gated top‑up dialog matches new subscription flag

The new isCloud guard plus isSubscribedOrIsNotCloud check correctly prevents the top‑up dialog (and useSubscription() usage) on local builds and when cloud users aren’t eligible.

tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts (1)

27-28: Watcher tests correctly updated to isSubscribedOrIsNotCloud

Using a computed based on isActive and passing isSubscribedOrIsNotCloud into the watcher keeps the tests aligned with the new API and preserves the intended behavior.

Also applies to: 77-83, 107-113, 129-135, 155-160

src/composables/auth/useFirebaseAuthActions.ts (1)

84-89: Cloud‑only subscription check in purchaseCredits is consistent

Wrapping the useSubscription() access in an isCloud check and switching to isSubscribedOrIsNotCloud.value cleanly aligns this flow with the new flag while avoiding cloud subscription setup on local runs.

src/components/dialog/content/setting/CreditsPanel.vue (1)

18-23: Credits top‑up button now correctly respects new subscription flag

The isSubscribedOrIsNotCloud computed cleanly gates the purchase button for cloud users while avoiding useSubscription() calls on local builds; the template condition matches the new flag.

Also applies to: 128-152

src/platform/cloud/subscription/composables/useSubscription.ts (1)

34-38: Renamed subscription flag is consistently wired through the composable

isSubscribedOrIsNotCloud is correctly computed, passed into useSubscriptionCancellationWatcher, and exposed on the returned API, keeping behavior intact while giving downstream callers a clearer predicate.

Also applies to: 111-118, 224-241

src/scripts/app.ts (1)

679-690: Logic correctly short-circuits to avoid cloud module initialization in non-cloud builds.

The branching ensures useSubscription() is only called when isCloud is true, aligning with the PR's goal to prevent cloud-specific module initialization in local environments. The redundancy with showTopUpCreditsDialog's internal check is intentional defensive layering.

tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (1)

95-127: Test updates correctly reflect the API rename.

The test cases properly validate that isSubscribedOrIsNotCloud behaves as expected: true when the subscription is active, false when inactive. The mocked isCloud: true context at line 56 ensures these tests run in the cloud environment where this distinction matters.

tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (2)

9-17: Mock data correctly updated to use the renamed property.

The mock structure aligns with the updated useSubscription API, ensuring tests accurately simulate both subscribed and non-subscribed states via isSubscribedOrIsNotCloud.


121-151: Test cases properly exercise both subscription states.

Each test correctly mutates mockSubscriptionData.isSubscribedOrIsNotCloud before mounting to validate the expected UI behavior for active, inactive, and cancelled subscription scenarios.

src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue (1)

4-17: Component correctly updated to use the renamed subscription predicate.

The template key, destructuring, and computed logic all consistently reference isSubscribedOrIsNotCloud, maintaining the intended behavior: render ComfyQueueButton when the user is subscribed or not in cloud mode, otherwise render SubscribeToRunButton.

src/platform/cloud/subscription/components/SubscribeButton.vue (2)

54-54: Destructuring updated to use the renamed property.


79-83: Polling logic correctly uses the renamed predicate.

When the subscription checkout completes successfully, isSubscribedOrIsNotCloud.value becomes true in cloud mode, stopping the poll and emitting the subscribed event. The logic is semantically unchanged.

src/components/topbar/CurrentUserPopover.vue (2)

26-59: LGTM! Clear and consistent rename.

The rename from isActiveSubscription to isSubscribedOrIsNotCloud significantly improves code clarity by explicitly conveying that the UI shows credits/top-up functionality either when the user is subscribed OR when running locally (not in cloud mode). The conditional logic for toggling between the credits UI and the subscribe button is now more self-documenting.


128-128: Consistent destructuring update.

The script section correctly reflects the renamed property, maintaining consistency between the template and script logic.

src/platform/cloud/subscription/components/SubscriptionPanel.vue (2)

7-72: LGTM! Comprehensive and consistent rename across subscription UI.

The rename improves clarity across multiple conditional blocks that control the subscription panel's UI state. The new name isSubscribedOrIsNotCloud makes it explicit that subscription features are available both for cloud subscribers and local installations.


322-330: Consistent destructuring with template usage.

The script correctly destructures isSubscribedOrIsNotCloud from useSubscription(), maintaining perfect alignment with all template conditional checks throughout the component.

src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (2)

13-27: LGTM! Type definition and parameter consistently updated.

The rename propagates correctly through the type definition and function signature, maintaining type safety and consistency with the calling code.


69-101: Proper cancellation detection logic with correct cleanup.

The conditional check at line 76 correctly uses the renamed isSubscribedOrIsNotCloud to detect when a subscription becomes inactive. The watcher properly cleans up resources via onScopeDispose (lines 121-123), preventing memory leaks as emphasized in the project learnings.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
tests-ui/tests/composables/useCoreCommands.test.ts (1)

101-106: Consider aligning mocked subscription flag shape with real composable

Renaming the mocked field to isSubscribedOrIsNotCloud keeps these tests in sync with the new API. If the real useSubscription now exposes this as a Ref<boolean>, you might optionally switch the mock to isSubscribedOrIsNotCloud: ref(true) to better mirror production usage and catch future .value access changes, though the current truthy function works for these tests.

src/components/topbar/CurrentUserPopover.vue (1)

128-128: Consider adding cloud-aware initialization.

While the renaming is correct, this component could benefit from the conditional initialization pattern used in CreditsPanel.vue (line 148) to prevent cloud module initialization on local environments:

const subscription = isCloud ? useSubscription() : null
const isSubscribedOrIsNotCloud = computed(() => {
  if (!isCloud) return true
  return subscription?.isSubscribedOrIsNotCloud.value ?? false
})

This would align with the PR's goal to avoid initializing cloud modules on local environments.

Apply this pattern if the component can be loaded in non-cloud environments:

+import { isCloud } from '@/platform/distribution/types'
+
 const { userDisplayName, userEmail, userPhotoUrl, handleSignOut } =
   useCurrentUser()
 const authActions = useFirebaseAuthActions()
 const dialogService = useDialogService()
-const { isSubscribedOrIsNotCloud, fetchStatus } = useSubscription()
+const subscription = isCloud ? useSubscription() : null
+const isSubscribedOrIsNotCloud = computed(() => {
+  if (!isCloud) return true
+  return subscription?.isSubscribedOrIsNotCloud.value ?? false
+})
+const fetchStatus = subscription?.fetchStatus ?? (() => Promise.resolve())
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6827413 and 79ddb75.

📒 Files selected for processing (16)
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue (2 hunks)
  • src/components/dialog/content/setting/CreditsPanel.vue (3 hunks)
  • src/components/topbar/CurrentUserPopover.test.ts (1 hunks)
  • src/components/topbar/CurrentUserPopover.vue (3 hunks)
  • src/composables/auth/useFirebaseAuthActions.ts (1 hunks)
  • src/composables/useCoreCommands.ts (4 hunks)
  • src/platform/cloud/subscription/components/SubscribeButton.vue (2 hunks)
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue (5 hunks)
  • src/platform/cloud/subscription/composables/useSubscription.ts (2 hunks)
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (2 hunks)
  • src/scripts/app.ts (1 hunks)
  • src/services/dialogService.ts (1 hunks)
  • tests-ui/tests/composables/useCoreCommands.test.ts (1 hunks)
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (3 hunks)
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (3 hunks)
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (23)
**/*.vue

📄 CodeRabbit inference engine (.cursorrules)

**/*.vue: Use setup() function for component logic in Vue 3 Composition API
Utilize ref and reactive for reactive state in Vue 3
Implement computed properties with computed() function
Use watch and watchEffect for side effects in Vue 3
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection in Vue 3
Use Vue 3.5 style of default prop declaration with defineProps()
Organize Vue components in <script> <style> order
Use Tailwind CSS for styling Vue components
Implement responsive design with Tailwind CSS
Do not use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage). Use replacements: Select, Popover, DatePicker, ToggleSwitch, Drawer, AutoComplete, Tabs, Stepper, Message respectively
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components in Vue 3
Follow Vue 3 style guide and naming conventions
Never use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage)

Never use :class="[]" to merge class names - always use import { cn } from '@/utils/tailwindUtil' for class merging in Vue templates

**/*.vue: Use TypeScript with Vue 3 Single File Components (.vue files)
Name Vue components in PascalCase (e.g., MenuHamburger.vue)

Files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{vue,ts,tsx}: Leverage VueUse functions for performance-enhancing utilities
Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.json

Files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/composables/useCoreCommands.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/services/dialogService.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/scripts/app.ts
**/*.{ts,tsx,js,vue}

📄 CodeRabbit inference engine (.cursorrules)

Implement proper error handling in components and services

**/*.{ts,tsx,js,vue}: Use 2-space indentation, single quotes, no semicolons, and maintain 80-character line width as configured in .prettierrc
Organize imports by sorting and grouping by plugin, and run pnpm format before committing

Files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/composables/useCoreCommands.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/services/dialogService.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/scripts/app.ts
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/scripts/app.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use camelCase for variable and setting names in TypeScript/Vue files

Files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/composables/useCoreCommands.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/services/dialogService.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/scripts/app.ts
**/*.{vue,html}

📄 CodeRabbit inference engine (CLAUDE.md)

Never use dark: or dark-theme: Tailwind variants - instead use semantic values from style.css theme, e.g. bg-node-component-surface

Files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,vue}: Use const settingStore = useSettingStore() and settingStore.get('Comfy.SomeSetting') to retrieve settings in TypeScript/Vue files
Use await settingStore.set('Comfy.SomeSetting', newValue) to update settings in TypeScript/Vue files
Check server capabilities using api.serverSupportsFeature('feature_name') before using enhanced features
Use api.getServerFeature('config_name', defaultValue) to retrieve server feature configuration

Enforce ESLint rules for Vue + TypeScript including: no floating promises, no unused imports, and i18n raw text restrictions in templates

Files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/composables/useCoreCommands.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/services/dialogService.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/scripts/app.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/scripts/app.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/composables/useCoreCommands.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/scripts/app.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/composables/useCoreCommands.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Use es-toolkit for utility functions

Files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/composables/useCoreCommands.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/scripts/app.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

Use TypeScript for type safety

**/*.{ts,tsx}: Never use any type - use proper TypeScript types
Never use as any type assertions - fix the underlying type issue

Files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/composables/useCoreCommands.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/scripts/app.ts
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Define dynamic setting defaults using runtime context with functions in settings configuration
Use defaultsByInstallVersion property for gradual feature rollout based on version in settings configuration

Files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/composables/useCoreCommands.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/scripts/app.ts
tests-ui/**/*.test.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (tests-ui/CLAUDE.md)

tests-ui/**/*.test.{js,ts,jsx,tsx}: Write tests for new features
Follow existing test patterns in the codebase
Use existing test utilities rather than writing custom utilities
Mock external dependencies in tests
Always prefer vitest mock functions over writing verbose manual mocks

Files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
**/*.{test,spec}.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Unit and component tests should be located in tests-ui/ or co-located with components as src/components/**/*.{test,spec}.ts; E2E tests should be in browser_tests/

Files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/scripts/app.ts
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
**/composables/use*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables in the format useXyz.ts

Files:

  • src/composables/useCoreCommands.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
src/components/**/*.vue

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue components

Files:

  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
src/components/**/*.{vue,css}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package

Files:

  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
src/components/**/*.{vue,ts,js}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings

Files:

  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks

Applied to files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/composables/useCoreCommands.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Mock external dependencies in tests

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Write tests for new features

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Follow existing test patterns in the codebase

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Always prefer vitest mock functions over writing verbose manual mocks

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue OverlayPanel component with Popover

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
🧬 Code graph analysis (6)
tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/composables/useCoreCommands.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/services/dialogService.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (2)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • CloudSubscriptionStatusResponse (23-28)
src/platform/telemetry/types.ts (1)
  • TelemetryProvider (259-328)
tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts (1)
src/extensions/core/load3d/Load3d.ts (1)
  • isActive (383-391)
src/composables/auth/useFirebaseAuthActions.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
🪛 ESLint
src/components/dialog/content/setting/CreditsPanel.vue

[error] 128-128: Unable to resolve path to module '@/platform/distribution/types'.

(import-x/no-unresolved)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: merge-reports
🔇 Additional comments (13)
src/components/topbar/CurrentUserPopover.test.ts (1)

82-88: Subscription mock rename is consistent with composable API

Mocking useSubscription with isSubscribedOrIsNotCloud: { value: true } aligns with the new flag name and expected ref-like shape; no behavior change in the tests.

src/services/dialogService.ts (1)

380-399: Cloud-only subscription guard in showTopUpCreditsDialog

The early if (isCloud) { const { isSubscribedOrIsNotCloud } = useSubscription(); if (!isSubscribedOrIsNotCloud.value) return } cleanly avoids touching the subscription composable on local builds and prevents showing the top-up dialog for unsubscribed cloud users.

Please just confirm that a silent no-op in the unsubscribed cloud case is intentional and that all callers already gate the top‑up entry points on subscription state, so users never click a button that does nothing.

src/platform/cloud/subscription/components/SubscribeButton.vue (1)

54-83: Polling now uses isSubscribedOrIsNotCloud consistently

Switching the destructured flag and the polling condition to isSubscribedOrIsNotCloud.value keeps the subscribe flow semantics intact while aligning with the new API; interval and loading-state cleanup remain correct.

src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue (1)

1-18: Run button wrapper correctly switched to isSubscribedOrIsNotCloud

The computed and template key now both depend on isSubscribedOrIsNotCloud instead of the old flag, preserving the queue/subscribe toggle behavior with the updated API.

tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (1)

8-17: Tests now track isSubscribedOrIsNotCloud for subscription state

Renaming the mock field and all subscription-state expectations to isSubscribedOrIsNotCloud keeps the active/inactive and renewal/expiry test scenarios aligned with the updated composable API, with no change to asserted behavior.

Also applies to: 121-152

tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts (1)

23-32: Cancellation watcher tests aligned with isSubscribedOrIsNotCloud

Using a local computed isSubscribedOrIsNotCloud and passing it into useSubscriptionCancellationWatcher in all test setups preserves the prior behavior while matching the new option name expected by the composable.

Also applies to: 77-83, 107-113, 129-135, 155-160

src/composables/auth/useFirebaseAuthActions.ts (1)

84-89: Cloud-only subscription guard added to purchaseCredits

The new if (isCloud) { const { isSubscribedOrIsNotCloud } = useSubscription(); if (!isSubscribedOrIsNotCloud.value) return } guard cleanly avoids initializing subscription logic on local and prevents initiating a credit purchase when the cloud user isn’t subscribed.

Please double‑check that callers never invoke purchaseCredits for unsubscribed cloud users (or, if they can, that a silent early return without feedback is the desired UX).

tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (1)

95-127: LGTM! Test updates align with API rename.

The test correctly reflects the renamed subscription state property. The test logic and assertions remain unchanged, maintaining coverage.

src/components/dialog/content/setting/CreditsPanel.vue (1)

148-152: Excellent cloud-aware initialization pattern.

This is the correct approach to prevent cloud module initialization on local environments:

  1. Conditionally call useSubscription() only when isCloud is true
  2. The computed property correctly returns true for non-cloud (no subscription required)
  3. For cloud environments, it delegates to the subscription state

This pattern should be used consistently across the codebase where subscription status is needed.

src/scripts/app.ts (1)

679-690: Cloud-aware error handling is correct.

The logic properly short-circuits for non-cloud environments before initializing the subscription module. For cloud environments, the subscription is only checked when a payment error occurs.

Note: Since useSubscription() is a shared composable (via createSharedComposable), calling it multiple times returns the same instance, making this pattern safe.

src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (1)

15-27: LGTM! Parameter renaming is consistent.

The cancellation watcher correctly receives and uses the renamed subscription state property. No logic changes, maintaining existing behavior.

Also applies to: 76-76

src/platform/cloud/subscription/components/SubscriptionPanel.vue (1)

7-11: LGTM! Consistent renaming throughout the component.

All references to the subscription state have been correctly updated to use isSubscribedOrIsNotCloud. Since this component is in the cloud-specific path, conditional initialization is not needed here.

Also applies to: 30-47, 50-72, 199-212, 323-330

src/platform/cloud/subscription/composables/useSubscription.ts (1)

34-38: LGTM! Public API renamed consistently.

The core subscription composable correctly:

  1. Computes isSubscribedOrIsNotCloud based on cloud status and subscription state
  2. Passes the renamed property to the cancellation watcher
  3. Exports the renamed property in the returned object

The logic correctly returns true for non-cloud environments, treating them as "effectively subscribed" for feature access purposes.

Also applies to: 114-114, 226-226

Copy link
Contributor

@DrJKL DrJKL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love compound logic in names like this.

Is there something more essential about the gating that we can describe without exposing what specifically goes into it right now?

Maybe subscriptionIneligible?

@github-actions
Copy link

github-actions bot commented Dec 4, 2025

Bundle Size Report

Summary

  • Raw size: 17 MB baseline 17 MB — 🔴 +721 B
  • Gzip: 3.38 MB baseline 3.38 MB — 🔴 +857 B
  • Brotli: 2.59 MB baseline 2.59 MB — 🔴 +782 B
  • Bundles: 98 current • 97 baseline • 53 added / 52 removed

Category Glance
UI Components 🔴 +9.51 kB (186 kB) · App Entry Points 🟢 -8.94 kB (3.19 MB) · Other 🔴 +60 B (3.81 MB) · Panels & Settings 🔴 +48 B (298 kB) · Graph Workspace 🔴 +38 B (976 kB) · Vendor & Third-Party ⚪ 0 B (8.56 MB) · + 3 more

Per-category breakdown
App Entry Points — 3.19 MB (baseline 3.2 MB) • 🟢 -8.94 kB

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-3HUtawmM.js (removed) 2.98 MB 🟢 -2.98 MB 🟢 -619 kB 🟢 -471 kB
assets/index-B33clhqC.js (new) 2.97 MB 🔴 +2.97 MB 🔴 +618 kB 🔴 +469 kB
assets/index-B5v5J6ae.js (removed) 223 kB 🟢 -223 kB 🟢 -47.6 kB 🟢 -39.2 kB
assets/index-BHsuCg45.js (new) 223 kB 🔴 +223 kB 🔴 +47.6 kB 🔴 +39.2 kB
assets/index-CbZ0zKSI.js (new) 360 B 🔴 +360 B 🔴 +256 B 🔴 +229 B
assets/index-Bz9h3CuX.js (removed) 345 B 🟢 -345 B 🟢 -246 B 🟢 -236 B
assets/index-J9bobPgU.js (new) 345 B 🔴 +345 B 🔴 +244 B 🔴 +233 B

Status: 4 added / 3 removed

Graph Workspace — 976 kB (baseline 976 kB) • 🔴 +38 B

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-CeL5mZkO.js (new) 976 kB 🔴 +976 kB 🔴 +189 kB 🔴 +144 kB
assets/GraphView-ClGwpGKv.js (removed) 976 kB 🟢 -976 kB 🟢 -189 kB 🟢 -144 kB

Status: 1 added / 1 removed

Views & Navigation — 6.54 kB (baseline 6.54 kB) • ⚪ 0 B

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/UserSelectView-DrHNw_5E.js (new) 6.54 kB 🔴 +6.54 kB 🔴 +2.14 kB 🔴 +1.89 kB
assets/UserSelectView-oL9BnpEJ.js (removed) 6.54 kB 🟢 -6.54 kB 🟢 -2.14 kB 🟢 -1.89 kB

Status: 1 added / 1 removed

Panels & Settings — 298 kB (baseline 298 kB) • 🔴 +48 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CreditsPanel-CmFFiHPU.js (new) 21.5 kB 🔴 +21.5 kB 🔴 +5.16 kB 🔴 +4.51 kB
assets/CreditsPanel-Bq01BWmk.js (removed) 21.4 kB 🟢 -21.4 kB 🟢 -5.15 kB 🟢 -4.49 kB
assets/KeybindingPanel-DBBAruWK.js (removed) 13.6 kB 🟢 -13.6 kB 🟢 -3.42 kB 🟢 -3.01 kB
assets/KeybindingPanel-DyOCnELU.js (new) 13.6 kB 🔴 +13.6 kB 🔴 +3.42 kB 🔴 +3.01 kB
assets/ExtensionPanel-Ft6RCmOM.js (removed) 10.8 kB 🟢 -10.8 kB 🟢 -2.58 kB 🟢 -2.26 kB
assets/ExtensionPanel-3P7kSEBl.js (new) 10.8 kB 🔴 +10.8 kB 🔴 +2.57 kB 🔴 +2.25 kB
assets/AboutPanel-CPB8Uleb.js (removed) 9.16 kB 🟢 -9.16 kB 🟢 -2.46 kB 🟢 -2.21 kB
assets/AboutPanel-CJGWnl81.js (new) 9.16 kB 🔴 +9.16 kB 🔴 +2.46 kB 🔴 +2.21 kB
assets/ServerConfigPanel-BHz7ynv2.js (removed) 6.56 kB 🟢 -6.56 kB 🟢 -1.83 kB 🟢 -1.63 kB
assets/ServerConfigPanel-Rcyx1fsS.js (new) 6.56 kB 🔴 +6.56 kB 🔴 +1.83 kB 🔴 +1.63 kB
assets/UserPanel-CQYRR1DV.js (removed) 6.23 kB 🟢 -6.23 kB 🟢 -1.72 kB 🟢 -1.5 kB
assets/UserPanel-Deumm1HR.js (new) 6.23 kB 🔴 +6.23 kB 🔴 +1.72 kB 🔴 +1.51 kB
assets/settings-BhbWhsRg.js 101 B 101 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BXTtSH4O.js 33.3 kB 33.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-C9Pzn-NG.js 25.2 kB 25.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CCy2fA_h.js 27.3 kB 27.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CQpqEFfl.js 26.6 kB 26.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DHcnxypw.js 21.7 kB 21.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DhFTK9fY.js 25.1 kB 25.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DlT4t_ui.js 25.9 kB 25.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DRgSrIdD.js 24.2 kB 24.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-tjkeqiZq.js 21.1 kB 21.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 6 added / 6 removed

UI Components — 186 kB (baseline 177 kB) • 🔴 +9.51 kB

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/LazyImage.vue_vue_type_script_setup_true_lang-S2NwFAxk.js (new) 56.4 kB 🔴 +56.4 kB 🔴 +12.5 kB 🔴 +10.9 kB
assets/Load3D.vue_vue_type_script_setup_true_lang-2tDJy6uq.js (removed) 53.9 kB 🟢 -53.9 kB 🟢 -8.52 kB 🟢 -7.32 kB
assets/Load3D.vue_vue_type_script_setup_true_lang-B5Jfts0l.js (new) 53.9 kB 🔴 +53.9 kB 🔴 +8.52 kB 🔴 +7.32 kB
assets/WidgetSelect.vue_vue_type_script_setup_true_lang-_j8O9w0k.js (new) 48 kB 🔴 +48 kB 🔴 +10.3 kB 🔴 +8.97 kB
assets/WidgetSelect.vue_vue_type_script_setup_true_lang-Dvysv2Pj.js (removed) 48 kB 🟢 -48 kB 🟢 -10.3 kB 🟢 -8.97 kB
assets/LazyImage.vue_vue_type_script_setup_true_lang-do6AjX-p.js (removed) 46.9 kB 🟢 -46.9 kB 🟢 -10.5 kB 🟢 -9.17 kB
assets/WidgetInputNumber.vue_vue_type_script_setup_true_lang-_AKQMStu.js (new) 12.9 kB 🔴 +12.9 kB 🔴 +3.37 kB 🔴 +2.97 kB
assets/WidgetInputNumber.vue_vue_type_script_setup_true_lang-DeOzU-xz.js (removed) 12.9 kB 🟢 -12.9 kB 🟢 -3.37 kB 🟢 -2.98 kB
assets/ComfyQueueButton-mYATHlCH.js (new) 8.47 kB 🔴 +8.47 kB 🔴 +2.49 kB 🔴 +2.22 kB
assets/ComfyQueueButton-D-pNlJ0-.js (removed) 8.44 kB 🟢 -8.44 kB 🟢 -2.48 kB 🟢 -2.21 kB
assets/WidgetLayoutField.vue_vue_type_script_setup_true_lang-6ZIklFyS.js (removed) 2.26 kB 🟢 -2.26 kB 🟢 -878 B 🟢 -757 B
assets/WidgetLayoutField.vue_vue_type_script_setup_true_lang-BjYu04Wi.js (new) 2.26 kB 🔴 +2.26 kB 🔴 +876 B 🔴 +763 B
assets/WidgetButton-BWYH9MQs.js (new) 2.04 kB 🔴 +2.04 kB 🔴 +931 B 🔴 +814 B
assets/WidgetButton-CFWrwaAG.js (removed) 2.04 kB 🟢 -2.04 kB 🟢 -926 B 🟢 -812 B
assets/UserAvatar.vue_vue_type_script_setup_true_lang-BPGmgVoN.js (removed) 1.34 kB 🟢 -1.34 kB 🟢 -687 B 🟢 -596 B
assets/UserAvatar.vue_vue_type_script_setup_true_lang-DJRlkgNk.js (new) 1.34 kB 🔴 +1.34 kB 🔴 +687 B 🔴 +603 B
assets/MediaTitle.vue_vue_type_script_setup_true_lang-BZ9RjVFK.js (new) 897 B 🔴 +897 B 🔴 +503 B 🔴 +430 B
assets/MediaTitle.vue_vue_type_script_setup_true_lang-RzUAxZcp.js (removed) 897 B 🟢 -897 B 🟢 -502 B 🟢 -430 B

Status: 9 added / 9 removed

Data & Services — 12.5 kB (baseline 12.5 kB) • ⚪ 0 B

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/keybindingService-LwpnoM17.js (removed) 7.51 kB 🟢 -7.51 kB 🟢 -1.83 kB 🟢 -1.58 kB
assets/keybindingService-ZIJ2kIFe.js (new) 7.51 kB 🔴 +7.51 kB 🔴 +1.83 kB 🔴 +1.58 kB
assets/serverConfigStore-L3qzi_1Z.js (removed) 2.83 kB 🟢 -2.83 kB 🟢 -909 B 🟢 -791 B
assets/serverConfigStore-mn_DuaEz.js (new) 2.83 kB 🔴 +2.83 kB 🔴 +906 B 🔴 +788 B
assets/audioService-CXZoJsfw.js (removed) 2.2 kB 🟢 -2.2 kB 🟢 -962 B 🟢 -822 B
assets/audioService-DLoyAQ4J.js (new) 2.2 kB 🔴 +2.2 kB 🔴 +962 B 🔴 +821 B

Status: 3 added / 3 removed

Utilities & Hooks — 2.94 kB (baseline 2.94 kB) • ⚪ 0 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/audioUtils-BnPRNjYg.js (new) 1.41 kB 🔴 +1.41 kB 🔴 +651 B 🔴 +546 B
assets/audioUtils-n8cHb-OP.js (removed) 1.41 kB 🟢 -1.41 kB 🟢 -649 B 🟢 -547 B
assets/mathUtil-CTARWQ-l.js 1.07 kB 1.07 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeFilterUtil-CXKCRJ-m.js 460 B 460 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 1 added / 1 removed

Vendor & Third-Party — 8.56 MB (baseline 8.56 MB) • ⚪ 0 B

External libraries and shared vendor chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/vendor-other-BZV8aGUB.js (removed) 3.98 MB 🟢 -3.98 MB 🟢 -843 kB 🟢 -673 kB
assets/vendor-other-DgsB6QUl.js (new) 3.98 MB 🔴 +3.98 MB 🔴 +843 kB 🔴 +673 kB
assets/vendor-primevue-DUTcKlCc.js (removed) 1.96 MB 🟢 -1.96 MB 🟢 -336 kB 🟢 -202 kB
assets/vendor-primevue-DwhvXzQr.js (new) 1.96 MB 🔴 +1.96 MB 🔴 +336 kB 🔴 +202 kB
assets/vendor-chart-DABxjSY-.js (new) 452 kB 🔴 +452 kB 🔴 +99.1 kB 🔴 +81 kB
assets/vendor-chart-DJFoH6N_.js (removed) 452 kB 🟢 -452 kB 🟢 -99.1 kB 🟢 -81 kB
assets/vendor-tiptap-Cmu0_BY4.js (removed) 232 kB 🟢 -232 kB 🟢 -45.7 kB 🟢 -37.7 kB
assets/vendor-tiptap-CyVxD5sH.js (new) 232 kB 🔴 +232 kB 🔴 +45.7 kB 🔴 +37.7 kB
assets/vendor-vue-Bz22sFex.js (removed) 160 kB 🟢 -160 kB 🟢 -37.3 kB 🟢 -31.6 kB
assets/vendor-vue-CT1I1z-g.js (new) 160 kB 🔴 +160 kB 🔴 +37.3 kB 🔴 +31.6 kB
assets/vendor-three-aR6ntw5X.js 1.37 MB 1.37 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-xterm-BZLod3g9.js 407 kB 407 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 5 added / 5 removed

Other — 3.81 MB (baseline 3.81 MB) • 🔴 +60 B

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/WidgetRecordAudio-BQSAOt5C.js (new) 20.4 kB 🔴 +20.4 kB 🔴 +5.24 kB 🔴 +4.63 kB
assets/WidgetRecordAudio-CMiw96lw.js (removed) 20.4 kB 🟢 -20.4 kB 🟢 -5.24 kB 🟢 -4.62 kB
assets/AudioPreviewPlayer-C8p1OoIC.js (removed) 13.5 kB 🟢 -13.5 kB 🟢 -3.4 kB 🟢 -3.05 kB
assets/AudioPreviewPlayer-CxmJNMY5.js (new) 13.5 kB 🔴 +13.5 kB 🔴 +3.4 kB 🔴 +3.04 kB
assets/WidgetGalleria-C2WgPvYa.js (removed) 4.1 kB 🟢 -4.1 kB 🟢 -1.44 kB 🟢 -1.3 kB
assets/WidgetGalleria-DX6Dx2lo.js (new) 4.1 kB 🔴 +4.1 kB 🔴 +1.45 kB 🔴 +1.3 kB
assets/WidgetColorPicker-5TqCX6DR.js (removed) 3.41 kB 🟢 -3.41 kB 🟢 -1.38 kB 🟢 -1.23 kB
assets/WidgetColorPicker-CXed-jDU.js (new) 3.41 kB 🔴 +3.41 kB 🔴 +1.38 kB 🔴 +1.23 kB
assets/WidgetMarkdown-0E1mwyWf.js (new) 3.08 kB 🔴 +3.08 kB 🔴 +1.28 kB 🔴 +1.12 kB
assets/WidgetMarkdown-Dn1_K15A.js (removed) 3.08 kB 🟢 -3.08 kB 🟢 -1.28 kB 🟢 -1.12 kB
assets/WidgetTextarea-CEmXjZ1v.js (removed) 2.93 kB 🟢 -2.93 kB 🟢 -1.17 kB 🟢 -1.05 kB
assets/WidgetTextarea-CrrMKVt5.js (new) 2.93 kB 🔴 +2.93 kB 🔴 +1.17 kB 🔴 +1.04 kB
assets/WidgetAudioUI-B231GA41.js (new) 2.88 kB 🔴 +2.88 kB 🔴 +1.18 kB 🔴 +1.06 kB
assets/WidgetAudioUI-CNRgKk_A.js (removed) 2.85 kB 🟢 -2.85 kB 🟢 -1.16 kB 🟢 -1.05 kB
assets/MediaVideoTop-CEINzZ1c.js (new) 2.76 kB 🔴 +2.76 kB 🔴 +1.05 kB 🔴 +901 B
assets/MediaVideoTop-ehTZdDBw.js (removed) 2.76 kB 🟢 -2.76 kB 🟢 -1.05 kB 🟢 -901 B
assets/WidgetChart-C_RnMGGy.js (new) 2.48 kB 🔴 +2.48 kB 🔴 +932 B 🔴 +814 B
assets/WidgetChart-j6EYUdOM.js (removed) 2.48 kB 🟢 -2.48 kB 🟢 -932 B 🟢 -819 B
assets/WidgetImageCompare-BHhMYDHR.js (new) 2.21 kB 🔴 +2.21 kB 🔴 +749 B 🔴 +664 B
assets/WidgetImageCompare-D5bj5c8l.js (removed) 2.21 kB 🟢 -2.21 kB 🟢 -748 B 🟢 -659 B
assets/WidgetInputText-CKR8w4Ts.js (new) 1.99 kB 🔴 +1.99 kB 🔴 +920 B 🔴 +850 B
assets/WidgetInputText-Kd5vegmc.js (removed) 1.99 kB 🟢 -1.99 kB 🟢 -915 B 🟢 -852 B
assets/MediaImageTop-Bc_jjvyf.js (new) 1.75 kB 🔴 +1.75 kB 🔴 +841 B 🔴 +714 B
assets/MediaImageTop-BtY1hGDO.js (removed) 1.75 kB 🟢 -1.75 kB 🟢 -843 B 🟢 -718 B
assets/WidgetToggleSwitch-DPJMnc2A.js (removed) 1.58 kB 🟢 -1.58 kB 🟢 -759 B 🟢 -663 B
assets/WidgetToggleSwitch-E1fZMVnN.js (new) 1.58 kB 🔴 +1.58 kB 🔴 +760 B 🔴 +670 B
assets/MediaImageBottom-C_YgZSGI.js (new) 1.57 kB 🔴 +1.57 kB 🔴 +745 B 🔴 +647 B
assets/MediaImageBottom-M0YSS0zk.js (removed) 1.57 kB 🟢 -1.57 kB 🟢 -742 B 🟢 -648 B
assets/MediaAudioBottom-C2AYyE-5.js (removed) 1.52 kB 🟢 -1.52 kB 🟢 -740 B 🟢 -658 B
assets/MediaAudioBottom-DMheqyQr.js (new) 1.52 kB 🔴 +1.52 kB 🔴 +741 B 🔴 +653 B
assets/MediaVideoBottom-p0wswRKb.js (new) 1.52 kB 🔴 +1.52 kB 🔴 +741 B 🔴 +654 B
assets/MediaVideoBottom-SAdrXMVx.js (removed) 1.52 kB 🟢 -1.52 kB 🟢 -737 B 🟢 -652 B
assets/Media3DBottom-B4kk52r-.js (removed) 1.5 kB 🟢 -1.5 kB 🟢 -732 B 🟢 -650 B
assets/Media3DBottom-DfQ1O1QL.js (new) 1.5 kB 🔴 +1.5 kB 🔴 +734 B 🔴 +649 B
assets/Media3DTop-CtfzlsE5.js (new) 1.49 kB 🔴 +1.49 kB 🔴 +764 B 🔴 +651 B
assets/Media3DTop-DYCaiQMv.js (removed) 1.49 kB 🟢 -1.49 kB 🟢 -765 B 🟢 -653 B
assets/MediaAudioTop-BPDWO8-i.js (removed) 1.46 kB 🟢 -1.46 kB 🟢 -740 B 🟢 -616 B
assets/MediaAudioTop-T0xe8Y0p.js (new) 1.46 kB 🔴 +1.46 kB 🔴 +739 B 🔴 +620 B
assets/WidgetSelect-5xpY2yvH.js (new) 685 B 🔴 +685 B 🔴 +353 B 🔴 +315 B
assets/WidgetSelect-AHfGel_s.js (removed) 655 B 🟢 -655 B 🟢 -342 B 🟢 -289 B
assets/WidgetInputNumber-D0dP4VmT.js (removed) 595 B 🟢 -595 B 🟢 -328 B 🟢 -278 B
assets/WidgetInputNumber-YgB6_Psa.js (new) 595 B 🔴 +595 B 🔴 +330 B 🔴 +275 B
assets/Load3D-BuKrzzAk.js (new) 424 B 🔴 +424 B 🔴 +267 B 🔴 +222 B
assets/Load3D-u7r4K-hS.js (removed) 424 B 🟢 -424 B 🟢 -267 B 🟢 -223 B
assets/WidgetLegacy-BIC4JDWD.js (removed) 364 B 🟢 -364 B 🟢 -237 B 🟢 -203 B
assets/WidgetLegacy-BVYJC4Yw.js (new) 364 B 🔴 +364 B 🔴 +237 B 🔴 +194 B
assets/commands-_s-RvhJR.js 13.6 kB 13.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BuUILW6P.js 13 kB 13 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BV4R6fLx.js 14.9 kB 14.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BWp4HdfU.js 101 B 101 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CLwPdnT6.js 14.2 kB 14.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CWMchBmd.js 15.9 kB 15.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DazTQhtc.js 12.9 kB 12.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DmWrOe93.js 13.7 kB 13.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DwiH7Kr6.js 13.8 kB 13.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-mS3LCNPn.js 14.5 kB 14.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-B1JflQcI.js 72.2 kB 72.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-B2lyXe48.js 114 kB 114 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-B9XEQ-pc.js 94 kB 94 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BErKFzc-.js 73.1 kB 73.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Bf7Tze-u.js 83.4 kB 83.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BhGMcO4Q.js 84.3 kB 84.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CPZUloNQ.js 99 kB 99 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Cw9RZWRY.js 89 B 89 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Dva0z-T2.js 86.5 kB 86.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-un0K9wDS.js 81.8 kB 81.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-8e6QYQW0.js 283 kB 283 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-A_9dx4yn.js 304 kB 304 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BbD3HDi7.js 307 kB 307 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BOJhIPft.js 369 kB 369 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Bw_Jitw_.js 101 B 101 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-C-Pw33mW.js 317 kB 317 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-ChLyG0UJ.js 285 kB 285 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CUVPxA4l.js 342 kB 342 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Dx5Y4xrW.js 310 kB 310 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-JqO5mNmW.js 306 kB 306 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetPropFilter-BIbGSUAt.js 1.28 kB 1.28 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 23 added / 23 removed

@christian-byrne
Copy link
Contributor Author

I don't love compound logic in names like this.

Why's that?

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 79ddb75 and ee749eb.

📒 Files selected for processing (2)
  • src/composables/useCoreCommands.ts (7 hunks)
  • tests-ui/tests/composables/useCoreCommands.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (17)
**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{vue,ts,tsx}: Leverage VueUse functions for performance-enhancing utilities
Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.json

Files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/useCoreCommands.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Use es-toolkit for utility functions

Files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/useCoreCommands.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

Use TypeScript for type safety

**/*.{ts,tsx}: Never use any type - use proper TypeScript types
Never use as any type assertions - fix the underlying type issue

Files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/useCoreCommands.ts
**/*.{ts,tsx,js,vue}

📄 CodeRabbit inference engine (.cursorrules)

Implement proper error handling in components and services

**/*.{ts,tsx,js,vue}: Use 2-space indentation, single quotes, no semicolons, and maintain 80-character line width as configured in .prettierrc
Organize imports by sorting and grouping by plugin, and run pnpm format before committing

Files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/useCoreCommands.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use camelCase for variable and setting names in TypeScript/Vue files

Files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/useCoreCommands.ts
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,vue}: Use const settingStore = useSettingStore() and settingStore.get('Comfy.SomeSetting') to retrieve settings in TypeScript/Vue files
Use await settingStore.set('Comfy.SomeSetting', newValue) to update settings in TypeScript/Vue files
Check server capabilities using api.serverSupportsFeature('feature_name') before using enhanced features
Use api.getServerFeature('config_name', defaultValue) to retrieve server feature configuration

Enforce ESLint rules for Vue + TypeScript including: no floating promises, no unused imports, and i18n raw text restrictions in templates

Files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/useCoreCommands.ts
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Define dynamic setting defaults using runtime context with functions in settings configuration
Use defaultsByInstallVersion property for gradual feature rollout based on version in settings configuration

Files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/useCoreCommands.ts
tests-ui/**/*.test.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (tests-ui/CLAUDE.md)

tests-ui/**/*.test.{js,ts,jsx,tsx}: Write tests for new features
Follow existing test patterns in the codebase
Use existing test utilities rather than writing custom utilities
Mock external dependencies in tests
Always prefer vitest mock functions over writing verbose manual mocks

Files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
**/*.{test,spec}.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Unit and component tests should be located in tests-ui/ or co-located with components as src/components/**/*.{test,spec}.ts; E2E tests should be in browser_tests/

Files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
**/composables/use*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables in the format useXyz.ts

Files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/useCoreCommands.ts
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/composables/useCoreCommands.ts
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/composables/useCoreCommands.ts
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/composables/useCoreCommands.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/composables/useCoreCommands.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/composables/useCoreCommands.ts
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/composables/useCoreCommands.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/composables/useCoreCommands.ts
🧠 Learnings (15)
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Mock external dependencies in tests

Applied to files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks

Applied to files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Always prefer vitest mock functions over writing verbose manual mocks

Applied to files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible

Applied to files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-24T19:46:52.279Z
Learning: Applies to **/*.vue : Utilize ref and reactive for reactive state in Vue 3

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive state

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Implement computed properties with computed()

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-24T19:46:52.279Z
Learning: Applies to **/*.vue : Implement computed properties with computed() function

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-24T19:46:52.279Z
Learning: Applies to **/*.{vue,ts,tsx} : Leverage VueUse functions for performance-enhancing utilities

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Extract complex conditionals to computed properties

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:14.779Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:14.779Z
Learning: Applies to **/*.{ts,tsx,vue} : Use `const settingStore = useSettingStore()` and `settingStore.get('Comfy.SomeSetting')` to retrieve settings in TypeScript/Vue files

Applied to files:

  • src/composables/useCoreCommands.ts
🧬 Code graph analysis (1)
src/composables/useCoreCommands.ts (3)
tests-ui/tests/renderer/extensions/vueNodes/widgets/composables/useRemoteWidget.test.ts (1)
  • isCloud (34-36)
tests-ui/tests/renderer/extensions/vueNodes/widgets/composables/useComboWidget.test.ts (1)
  • isCloud (44-46)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: lint-and-format
  • GitHub Check: setup
  • GitHub Check: test
  • GitHub Check: collect
🔇 Additional comments (3)
tests-ui/tests/composables/useCoreCommands.test.ts (1)

101-106: LGTM! Mock structure correctly implements ref-like API.

The mock now properly returns isSubscribedOrIsNotCloud as a ref-like object with { value: true }, which matches how the production code accesses subscriptionState.value in the command functions.

src/composables/useCoreCommands.ts (2)

94-97: Excellent: Cloud-aware initialization successfully prevents module loading on local.

The conditional pattern isCloud ? useSubscription() : null ensures the cloud subscription module is only initialized in cloud environments, directly achieving the PR's stated goal. The fallback to defaultSubscriptionState (value: true) and noop correctly bypasses subscription checks on local builds.


489-490: Consistent subscription gating across all queue commands.

All three queue commands (QueuePrompt, QueuePromptFront, QueueSelectedOutputNodes) now uniformly check subscriptionState.value and invoke subscriptionDialog() when gated. This correctly enforces subscription requirements in cloud environments while allowing unrestricted execution locally.

Also applies to: 512-513, 534-535

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ef110f3 and 3b66bb9.

📒 Files selected for processing (16)
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue (2 hunks)
  • src/components/dialog/content/setting/CreditsPanel.vue (3 hunks)
  • src/components/topbar/CurrentUserPopover.test.ts (1 hunks)
  • src/components/topbar/CurrentUserPopover.vue (3 hunks)
  • src/composables/auth/useFirebaseAuthActions.ts (1 hunks)
  • src/composables/useCoreCommands.ts (7 hunks)
  • src/platform/cloud/subscription/components/SubscribeButton.vue (2 hunks)
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue (5 hunks)
  • src/platform/cloud/subscription/composables/useSubscription.ts (4 hunks)
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (2 hunks)
  • src/scripts/app.ts (1 hunks)
  • src/services/dialogService.ts (1 hunks)
  • tests-ui/tests/composables/useCoreCommands.test.ts (1 hunks)
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (3 hunks)
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (3 hunks)
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (19)
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/scripts/app.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/scripts/app.ts
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/scripts/app.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/scripts/app.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript exclusively; no new JavaScript code

Files:

  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/scripts/app.ts
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
**/*.{ts,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,vue}: Use camelCase for variable and function names
Indent with 2 spaces (see .prettierrc)
Use single quotes for strings (see .prettierrc)
No trailing semicolons (see .prettierrc)
Maximum line width of 80 characters (see .prettierrc)
Sort and group imports by plugin (run pnpm format before committing)
Never use any type; use proper TypeScript types instead
Never use as any type assertions; fix the underlying type issue instead
Avoid code comments unless absolutely necessary; write expressive, self-documenting code instead
When writing new code, ask if there is a simpler way to introduce the same functionality; if yes, choose the simpler approach
Use refactoring to make complex code simpler
Use es-toolkit for utility functions
Use Vite for fast development and building
Implement proper error handling
Write tests for all changes, especially bug fixes to catch future regressions

Files:

  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/scripts/app.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
**/composables/**/use*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables with useXyz.ts pattern

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/composables/useCoreCommands.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
tests-ui/**/*.test.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (tests-ui/CLAUDE.md)

tests-ui/**/*.test.{js,ts,jsx,tsx}: Write tests for new features
Follow existing test patterns in the codebase
Use existing test utilities rather than writing custom utilities
Mock external dependencies in tests
Always prefer vitest mock functions over writing verbose manual mocks

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.test.ts: Avoid writing change detector tests that just assert default values
Avoid writing tests dependent on non-behavioral features like utility classes or styles
Avoid writing redundant tests

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
src/components/**/*.vue

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue components

Files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
src/components/**/*.{vue,css}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package

Files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
src/components/**/*.{vue,ts,js}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings

Files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.test.ts
**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

**/*.vue: Use Vue 3 SFCs with Composition API only (use <script setup lang="ts">, not Options API)
Avoid using <style> blocks; use Tailwind 4 for all styling
Use defineProps with TypeScript style default declaration; do not use withDefaults or runtime props declaration
Prefer useModel over separately defining a prop and emit
Use computed instead of a ref and watch if possible
Avoid using ref if a prop would accomplish the design goals; avoid using computed if a ref or prop directly would work
Do not import Vue macros unnecessarily
Never use the dark: Tailwind variant; use semantic values from the style.css theme instead (e.g., bg-node-component-surface)
Never use :class="[]" to merge class names; always use cn() from @/utils/tailwindUtil (e.g., <div :class="cn('text-node-component-header-icon', hasError && 'text-danger')" />)
Leverage VueUse functions for performance-enhancing styles
Avoid new usage of PrimeVue components
Use Vue 3 Teleport component when needed
Use Vue 3 Suspense for async components

Files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
**/components/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

Name Vue components in PascalCase (e.g., MenuHamburger.vue)

Files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
src/**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

Write unit and component tests with Vitest using happy-dom

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
🧠 Learnings (19)
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks

Applied to files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/useCoreCommands.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue OverlayPanel component with Popover

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Extract complex conditionals to computed properties

Applied to files:

  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.vue : Use `computed` instead of a `ref` and `watch` if possible

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Implement computed properties with computed()

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.vue : Avoid using `ref` if a prop would accomplish the design goals; avoid using `computed` if a `ref` or prop directly would work

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.vue : Leverage VueUse functions for performance-enhancing styles

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.test.ts : Avoid writing change detector tests that just assert default values

Applied to files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Write tests for new features

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Mock external dependencies in tests

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Follow existing test patterns in the codebase

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Prefer emit/event-name for state changes over other communication patterns

Applied to files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Always prefer vitest mock functions over writing verbose manual mocks

Applied to files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
🧬 Code graph analysis (6)
src/services/dialogService.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • CloudSubscriptionStatusResponse (23-28)
src/composables/auth/useFirebaseAuthActions.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/scripts/app.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/composables/useCoreCommands.ts (3)
tests-ui/tests/renderer/extensions/vueNodes/widgets/composables/useRemoteWidget.test.ts (1)
  • isCloud (34-36)
tests-ui/tests/renderer/extensions/vueNodes/widgets/composables/useComboWidget.test.ts (1)
  • isCloud (44-46)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: setup
  • GitHub Check: test
  • GitHub Check: collect
  • GitHub Check: lint-and-format
🔇 Additional comments (17)
src/components/topbar/CurrentUserPopover.test.ts (1)

85-85: LGTM! Mock correctly updated.

The mock shape properly reflects the ref-like structure of isSubscriptionRequirementMet from the renamed subscription API.

tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (2)

10-10: LGTM! Mock data updated consistently.

The subscription requirement property is correctly renamed throughout the mock data and test assertions.


123-151: LGTM! Test assertions updated correctly.

All test cases properly reference isSubscriptionRequirementMet instead of the old isActiveSubscription property, maintaining test coverage while aligning with the renamed API.

src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue (1)

14-17: LGTM! Subscription state properly renamed.

The component correctly destructures and accesses isSubscriptionRequirementMet.value to determine which button to render.

tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts (2)

27-27: LGTM! Test variable renamed consistently.

The computed ref is correctly renamed to isSubscriptionRequirementMet, matching the updated composable API.


77-83: LGTM! Watcher options updated correctly.

All initWatcher calls properly pass isSubscriptionRequirementMet instead of the old parameter name, maintaining test coverage.

tests-ui/tests/composables/useCoreCommands.test.ts (1)

103-103: LGTM! Mock shape corrected.

The mock now correctly provides isSubscriptionRequirementMet as a ref-like object with a value property, matching the real composable API and addressing the previous review feedback.

src/platform/cloud/subscription/components/SubscribeButton.vue (2)

54-55: LGTM! Subscription state properly renamed.

The destructuring correctly uses isSubscriptionRequirementMet from the updated composable API.


80-80: LGTM! Polling completion check updated correctly.

The condition properly references isSubscriptionRequirementMet.value to determine when to stop polling and emit the subscribed event.

tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (2)

95-110: Tests correctly updated to use isSubscriptionRequirementMet (active case).

Renaming to isSubscriptionRequirementMet and asserting .value === true for an active subscription matches the new composable API and semantics. No further changes needed here.


112-127: Tests correctly updated to use isSubscriptionRequirementMet (inactive case).

The inactive subscription test now destructures isSubscriptionRequirementMet and asserts .value === false, which is consistent with the new computed behavior under subscription_required: true.

src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (1)

13-19: Rename to isSubscriptionRequirementMet is consistent and behavior‑preserving.

The watcher options, destructuring, and cancellation check now consistently use isSubscriptionRequirementMet.value. Given the caller only enables the watcher when cloud subscription is required, this keeps the previous behavior while aligning with the new API name.

Also applies to: 21-27, 69-77

src/scripts/app.ts (1)

679-690: Cloud‑aware top‑up dialog gating looks correct.

The new logic avoids initializing useSubscription() on non‑cloud builds and, in cloud, only shows the Top Up Credits dialog when isSubscriptionRequirementMet.value is true, which aligns with the intended “only top‑up for active subscribers” behavior. This also keeps the Payment Required flow side‑effect‑free on local.

src/components/dialog/content/setting/CreditsPanel.vue (1)

18-22: CreditsPanel now correctly gates on cloud subscription without initializing it on local.

Using subscription = isCloud ? useSubscription() : null plus the computed isSubscriptionRequirementMet (true for non‑cloud, delegated to the composable in cloud) cleanly meets the PR goal: no cloud subscription initialization on local, while still hiding the purchase button when the subscription requirement isn’t met in cloud.

Also applies to: 128-152

src/platform/cloud/subscription/components/SubscriptionPanel.vue (1)

6-10: SubscriptionPanel correctly migrated to isSubscriptionRequirementMet.

All title, detail, and button conditions now depend on isSubscriptionRequirementMet, and the script setup destructuring matches the updated useSubscription API. The subscribed vs unsubscribed UI flows remain intact under the new flag name.

Also applies to: 30-51, 189-212, 322-330

src/composables/useCoreCommands.ts (1)

1-2: Cloud‑aware subscription gating for core commands is well factored.

The defaultSubscriptionState/noop helpers plus subscription = isCloud ? useSubscription() : null and subscriptionState/subscriptionDialog give you:

  • No subscription initialization or gating in non‑cloud builds.
  • Centralized, readable gating for all queue commands in cloud (QueuePrompt, QueuePromptFront, QueueSelectedOutputNodes).

Using computed(() => true) for the default state is also a nice, type‑safe improvement over the previous manual object.

Also applies to: 52-52, 69-71, 92-96, 486-490, 509-513, 531-535

src/platform/cloud/subscription/composables/useSubscription.ts (1)

34-38: useSubscription’s new isSubscriptionRequirementMet flag cleanly encodes environment‑aware gating.

The computed correctly short‑circuits to true when not in cloud or when subscription_required is disabled, and otherwise reflects subscriptionStatus.is_active. Wiring this into useSubscriptionCancellationWatcher, requireActiveSubscription, and the returned state object keeps downstream consumers consistent with the renamed, more expressive flag without changing cloud behavior where subscription is enforced.

Also applies to: 108-115, 125-131, 224-231

@christian-byrne christian-byrne force-pushed the fix/top-up-local branch 2 times, most recently from 9614a5d to 490e7ea Compare December 6, 2025 04:08
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (1)

8-17: Align isSubscriptionRequirementMet mock with ref/computed API

In this suite, mockSubscriptionData.isSubscriptionRequirementMet is a bare boolean, but elsewhere isSubscriptionRequirementMet is treated as a ref/computed (.value is read in components like SubscribeButton.vue and related composables). Using a plain boolean here risks the tests drifting from the real API if SubscriptionPanel.vue ever starts reading .value.

To keep the mock shape consistent and future-proof the tests, consider making it ref-like and updating the mutations:

 const mockSubscriptionData = {
-  isSubscriptionRequirementMet: false,
+  isSubscriptionRequirementMet: { value: false },
   isCancelled: false,
   formattedRenewalDate: '2024-12-31',
   formattedEndDate: '2024-12-31',
   formattedMonthlyPrice: '$9.99',
   manageSubscription: vi.fn(),
   handleInvoiceHistory: vi.fn()
 }
@@
   describe('subscription state functionality', () => {
     it('shows correct UI for active subscription', () => {
-      mockSubscriptionData.isSubscriptionRequirementMet = true
+      mockSubscriptionData.isSubscriptionRequirementMet.value = true
@@
     it('shows correct UI for inactive subscription', () => {
-      mockSubscriptionData.isSubscriptionRequirementMet = false
+      mockSubscriptionData.isSubscriptionRequirementMet.value = false
@@
     it('shows renewal date for active non-cancelled subscription', () => {
-      mockSubscriptionData.isSubscriptionRequirementMet = true
+      mockSubscriptionData.isSubscriptionRequirementMet.value = true
@@
     it('shows expiry date for cancelled subscription', () => {
-      mockSubscriptionData.isSubscriptionRequirementMet = true
+      mockSubscriptionData.isSubscriptionRequirementMet.value = true

This keeps the tests closely aligned with the production composable while preserving the existing scenarios.

Also applies to: 123-123, 130-130, 140-140, 147-147

src/scripts/app.ts (1)

46-47: Avoid duplicating subscription gating and static useSubscription import in app.ts

The new execution_error branch correctly gates the Top Up dialog on isSubscriptionRequirementMet in cloud, but showTopUpCreditsDialog already encapsulates that same cloud-aware check (including a lazy import of useSubscription). Doing the check again here:

  • Duplicates logic and checks the same flag twice in cloud builds.
  • Forces a static import { useSubscription } in app.ts, which works against the goal of keeping cloud-only modules out of local builds where possible.

You can simplify and better support tree-shaking by delegating to the dialog service and removing the direct useSubscription dependency:

-import { useDialogService } from '@/services/dialogService'
-import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
+import { useDialogService } from '@/services/dialogService'
@@
-      } else if (
+      } else if (
         detail.exception_message?.includes(
           'Payment Required: Please add credits to your account to use this node.'
         )
       ) {
-        if (!isCloud) {
-          useDialogService().showTopUpCreditsDialog({
-            isInsufficientCredits: true
-          })
-        } else {
-          const { isSubscriptionRequirementMet } = useSubscription()
-          if (isSubscriptionRequirementMet.value) {
-            useDialogService().showTopUpCreditsDialog({
-              isInsufficientCredits: true
-            })
-          }
-        }
+        useDialogService().showTopUpCreditsDialog({
+          isInsufficientCredits: true
+        })
       } else {

Since showTopUpCreditsDialog already handles the isCloud + isSubscriptionRequirementMet gating internally, this preserves behavior while keeping the cloud-specific composable out of app.ts.

Also applies to: 666-691

src/services/dialogService.ts (1)

379-401: Update all non-awaited call sites to handle async showTopUpCreditsDialog

The function is now async, but three of four call sites do not await it:

  • src/scripts/app.ts:680, 686: Called in error handler without await. The early return on !isSubscriptionRequirementMet will not prevent the dialog call.
  • src/components/topbar/CurrentUserPopover.vue:151: Called in synchronous handleTopUp() without await.
  • src/components/dialog/content/setting/CreditsPanel.vue:176: Called in synchronous handlePurchaseCreditsClick() without await.

Only src/platform/cloud/subscription/composables/useSubscriptionActions.ts:40 properly awaits the function in an async context.

The cloud-gating logic (early return when isCloud && !isSubscriptionRequirementMet) will not work as intended for non-awaited call sites. Either add await to each call site (and make the containing function async), or remove the early return and handle the gating at the call site.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9614a5d and 490e7ea.

📒 Files selected for processing (17)
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue (2 hunks)
  • src/components/dialog/content/setting/CreditsPanel.vue (3 hunks)
  • src/components/topbar/CurrentUserPopover.test.ts (1 hunks)
  • src/components/topbar/CurrentUserPopover.vue (4 hunks)
  • src/composables/auth/useFirebaseAuthActions.ts (1 hunks)
  • src/composables/useCoreCommands.ts (7 hunks)
  • src/platform/cloud/subscription/components/SubscribeButton.vue (2 hunks)
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue (5 hunks)
  • src/platform/cloud/subscription/composables/useSubscription.ts (4 hunks)
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts (1 hunks)
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (2 hunks)
  • src/scripts/app.ts (1 hunks)
  • src/services/dialogService.ts (1 hunks)
  • tests-ui/tests/composables/useCoreCommands.test.ts (1 hunks)
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (3 hunks)
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (3 hunks)
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (19)
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/composables/useCoreCommands.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript exclusively; no new JavaScript code

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
**/*.{ts,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,vue}: Use camelCase for variable and function names
Indent with 2 spaces (see .prettierrc)
Use single quotes for strings (see .prettierrc)
No trailing semicolons (see .prettierrc)
Maximum line width of 80 characters (see .prettierrc)
Sort and group imports by plugin (run pnpm format before committing)
Never use any type; use proper TypeScript types instead
Never use as any type assertions; fix the underlying type issue instead
Avoid code comments unless absolutely necessary; write expressive, self-documenting code instead
When writing new code, ask if there is a simpler way to introduce the same functionality; if yes, choose the simpler approach
Use refactoring to make complex code simpler
Use es-toolkit for utility functions
Use Vite for fast development and building
Implement proper error handling
Write tests for all changes, especially bug fixes to catch future regressions

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/components/topbar/CurrentUserPopover.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/scripts/app.ts
**/composables/**/use*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables with useXyz.ts pattern

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
src/components/**/*.vue

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue components

Files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
src/components/**/*.{vue,css}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package

Files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
src/components/**/*.{vue,ts,js}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings

Files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.test.ts
**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

**/*.vue: Use Vue 3 SFCs with Composition API only (use <script setup lang="ts">, not Options API)
Avoid using <style> blocks; use Tailwind 4 for all styling
Use defineProps with TypeScript style default declaration; do not use withDefaults or runtime props declaration
Prefer useModel over separately defining a prop and emit
Use computed instead of a ref and watch if possible
Avoid using ref if a prop would accomplish the design goals; avoid using computed if a ref or prop directly would work
Do not import Vue macros unnecessarily
Never use the dark: Tailwind variant; use semantic values from the style.css theme instead (e.g., bg-node-component-surface)
Never use :class="[]" to merge class names; always use cn() from @/utils/tailwindUtil (e.g., <div :class="cn('text-node-component-header-icon', hasError && 'text-danger')" />)
Leverage VueUse functions for performance-enhancing styles
Avoid new usage of PrimeVue components
Use Vue 3 Teleport component when needed
Use Vue 3 Suspense for async components

Files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
**/components/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

Name Vue components in PascalCase (e.g., MenuHamburger.vue)

Files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
tests-ui/**/*.test.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (tests-ui/CLAUDE.md)

tests-ui/**/*.test.{js,ts,jsx,tsx}: Write tests for new features
Follow existing test patterns in the codebase
Use existing test utilities rather than writing custom utilities
Mock external dependencies in tests
Always prefer vitest mock functions over writing verbose manual mocks

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.test.ts: Avoid writing change detector tests that just assert default values
Avoid writing tests dependent on non-behavioral features like utility classes or styles
Avoid writing redundant tests

Files:

  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/components/topbar/CurrentUserPopover.test.ts
src/**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

Write unit and component tests with Vitest using happy-dom

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
🧠 Learnings (29)
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks

Applied to files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/components/topbar/CurrentUserPopover.vue
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • src/composables/useCoreCommands.ts
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue OverlayPanel component with Popover

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Sidebar component with Drawer

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Calendar component with DatePicker

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.vue : Avoid new usage of PrimeVue components

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue TabMenu component with Tabs without panels

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Implement lifecycle hooks with onMounted, onUpdated, etc.

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use setup() function in Vue 3 Composition API

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Write tests for new features

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.test.ts : Avoid writing change detector tests that just assert default values

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Mock external dependencies in tests

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/components/topbar/CurrentUserPopover.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible

Applied to files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/components/topbar/CurrentUserPopover.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Extract complex conditionals to computed properties

Applied to files:

  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/composables/useCoreCommands.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.vue : Use `computed` instead of a `ref` and `watch` if possible

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Implement computed properties with computed()

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.vue : Avoid using `ref` if a prop would accomplish the design goals; avoid using `computed` if a `ref` or prop directly would work

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.vue : Leverage VueUse functions for performance-enhancing styles

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Prefer emit/event-name for state changes over other communication patterns

Applied to files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Always prefer vitest mock functions over writing verbose manual mocks

Applied to files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setup

Applied to files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{services,composables}/**/*.{ts,tsx} : Use `api.fileURL()` for static file access instead of constructing URLs directly

Applied to files:

  • src/composables/auth/useFirebaseAuthActions.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Implement proper error handling

Applied to files:

  • src/composables/auth/useFirebaseAuthActions.ts
🧬 Code graph analysis (5)
src/composables/useCoreCommands.ts (3)
tests-ui/tests/renderer/extensions/vueNodes/widgets/composables/useRemoteWidget.test.ts (1)
  • isCloud (34-36)
tests-ui/tests/renderer/extensions/vueNodes/widgets/composables/useComboWidget.test.ts (1)
  • isCloud (44-46)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/services/dialogService.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/composables/auth/useFirebaseAuthActions.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/scripts/app.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test
  • GitHub Check: setup
  • GitHub Check: lint-and-format
🔇 Additional comments (19)
src/components/topbar/CurrentUserPopover.test.ts (1)

81-88: Ref-like isSubscriptionRequirementMet mock matches composable API

Mocking isSubscriptionRequirementMet as { value: true } aligns with a ref/computed-style API and avoids .value access issues in the component under test. This is consistent with the other updated tests.

tests-ui/tests/composables/useCoreCommands.test.ts (1)

101-106: Correct ref-like mock for isSubscriptionRequirementMet

Returning isSubscriptionRequirementMet as { value: true } fixes the earlier mismatch with the real composable (which is read via .value) and keeps the guard logic in useCoreCommands behaving as in production.

tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts (1)

27-27: Computed isSubscriptionRequirementMet correctly mirrors active state

Deriving isSubscriptionRequirementMet via computed(() => isActive.value) and passing it into useSubscriptionCancellationWatcher keeps the tests aligned with the new API while preserving behavior of all scenarios (cancellation detection, focus-triggered checks, max attempts, and guard failures).

Also applies to: 77-83, 107-113, 129-135, 155-160

src/platform/cloud/subscription/composables/useSubscriptionActions.ts (1)

39-41: Async handleAddApiCredits correctly mirrors async dialog behavior

Making handleAddApiCredits async and awaiting dialogService.showTopUpCreditsDialog() matches the dialog’s new async, gated behavior and keeps the action’s completion semantics clear. Call sites using it as a click handler continue to work as before.

src/platform/cloud/subscription/components/SubscribeButton.vue (1)

54-55: Correct use of isSubscriptionRequirementMet ref in subscribe polling

Destructuring isSubscriptionRequirementMet from useSubscription() and checking isSubscriptionRequirementMet.value inside the polling loop preserves the previous behavior while aligning with the new flag name and ref-like API.

Also applies to: 80-84

src/composables/auth/useFirebaseAuthActions.ts (1)

84-90: LGTM! Dynamic import pattern correctly enables tree-shaking for local builds.

The useSubscription composable is now lazily imported within the isCloud guard, ensuring cloud modules won't be bundled in local environments. The subscription requirement check properly gates the purchase flow.

src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (1)

13-23: LGTM! Consistent rename of subscription state property.

The isActiveSubscriptionisSubscriptionRequirementMet rename is correctly applied in the type definition, parameter destructuring, and all usages. The cleanup logic via onScopeDispose properly prevents memory leaks.

src/components/topbar/CurrentUserPopover.vue (2)

128-131: LGTM! Cloud-aware subscription initialization with proper fallbacks.

The conditional useSubscription() call with fallbacks for non-cloud environments is correctly implemented. The isSubscriptionRequirementMet defaults to true and fetchStatus to a no-op when not in cloud context.

Note: Same tree-shaking consideration as CreditsPanel.vue applies here regarding the static import. If tree-shaking is critical, dynamic import could be used, but this may be acceptable if the popover is primarily used in cloud environments.


26-29: Template bindings correctly updated to use renamed property.

The conditional rendering based on isSubscriptionRequirementMet properly gates the credits section and plan settings button, showing the subscribe button when the requirement is not met.

src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue (1)

12-17: No action needed—this component is properly guarded by isCloud.

CloudRunButtonWrapper is only imported when isCloud && window.__CONFIG__?.subscription_required is true (in src/components/actionbar/ComfyRunButton/index.ts), so the direct useSubscription() call is safe and will not initialize cloud modules in local environments.

src/components/dialog/content/setting/CreditsPanel.vue (1)

127-152: Code pattern is correct and tree-shakeable; no changes needed.

The current implementation properly supports tree-shaking. The isCloud constant is a build-time value (DISTRIBUTION === 'cloud'), enabling the bundler to eliminate the unused branch in local builds. The pattern of static import with conditional call (isCloud ? useSubscription() : null) is consistent with the codebase and allows dead-code elimination at build time. Additionally, CreditsPanel itself is already dynamically imported in useSettingUI.ts, making it a lazy-loaded component that won't be included in local builds.

tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (1)

95-127: LGTM!

Test descriptions and assertions are correctly updated to reference isSubscriptionRequirementMet. The test logic properly validates both active and inactive subscription scenarios.

src/composables/useCoreCommands.ts (2)

69-96: Cloud-aware subscription initialization pattern looks correct.

The implementation properly defers useSubscription() initialization to cloud environments only, achieving the PR's goal of avoiding cloud module initialization on local. The fallback pattern with computed(() => true) and noop ensures non-cloud environments bypass subscription gating seamlessly.


487-490: LGTM!

Subscription gating correctly checks subscriptionState.value and shows the dialog with early return when the requirement is not met. This pattern is consistently applied across all queue commands.

src/platform/cloud/subscription/components/SubscriptionPanel.vue (2)

7-10: LGTM!

Template correctly uses the renamed isSubscriptionRequirementMet property for conditional rendering of subscription-related UI elements.


322-330: LGTM!

Script setup correctly destructures isSubscriptionRequirementMet from useSubscription(), maintaining alignment with the composable's updated API.

src/platform/cloud/subscription/composables/useSubscription.ts (3)

34-38: LGTM!

The renamed isSubscriptionRequirementMet computed property accurately reflects the semantic: the requirement is met when either (1) not running on cloud, (2) subscription is not required by config, or (3) subscription is active. This is more expressive than the previous isActiveSubscription name.


111-118: LGTM!

Cancellation watcher correctly receives the renamed isSubscriptionRequirementMet computed property.


224-241: LGTM!

The return object correctly exposes the renamed isSubscriptionRequirementMet property. All consumers in the PR have been updated to consume this renamed API.

import { useSubgraphNavigationStore } from '@/stores/subgraphNavigationStore'
import { useSubgraphStore } from '@/stores/subgraphStore'
import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore'
import { isCloud } from '@/platform/distribution/types'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Import placement breaks alphabetical grouping.

The isCloud import is inserted between unrelated imports, breaking the alphabetical ordering within the import group. This should be placed with other platform imports or sorted according to the project's import conventions.

-import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore'
-import { isCloud } from '@/platform/distribution/types'
-import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'
+import { isCloud } from '@/platform/distribution/types'
+import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore'
+import { useColorPaletteStore } from '@/stores/workspace/colorPaletteStore'

Note: Run pnpm format to auto-sort imports per the coding guidelines.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/composables/useCoreCommands.ts around line 52, the import "isCloud" was
inserted between unrelated imports and breaks the file's alphabetical/grouping
convention; move the import into the existing platform/distribution import block
(or next to other platform imports) and reorder imports alphabetically per
project conventions, then run "pnpm format" to auto-sort and apply formatting.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)

112-120: legacyIsActiveSubscription argument mirrors an unused option in the watcher

You’re passing legacyIsActiveSubscription: isActiveSubscription here, but useSubscriptionCancellationWatcher never reads that option—only isSubscriptionRequirementMet. This mirrors the dead field in the watcher options and doesn’t currently change behavior.

Recommend either removing this property from the call or updating the watcher to actually consume it, depending on whether you truly need a legacy path.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 490e7ea and 4b58fd3.

📒 Files selected for processing (2)
  • src/platform/cloud/subscription/composables/useSubscription.ts (4 hunks)
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript exclusively; no new JavaScript code

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
**/*.{ts,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,vue}: Use camelCase for variable and function names
Indent with 2 spaces (see .prettierrc)
Use single quotes for strings (see .prettierrc)
No trailing semicolons (see .prettierrc)
Maximum line width of 80 characters (see .prettierrc)
Sort and group imports by plugin (run pnpm format before committing)
Never use any type; use proper TypeScript types instead
Never use as any type assertions; fix the underlying type issue instead
Avoid code comments unless absolutely necessary; write expressive, self-documenting code instead
When writing new code, ask if there is a simpler way to introduce the same functionality; if yes, choose the simpler approach
Use refactoring to make complex code simpler
Use es-toolkit for utility functions
Use Vite for fast development and building
Implement proper error handling
Write tests for all changes, especially bug fixes to catch future regressions

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
**/composables/**/use*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables with useXyz.ts pattern

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
🧠 Learnings (1)
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks

Applied to files:

  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
🧬 Code graph analysis (1)
src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (2)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • CloudSubscriptionStatusResponse (23-28)
src/platform/telemetry/types.ts (1)
  • TelemetryProvider (259-328)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: deploy-and-comment
  • GitHub Check: setup
  • GitHub Check: collect
  • GitHub Check: lint-and-format
  • GitHub Check: test
🔇 Additional comments (3)
src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (1)

70-102: Switch to isSubscriptionRequirementMet in cancellation check looks correct

Using !isSubscriptionRequirementMet.value here matches the new “subscription required & active” semantics, and the watcher still correctly stops the timer and detaches the focus listener via stopCancellationWatcher, avoiding leaks. Based on learnings, this aligns with the subscription cleanup guidance.

src/platform/cloud/subscription/composables/useSubscription.ts (2)

34-40: isSubscriptionRequirementMet computed + aliasing via isActiveSubscription look sound

The computed correctly short-circuits to true for non‑cloud or non‑subscription‑required configs and falls back to subscriptionStatus.value?.is_active otherwise. Reusing the same computed instance for isActiveSubscription is a clean way to keep older call sites working without duplicating state.


226-231: Exposing both isSubscriptionRequirementMet and isActiveSubscription is a reasonable transition path

Returning the new flag plus the alias (with an inline deprecation note) gives callers time to migrate without breaking changes, while ensuring both names reflect the same underlying state.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (1)

10-17: Align isSubscriptionRequirementMet mock with ref-like API

Elsewhere useSubscription exposes isSubscriptionRequirementMet as a ref/computed, and other tests mock it as { value: boolean }. Here it’s a plain boolean and reassigned directly, which can diverge from production behavior if SubscriptionPanel.vue ever reads .value.

To keep mocks consistent and future‑proof, consider updating the shape:

 const mockSubscriptionData = {
-  isSubscriptionRequirementMet: false,
+  isSubscriptionRequirementMet: { value: false },
   isCancelled: false,
   formattedRenewalDate: '2024-12-31',
   formattedEndDate: '2024-12-31',
   formattedMonthlyPrice: '$9.99',
   manageSubscription: vi.fn(),
   handleInvoiceHistory: vi.fn()
 }

And in the tests:

 it('shows correct UI for active subscription', () => {
-  mockSubscriptionData.isSubscriptionRequirementMet = true
+  mockSubscriptionData.isSubscriptionRequirementMet.value = true
   const wrapper = createWrapper()
   expect(wrapper.text()).toContain('Manage Subscription')
   expect(wrapper.text()).toContain('Add Credits')
 })

 it('shows correct UI for inactive subscription', () => {
-  mockSubscriptionData.isSubscriptionRequirementMet = false
+  mockSubscriptionData.isSubscriptionRequirementMet.value = false
   const wrapper = createWrapper()
   …
 })

 it('shows renewal date for active non-cancelled subscription', () => {
-  mockSubscriptionData.isSubscriptionRequirementMet = true
+  mockSubscriptionData.isSubscriptionRequirementMet.value = true
   mockSubscriptionData.isCancelled = false
   …
 })

 it('shows expiry date for cancelled subscription', () => {
-  mockSubscriptionData.isSubscriptionRequirementMet = true
+  mockSubscriptionData.isSubscriptionRequirementMet.value = true
   mockSubscriptionData.isCancelled = true
   …
 })

This keeps the test double structurally compatible with the real composable.

Also applies to: 123-152

♻️ Duplicate comments (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)

125-131: Consider early‑returning in requireActiveSubscription when subscription isn’t required

requireActiveSubscription still calls fetchSubscriptionStatus() even when isSubscriptionRequirementMet will always be true (e.g., non‑cloud builds or when subscription_required is false), which means unnecessary network calls and side‑effects in cases where gating is effectively disabled.

You can short‑circuit before fetching to better match the PR goal of avoiding cloud side‑effects locally:

-  const requireActiveSubscription = async (): Promise<void> => {
-    await fetchSubscriptionStatus()
-
-    if (!isSubscriptionRequirementMet.value) {
-      showSubscriptionDialog()
-    }
-  }
+  const requireActiveSubscription = async (): Promise<void> => {
+    // Skip remote status checks when subscription gating is not enforced
+    if (!isCloud || !window.__CONFIG__?.subscription_required) {
+      return
+    }
+
+    await fetchSubscriptionStatus()
+
+    if (!isSubscriptionRequirementMet.value) {
+      showSubscriptionDialog()
+    }
+  }

This preserves behavior for cloud builds while avoiding unnecessary initialization and network calls when the subscription requirement is disabled.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4b58fd3 and 1ebdab9.

📒 Files selected for processing (18)
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue (2 hunks)
  • src/components/dialog/content/setting/CreditsPanel.vue (3 hunks)
  • src/components/topbar/CurrentUserPopover.test.ts (1 hunks)
  • src/components/topbar/CurrentUserPopover.vue (4 hunks)
  • src/composables/auth/useFirebaseAuthActions.ts (1 hunks)
  • src/composables/useCoreCommands.ts (7 hunks)
  • src/extensions/core/cloudRemoteConfig.ts (1 hunks)
  • src/platform/cloud/subscription/components/SubscribeButton.vue (2 hunks)
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue (5 hunks)
  • src/platform/cloud/subscription/composables/useSubscription.ts (4 hunks)
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts (1 hunks)
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (2 hunks)
  • src/scripts/app.ts (1 hunks)
  • src/services/dialogService.ts (1 hunks)
  • tests-ui/tests/composables/useCoreCommands.test.ts (1 hunks)
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (3 hunks)
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (3 hunks)
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (19)
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/scripts/app.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/extensions/core/cloudRemoteConfig.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • src/scripts/app.ts
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/extensions/core/cloudRemoteConfig.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/scripts/app.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/extensions/core/cloudRemoteConfig.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/scripts/app.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/extensions/core/cloudRemoteConfig.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
src/components/**/*.{vue,ts,js}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript exclusively; no new JavaScript code

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • src/scripts/app.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/extensions/core/cloudRemoteConfig.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
**/*.{ts,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,vue}: Use camelCase for variable and function names
Indent with 2 spaces (see .prettierrc)
Use single quotes for strings (see .prettierrc)
No trailing semicolons (see .prettierrc)
Maximum line width of 80 characters (see .prettierrc)
Sort and group imports by plugin (run pnpm format before committing)
Never use any type; use proper TypeScript types instead
Never use as any type assertions; fix the underlying type issue instead
Avoid code comments unless absolutely necessary; write expressive, self-documenting code instead
When writing new code, ask if there is a simpler way to introduce the same functionality; if yes, choose the simpler approach
Use refactoring to make complex code simpler
Use es-toolkit for utility functions
Use Vite for fast development and building
Implement proper error handling
Write tests for all changes, especially bug fixes to catch future regressions

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/scripts/app.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/extensions/core/cloudRemoteConfig.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
src/**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

Write unit and component tests with Vitest using happy-dom

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.test.ts: Avoid writing change detector tests that just assert default values
Avoid writing tests dependent on non-behavioral features like utility classes or styles
Avoid writing redundant tests

Files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
src/components/**/*.vue

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue components

Files:

  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
src/components/**/*.{vue,css}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package

Files:

  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

**/*.vue: Use Vue 3 SFCs with Composition API only (use <script setup lang="ts">, not Options API)
Avoid using <style> blocks; use Tailwind 4 for all styling
Use defineProps with TypeScript style default declaration; do not use withDefaults or runtime props declaration
Prefer useModel over separately defining a prop and emit
Use computed instead of a ref and watch if possible
Avoid using ref if a prop would accomplish the design goals; avoid using computed if a ref or prop directly would work
Do not import Vue macros unnecessarily
Never use the dark: Tailwind variant; use semantic values from the style.css theme instead (e.g., bg-node-component-surface)
Never use :class="[]" to merge class names; always use cn() from @/utils/tailwindUtil (e.g., <div :class="cn('text-node-component-header-icon', hasError && 'text-danger')" />)
Leverage VueUse functions for performance-enhancing styles
Avoid new usage of PrimeVue components
Use Vue 3 Teleport component when needed
Use Vue 3 Suspense for async components

Files:

  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
**/components/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

Name Vue components in PascalCase (e.g., MenuHamburger.vue)

Files:

  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/components/topbar/CurrentUserPopover.vue
  • src/components/dialog/content/setting/CreditsPanel.vue
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
tests-ui/**/*.test.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (tests-ui/CLAUDE.md)

tests-ui/**/*.test.{js,ts,jsx,tsx}: Write tests for new features
Follow existing test patterns in the codebase
Use existing test utilities rather than writing custom utilities
Mock external dependencies in tests
Always prefer vitest mock functions over writing verbose manual mocks

Files:

  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
src/**/{services,composables}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/{services,composables}/**/*.{ts,tsx}: Use api.apiURL() for backend endpoints instead of constructing URLs directly
Use api.fileURL() for static file access instead of constructing URLs directly

Files:

  • src/services/dialogService.ts
  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
**/composables/**/use*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Name composables with useXyz.ts pattern

Files:

  • src/platform/cloud/subscription/composables/useSubscriptionActions.ts
  • src/composables/useCoreCommands.ts
  • src/composables/auth/useFirebaseAuthActions.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
🧠 Learnings (33)
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Mock external dependencies in tests

Applied to files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible

Applied to files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Write tests for new features

Applied to files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.test.ts : Avoid writing change detector tests that just assert default values

Applied to files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setup

Applied to files:

  • src/components/topbar/CurrentUserPopover.test.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks

Applied to files:

  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts
  • src/platform/cloud/subscription/components/SubscribeButton.vue
  • src/services/dialogService.ts
  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.vue
  • src/composables/auth/useFirebaseAuthActions.ts
  • src/extensions/core/cloudRemoteConfig.ts
  • tests-ui/tests/composables/useCoreCommands.test.ts
  • src/platform/cloud/subscription/components/SubscriptionPanel.vue
  • src/platform/cloud/subscription/composables/useSubscription.ts
  • tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts
  • src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Extract complex conditionals to computed properties

Applied to files:

  • src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue
  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Prefer emit/event-name for state changes over other communication patterns

Applied to files:

  • src/platform/cloud/subscription/components/SubscribeButton.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.vue : Use `computed` instead of a `ref` and `watch` if possible

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Implement computed properties with computed()

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.{ts,vue} : Sort and group imports by plugin (run `pnpm format` before committing)

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.vue : Leverage VueUse functions for performance-enhancing styles

Applied to files:

  • src/composables/useCoreCommands.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API

Applied to files:

  • src/composables/useCoreCommands.ts
  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue OverlayPanel component with Popover

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Sidebar component with Drawer

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Calendar component with DatePicker

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.vue : Avoid new usage of PrimeVue components

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue TabMenu component with Tabs without panels

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Implement lifecycle hooks with onMounted, onUpdated, etc.

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use setup() function in Vue 3 Composition API

Applied to files:

  • src/components/topbar/CurrentUserPopover.vue
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{services,composables}/**/*.{ts,tsx} : Use `api.fileURL()` for static file access instead of constructing URLs directly

Applied to files:

  • src/composables/auth/useFirebaseAuthActions.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Implement proper error handling

Applied to files:

  • src/composables/auth/useFirebaseAuthActions.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Always prefer vitest mock functions over writing verbose manual mocks

Applied to files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Use existing test utilities rather than writing custom utilities

Applied to files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Follow existing test patterns in the codebase

Applied to files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/*.{ts,vue} : Write tests for all changes, especially bug fixes to catch future regressions

Applied to files:

  • tests-ui/tests/composables/useCoreCommands.test.ts
📚 Learning: 2025-12-06T00:52:35.750Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T00:52:35.750Z
Learning: Applies to **/composables/**/use*.ts : Name composables with `useXyz.ts` pattern

Applied to files:

  • src/platform/cloud/subscription/composables/useSubscription.ts
🧬 Code graph analysis (8)
src/scripts/app.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/services/dialogService.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/composables/useCoreCommands.ts (3)
tests-ui/tests/renderer/extensions/vueNodes/widgets/composables/useRemoteWidget.test.ts (1)
  • isCloud (34-36)
tests-ui/tests/renderer/extensions/vueNodes/widgets/composables/useComboWidget.test.ts (1)
  • isCloud (44-46)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/composables/auth/useFirebaseAuthActions.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
src/extensions/core/cloudRemoteConfig.ts (1)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • useSubscription (244-244)
tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts (1)
src/extensions/core/load3d/Load3d.ts (1)
  • isActive (383-391)
src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (2)
src/platform/cloud/subscription/composables/useSubscription.ts (1)
  • CloudSubscriptionStatusResponse (23-28)
src/platform/telemetry/types.ts (1)
  • TelemetryProvider (259-328)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: test
  • GitHub Check: setup
  • GitHub Check: collect
  • GitHub Check: lint-and-format
🔇 Additional comments (15)
src/components/topbar/CurrentUserPopover.test.ts (1)

81-88: Mock shape for isSubscriptionRequirementMet is correct

Returning { value: true } keeps the mock ref‑like and aligned with the real useSubscription API, so isSubscriptionRequirementMet.value usage in the component will behave as expected.

tests-ui/tests/composables/useCoreCommands.test.ts (1)

101-106: useSubscription mock now matches ref-like contract

Mocking isSubscriptionRequirementMet as { value: true } aligns with the composable’s ref/computed API and fixes the earlier mismatch where a function was returned.

tests-ui/tests/platform/cloud/subscription/useSubscriptionCancellationWatcher.test.ts (1)

27-36: Watcher tests correctly adapted to isSubscriptionRequirementMet

Wrapping isActive in a computed isSubscriptionRequirementMet and passing it into useSubscriptionCancellationWatcher keeps the tests reactive while matching the new option name and shape.

Also applies to: 77-83, 107-113, 129-135, 153-160

src/extensions/core/cloudRemoteConfig.ts (1)

16-27: Remote config watcher correctly tracks new subscription flag

Using { isSubscriptionRequirementMet } = useSubscription() and adding it to the watchDebounced sources keeps the logic functionally the same (guarding on isLoggedIn) while ensuring remote config refreshes when subscription state changes.

src/scripts/app.ts (1)

668-691: Payment‑required handling correctly gated by environment and subscription

The new branch:

  • Keeps local behavior unchanged (!isCloud always shows the Top Up dialog).
  • In cloud, only shows the Top Up dialog when isSubscriptionRequirementMet.value is true, avoiding offering credits when the subscription requirement isn’t met.

This is consistent with the updated subscription semantics and cloud‑aware gating elsewhere in the codebase.

src/components/actionbar/ComfyRunButton/CloudRunButtonWrapper.vue (1)

2-5: Cloud run button wrapper correctly migrated to isSubscriptionRequirementMet

Using isSubscriptionRequirementMet for both the key and currentButton selection cleanly switches between queue vs subscribe buttons while preserving reactivity (.value in script, unwrapped in template).

Also applies to: 14-18

src/platform/cloud/subscription/components/SubscribeButton.vue (1)

54-55: Subscription flag rename is correctly wired into polling flow

Using isSubscriptionRequirementMet from useSubscription() and checking it in the polling loop preserves the previous semantics while aligning with the new API; stop, telemetry, and subscribed emission all remain correctly gated on the requirement being met.

Also applies to: 80-84

src/composables/auth/useFirebaseAuthActions.ts (1)

83-90: Dynamic cloud‑scoped subscription check before credit purchase

Moving useSubscription into an isCloud‑guarded dynamic import and short‑circuiting when !isSubscriptionRequirementMet.value cleanly enforces subscription requirements for credit purchases while avoiding initialization of the subscription composable in local builds; non‑cloud behavior remains unchanged.

src/components/dialog/content/setting/CreditsPanel.vue (1)

18-23: Computed cloud‑aware isSubscriptionRequirementMet cleanly gates the purchase button

Deriving subscription only when isCloud and using a computed isSubscriptionRequirementMet (true for non‑cloud, otherwise mirroring the composable’s flag) ensures the “Purchase credits” button is only shown when the subscription requirement is satisfied, while keeping local environments unaffected and avoiding unnecessary subscription initialization.

Also applies to: 128-152

src/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher.ts (1)

13-19: Cancellation watcher correctly switched to isSubscriptionRequirementMet

Updating the options type, destructuring, and cancellation condition to use isSubscriptionRequirementMet keeps the watcher behavior consistent with the composable’s renamed API and removes the earlier unused legacy flag from the surface.

Also applies to: 21-27, 76-88

src/components/topbar/CurrentUserPopover.vue (1)

26-55: Cloud‑aware subscription gating in popover is consistent and safe

Guarding useSubscription() behind isCloud and exposing isSubscriptionRequirementMet with a computed true fallback ensures the popover only initializes subscription logic in cloud builds, cleanly switches between credits UI and SubscribeButton, and keeps handleSubscribed safe via a noop fetchStatus when subscription is unavailable.

Also applies to: 73-75, 124-132

tests-ui/tests/platform/cloud/subscription/useSubscription.test.ts (1)

95-110: Tests correctly validate isSubscriptionRequirementMet for active vs inactive states

Switching the expectations to isSubscriptionRequirementMet.value in both the active and inactive scenarios preserves the intent of the tests and keeps them aligned with the updated useSubscription API.

Also applies to: 112-127

src/composables/useCoreCommands.ts (1)

1-2: Subscription gating for queue commands via subscriptionState/subscriptionDialog is well-structured

Using isCloud ? useSubscription() : null with a defaultSubscriptionState = computed(() => true) and a noop dialog cleanly avoids initializing the shared subscription composable on local builds, while the new subscriptionState.value checks in the three queue commands correctly gate execution and invoke the subscription dialog when requirements aren’t met.

Also applies to: 24-25, 51-52, 69-71, 92-96, 477-497, 500-521, 523-566

src/platform/cloud/subscription/components/SubscriptionPanel.vue (1)

7-10: isSubscriptionRequirementMet rename is correctly propagated through the panel

All subscription‑gated template branches and the useSubscription destructuring have been updated to use isSubscriptionRequirementMet, keeping the UI logic consistent with the composable’s new API without altering behavior.

Also applies to: 30-47, 50-71, 199-212, 322-330

src/platform/cloud/subscription/composables/useSubscription.ts (1)

34-38: New isSubscriptionRequirementMet computed cleanly models “required or already subscribed”

The computed correctly returns true when subscription checks don’t apply (non‑cloud or subscription_required is falsy) and mirrors the previous semantics when they do. Wiring it into useSubscriptionCancellationWatcher and exposing it in the returned state keeps internal logic and public API aligned with the rename.

Also applies to: 111-118, 224-241

Comment on lines +39 to 41
const handleAddApiCredits = async () => {
await dialogService.showTopUpCreditsDialog()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider adding error handling around async top‑up dialog

Making handleAddApiCredits async and awaiting showTopUpCreditsDialog is fine for click handlers, but unlike handleMessageSupport/handleRefresh it doesn’t guard against rejections. For consistency and robustness you could wrap it:

- const handleAddApiCredits = async () => {
-   await dialogService.showTopUpCreditsDialog()
- }
+ const handleAddApiCredits = async () => {
+   try {
+     await dialogService.showTopUpCreditsDialog()
+   } catch (error) {
+     console.error(
+       '[useSubscriptionActions] Error opening top-up dialog:',
+       error
+     )
+   }
+ }

Not required for correctness, but aligns with the rest of this composable’s error‑handling pattern.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleAddApiCredits = async () => {
await dialogService.showTopUpCreditsDialog()
}
const handleAddApiCredits = async () => {
try {
await dialogService.showTopUpCreditsDialog()
} catch (error) {
console.error(
'[useSubscriptionActions] Error opening top-up dialog:',
error
)
}
}
🤖 Prompt for AI Agents
In src/platform/cloud/subscription/composables/useSubscriptionActions.ts around
lines 39 to 41, handleAddApiCredits calls and awaits
dialogService.showTopUpCreditsDialog but lacks error handling; wrap the await in
a try/catch (matching the pattern used by handleMessageSupport/handleRefresh),
log the error or surface it to dialogService/processLogger as appropriate, and
ensure any caught error resets any local state or rethrows if needed to preserve
existing behavior.

Comment on lines +379 to +388
async function showTopUpCreditsDialog(options?: {
isInsufficientCredits?: boolean
}) {
const { isActiveSubscription } = useSubscription()
if (!isActiveSubscription.value) return
if (isCloud) {
const { useSubscription } = await import(
'@/platform/cloud/subscription/composables/useSubscription'
)
const { isSubscriptionRequirementMet } = useSubscription()
if (!isSubscriptionRequirementMet.value) return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg -n "showTopUpCreditsDialog" src

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 999


🏁 Script executed:

# Check app.ts context around lines 680, 686
sed -n '675,695n' src/scripts/app.ts

# Check CurrentUserPopover.vue context around line 151
sed -n '145,160n' src/components/topbar/CurrentUserPopover.vue

# Check CreditsPanel.vue context around line 176
sed -n '170,185n' src/components/dialog/content/setting/CreditsPanel.vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 52


🏁 Script executed:

# Check app.ts around lines 680, 686
cat -n src/scripts/app.ts | sed -n '675,695p'

# Check CurrentUserPopover.vue around line 151
cat -n src/components/topbar/CurrentUserPopover.vue | sed -n '145,160p'

# Check CreditsPanel.vue around line 176
cat -n src/components/dialog/content/setting/CreditsPanel.vue | sed -n '170,185p'

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1916


🏁 Script executed:

# Read the full showTopUpCreditsDialog function from dialogService.ts
sed -n '379,430p' src/services/dialogService.ts | cat -n

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 2060


🏁 Script executed:

# Find dialogStore and its showDialog method
rg -n "showDialog" src/stores/dialogStore.ts -A 5 | head -40

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 442


🏁 Script executed:

# Check the full showDialog implementation
sed -n '212,245p' src/stores/dialogStore.ts | cat -n

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1404


Add await to showTopUpCreditsDialog calls to ensure subscription requirement check completes before dialog opens

The function is now async with a subscription requirement check in the cloud path (lines 384-387), but four call sites invoke it without await: lines 680 and 686 in src/scripts/app.ts, line 151 in src/components/topbar/CurrentUserPopover.vue, and line 176 in src/components/dialog/content/setting/CreditsPanel.vue. Without awaiting, the subscription requirement check may not complete before the dialog opens, bypassing the intended gate for cloud users. Update these fire-and-forget calls to await dialogService.showTopUpCreditsDialog() (line 40 in src/platform/cloud/subscription/composables/useSubscriptionActions.ts already does this correctly).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:cloud size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants