Skip to content

Conversation

@christian-byrne
Copy link
Contributor

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

Summary

Show in comfy credits

┆Issue is synchronized with this Notion page by Unito

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 13, 2025

📝 Walkthrough

Walkthrough

Refactored credit/pricing formatting in the node pricing composable by introducing centralized helper functions (formatCreditsLabel, formatCreditsRangeLabel, formatCreditsListLabel) and a safe execution wrapper, then replaced scattered hard-coded price strings throughout the dynamic and static pricing logic with these new utilities.

Changes

Cohort / File(s) Summary
Core pricing formatting utilities
src/composables/node/useNodePricing.ts
Introduced new formatting utilities (DEFAULT_NUMBER_OPTIONS, CreditFormatOptions, formatCreditsValue, makePrefix, makeSuffix, appendNote) and high-level formatters (formatCreditsLabel, formatCreditsRangeLabel, formatCreditsListLabel). Added safePricingExecution wrapper for error handling in pricing computations. Replaced all hard-coded price strings in dynamic pricing paths (calculateRunwayDurationPrice, makeOmniProDurationCalculator, pixversePricingCalculator, ltxvPricingCalculator, token-based pricing) and static configurations with the new formatting helpers.
Pricing tests
tests-ui/tests/composables/node/useNodePricing.test.ts
Updated test assertions to use new formatting helpers (creditsLabel, creditsRangeLabel, creditsListLabel) instead of static price strings. Introduced test-only utilities that produce expected formatted outputs using formatCreditsFromUsd. Updated all test cases covering static/dynamic pricing paths, ranges, per-second variants, and token/output pricing.

Possibly related PRs

✨ 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 node-pricing-credits

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.

@github-actions
Copy link

github-actions bot commented Dec 13, 2025

🎨 Storybook Build Status

Build completed successfully!

⏰ Completed at: 12/13/2025, 12:08:03 PM UTC

🔗 Links


🎉 Your Storybook is ready for review!

@github-actions
Copy link

github-actions bot commented Dec 13, 2025

🎭 Playwright Test Results

⚠️ Tests passed with flaky tests

⏰ Completed at: 12/13/2025, 12:16:52 PM UTC

📈 Summary

  • Total Tests: 504
  • Passed: 492 ✅
  • Failed: 0
  • Flaky: 3 ⚠️
  • Skipped: 9 ⏭️

📊 Test Reports by Browser

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

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

@github-actions
Copy link

Bundle Size Report

Summary

  • Raw size: 17.1 MB baseline 17.1 MB — 🔴 +8.74 kB
  • Gzip: 3.39 MB baseline 3.39 MB — 🔴 +639 B
  • Brotli: 2.6 MB baseline 2.6 MB — 🔴 +545 B
  • Bundles: 97 current • 97 baseline • 39 added / 39 removed

Category Glance
Graph Workspace 🔴 +8.71 kB (994 kB) · App Entry Points 🔴 +30 B (3.24 MB) · Vendor & Third-Party ⚪ 0 B (8.56 MB) · Other ⚪ 0 B (3.81 MB) · Panels & Settings ⚪ 0 B (298 kB) · UI Components ⚪ 0 B (178 kB) · + 3 more

Per-category breakdown
App Entry Points — 3.24 MB (baseline 3.24 MB) • 🔴 +30 B

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-CPwU7Hvf.js (new) 3.02 MB 🔴 +3.02 MB 🔴 +627 kB 🔴 +477 kB
assets/index-CtLncRtg.js (removed) 3.02 MB 🟢 -3.02 MB 🟢 -627 kB 🟢 -477 kB
assets/index-BWyJ4qpi.js (removed) 227 kB 🟢 -227 kB 🟢 -48.6 kB 🟢 -39.8 kB
assets/index-RcsuvEs2.js (new) 227 kB 🔴 +227 kB 🔴 +48.6 kB 🔴 +39.8 kB
assets/index-Du-K1fqI.js (new) 345 B 🔴 +345 B 🔴 +246 B 🔴 +232 B
assets/index-EaBrhMxi.js (removed) 345 B 🟢 -345 B 🟢 -241 B 🟢 -200 B

Status: 3 added / 3 removed

Graph Workspace — 994 kB (baseline 985 kB) • 🔴 +8.71 kB

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-BNXoH3g7.js (new) 994 kB 🔴 +994 kB 🔴 +191 kB 🔴 +146 kB
assets/GraphView-DESgvpoF.js (removed) 985 kB 🟢 -985 kB 🟢 -191 kB 🟢 -145 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-CjUISDp7.js (removed) 6.54 kB 🟢 -6.54 kB 🟢 -2.14 kB 🟢 -1.89 kB
assets/UserSelectView-D9sUO6uO.js (new) 6.54 kB 🔴 +6.54 kB 🔴 +2.14 kB 🔴 +1.89 kB

Status: 1 added / 1 removed

Panels & Settings — 298 kB (baseline 298 kB) • ⚪ 0 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/LegacyCreditsPanel-BIaVe1j8.js (removed) 21.4 kB 🟢 -21.4 kB 🟢 -5.15 kB 🟢 -4.5 kB
assets/LegacyCreditsPanel-Dog39RAi.js (new) 21.4 kB 🔴 +21.4 kB 🔴 +5.15 kB 🔴 +4.5 kB
assets/KeybindingPanel-AzLVKe2E.js (removed) 13.6 kB 🟢 -13.6 kB 🟢 -3.42 kB 🟢 -3.01 kB
assets/KeybindingPanel-F9i1MBvy.js (new) 13.6 kB 🔴 +13.6 kB 🔴 +3.42 kB 🔴 +3.01 kB
assets/ExtensionPanel-DsVrdgPR.js (removed) 10.8 kB 🟢 -10.8 kB 🟢 -2.57 kB 🟢 -2.26 kB
assets/ExtensionPanel-yam7F02W.js (new) 10.8 kB 🔴 +10.8 kB 🔴 +2.57 kB 🔴 +2.26 kB
assets/AboutPanel-BV3z-Sd8.js (removed) 9.16 kB 🟢 -9.16 kB 🟢 -2.46 kB 🟢 -2.21 kB
assets/AboutPanel-C92oPipq.js (new) 9.16 kB 🔴 +9.16 kB 🔴 +2.46 kB 🔴 +2.21 kB
assets/ServerConfigPanel-B3BNp_WL.js (new) 6.56 kB 🔴 +6.56 kB 🔴 +1.83 kB 🔴 +1.63 kB
assets/ServerConfigPanel-CKtPvzpt.js (removed) 6.56 kB 🟢 -6.56 kB 🟢 -1.83 kB 🟢 -1.63 kB
assets/UserPanel-CENxTdsM.js (removed) 6.23 kB 🟢 -6.23 kB 🟢 -1.72 kB 🟢 -1.51 kB
assets/UserPanel-HHH8Gl64.js (new) 6.23 kB 🔴 +6.23 kB 🔴 +1.72 kB 🔴 +1.5 kB
assets/settings-B_sqawkt.js 27.3 kB 27.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BhbWhsRg.js 101 B 101 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BlDXT7wp.js 21.7 kB 21.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-Bz8HAvJu.js 21.1 kB 21.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-C2vW8UNv.js 24.2 kB 24.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-C9vsDM17.js 25.1 kB 25.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DWD49kQp.js 33.3 kB 33.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DZE27_Iz.js 25.9 kB 25.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-OXaZPcZF.js 26.6 kB 26.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-RbkKsnDG.js 25.2 kB 25.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 6 added / 6 removed

UI Components — 178 kB (baseline 178 kB) • ⚪ 0 B

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/Load3D.vue_vue_type_script_setup_true_lang-CagY7rMf.js (new) 53.7 kB 🔴 +53.7 kB 🔴 +8.49 kB 🔴 +7.3 kB
assets/Load3D.vue_vue_type_script_setup_true_lang-CEyz60a2.js (removed) 53.7 kB 🟢 -53.7 kB 🟢 -8.49 kB 🟢 -7.29 kB
assets/WidgetSelect.vue_vue_type_script_setup_true_lang-brXdE0o2.js (removed) 48.1 kB 🟢 -48.1 kB 🟢 -10.4 kB 🟢 -8.99 kB
assets/WidgetSelect.vue_vue_type_script_setup_true_lang-BZxhD7f3.js (new) 48.1 kB 🔴 +48.1 kB 🔴 +10.4 kB 🔴 +8.99 kB
assets/LazyImage.vue_vue_type_script_setup_true_lang-C9N7tfSQ.js (removed) 48 kB 🟢 -48 kB 🟢 -10.6 kB 🟢 -9.32 kB
assets/LazyImage.vue_vue_type_script_setup_true_lang-CftyBWI_.js (new) 48 kB 🔴 +48 kB 🔴 +10.6 kB 🔴 +9.32 kB
assets/WidgetInputNumber.vue_vue_type_script_setup_true_lang-C6CcCvFZ.js (new) 12.9 kB 🔴 +12.9 kB 🔴 +3.37 kB 🔴 +2.96 kB
assets/WidgetInputNumber.vue_vue_type_script_setup_true_lang-DXmg7_k4.js (removed) 12.9 kB 🟢 -12.9 kB 🟢 -3.37 kB 🟢 -2.98 kB
assets/ComfyQueueButton-BRWFM9Qn.js (removed) 8.44 kB 🟢 -8.44 kB 🟢 -2.48 kB 🟢 -2.22 kB
assets/ComfyQueueButton-BVrb9umo.js (new) 8.44 kB 🔴 +8.44 kB 🔴 +2.48 kB 🔴 +2.21 kB
assets/WidgetLayoutField.vue_vue_type_script_setup_true_lang-aOiY3aCG.js (new) 2.15 kB 🔴 +2.15 kB 🔴 +897 B 🔴 +768 B
assets/WidgetLayoutField.vue_vue_type_script_setup_true_lang-COj6XUUj.js (removed) 2.15 kB 🟢 -2.15 kB 🟢 -897 B 🟢 -768 B
assets/MediaTitle.vue_vue_type_script_setup_true_lang-BariaGQm.js (removed) 897 B 🟢 -897 B 🟢 -500 B 🟢 -432 B
assets/MediaTitle.vue_vue_type_script_setup_true_lang-BLy8KvdN.js (new) 897 B 🔴 +897 B 🔴 +504 B 🔴 +446 B
assets/UserAvatar.vue_vue_type_script_setup_true_lang-Bjfb_hoW.js 1.34 kB 1.34 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetButton-Bm2lwPFd.js 2.04 kB 2.04 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 7 added / 7 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-BxJA_z2Q.js (new) 7.51 kB 🔴 +7.51 kB 🔴 +1.84 kB 🔴 +1.58 kB
assets/keybindingService-qJCUdWkx.js (removed) 7.51 kB 🟢 -7.51 kB 🟢 -1.83 kB 🟢 -1.58 kB
assets/audioService-DcUla7yD.js (new) 2.2 kB 🔴 +2.2 kB 🔴 +962 B 🔴 +829 B
assets/audioService-DTgCxhhP.js (removed) 2.2 kB 🟢 -2.2 kB 🟢 -959 B 🟢 -829 B
assets/serverConfigStore-BP9UaJXd.js 2.83 kB 2.83 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 2 added / 2 removed

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

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/audioUtils-D_4KkRdG.js (removed) 1.41 kB 🟢 -1.41 kB 🟢 -650 B 🟢 -542 B
assets/audioUtils-Yfbqde8u.js (new) 1.41 kB 🔴 +1.41 kB 🔴 +651 B 🔴 +551 B
assets/mathUtil-CD4DsosH.js 1.32 kB 1.32 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-chart-W_3Knk2t.js 452 kB 452 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-other-BzuNIfYH.js 3.98 MB 3.98 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-primevue-CmhMHYBF.js 1.96 MB 1.96 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-three-aR6ntw5X.js 1.37 MB 1.37 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-tiptap-DCLYW5rb.js 232 kB 232 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vue-C3MDzIsc.js 160 kB 160 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-xterm-BZLod3g9.js 407 kB 407 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Other — 3.81 MB (baseline 3.81 MB) • ⚪ 0 B

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/WidgetRecordAudio-BcOFZuBF.js (new) 20.4 kB 🔴 +20.4 kB 🔴 +5.23 kB 🔴 +4.63 kB
assets/WidgetRecordAudio-C6YNC7eo.js (removed) 20.4 kB 🟢 -20.4 kB 🟢 -5.23 kB 🟢 -4.63 kB
assets/AudioPreviewPlayer-B4hKeUfo.js (removed) 13.4 kB 🟢 -13.4 kB 🟢 -3.37 kB 🟢 -3.02 kB
assets/AudioPreviewPlayer-CWRxeIa1.js (new) 13.4 kB 🔴 +13.4 kB 🔴 +3.37 kB 🔴 +3.01 kB
assets/WidgetGalleria-BADvyW_z.js (removed) 4.1 kB 🟢 -4.1 kB 🟢 -1.44 kB 🟢 -1.3 kB
assets/WidgetGalleria-DtVz7Ub3.js (new) 4.1 kB 🔴 +4.1 kB 🔴 +1.45 kB 🔴 +1.3 kB
assets/WidgetColorPicker-DaSsK7ky.js (removed) 3.41 kB 🟢 -3.41 kB 🟢 -1.38 kB 🟢 -1.24 kB
assets/WidgetColorPicker-qxNgA57t.js (new) 3.41 kB 🔴 +3.41 kB 🔴 +1.38 kB 🔴 +1.23 kB
assets/WidgetTextarea-Ce6gMNps.js (removed) 3.08 kB 🟢 -3.08 kB 🟢 -1.21 kB 🟢 -1.08 kB
assets/WidgetTextarea-COa4ZoBq.js (new) 3.08 kB 🔴 +3.08 kB 🔴 +1.21 kB 🔴 +1.08 kB
assets/WidgetMarkdown-bniWjvMy.js (new) 3.08 kB 🔴 +3.08 kB 🔴 +1.28 kB 🔴 +1.12 kB
assets/WidgetMarkdown-Cg0qylZB.js (removed) 3.08 kB 🟢 -3.08 kB 🟢 -1.28 kB 🟢 -1.13 kB
assets/WidgetAudioUI-188xbvpA.js (removed) 2.86 kB 🟢 -2.86 kB 🟢 -1.16 kB 🟢 -1.05 kB
assets/WidgetAudioUI-Xgfci7pV.js (new) 2.86 kB 🔴 +2.86 kB 🔴 +1.17 kB 🔴 +1.06 kB
assets/WidgetInputText-AJjKc0nD.js (new) 1.99 kB 🔴 +1.99 kB 🔴 +920 B 🔴 +850 B
assets/WidgetInputText-CsV49T0c.js (removed) 1.99 kB 🟢 -1.99 kB 🟢 -916 B 🟢 -851 B
assets/WidgetToggleSwitch-CEWSsrI9.js (removed) 1.76 kB 🟢 -1.76 kB 🟢 -831 B 🟢 -736 B
assets/WidgetToggleSwitch-xXqDX3Ya.js (new) 1.76 kB 🔴 +1.76 kB 🔴 +833 B 🔴 +732 B
assets/MediaImageBottom-BgohU7fa.js (new) 1.55 kB 🔴 +1.55 kB 🔴 +737 B 🔴 +643 B
assets/MediaImageBottom-D5A5e2sv.js (removed) 1.55 kB 🟢 -1.55 kB 🟢 -734 B 🟢 -641 B
assets/MediaAudioBottom-B4gc93s_.js (new) 1.51 kB 🔴 +1.51 kB 🔴 +735 B 🔴 +651 B
assets/MediaAudioBottom-CPy7CrBr.js (removed) 1.51 kB 🟢 -1.51 kB 🟢 -731 B 🟢 -651 B
assets/Media3DBottom-3nsXIKhD.js (removed) 1.5 kB 🟢 -1.5 kB 🟢 -734 B 🟢 -654 B
assets/Media3DBottom-kp3fVCZK.js (new) 1.5 kB 🔴 +1.5 kB 🔴 +734 B 🔴 +652 B
assets/MediaVideoBottom-BDanNvvM.js (new) 1.5 kB 🔴 +1.5 kB 🔴 +733 B 🔴 +650 B
assets/MediaVideoBottom-BRDfzTlq.js (removed) 1.5 kB 🟢 -1.5 kB 🟢 -734 B 🟢 -649 B
assets/Media3DTop-CxXnnQ4E.js (new) 1.49 kB 🔴 +1.49 kB 🔴 +766 B 🔴 +653 B
assets/Media3DTop-DrnAmwzn.js (removed) 1.49 kB 🟢 -1.49 kB 🟢 -763 B 🟢 -653 B
assets/WidgetSelect-CNd6-e6h.js (new) 655 B 🔴 +655 B 🔴 +341 B 🔴 +287 B
assets/WidgetSelect-DVgMq3zq.js (removed) 655 B 🟢 -655 B 🟢 -342 B 🟢 -286 B
assets/WidgetInputNumber-C4NAWr98.js (new) 595 B 🔴 +595 B 🔴 +330 B 🔴 +281 B
assets/WidgetInputNumber-DhQmX4-3.js (removed) 595 B 🟢 -595 B 🟢 -328 B 🟢 -276 B
assets/Load3D-DA2vK-au.js (new) 424 B 🔴 +424 B 🔴 +266 B 🔴 +225 B
assets/Load3D-DIpC76F2.js (removed) 424 B 🟢 -424 B 🟢 -265 B 🟢 -222 B
assets/WidgetLegacy-C1Q4oZXu.js (new) 364 B 🔴 +364 B 🔴 +237 B 🔴 +225 B
assets/WidgetLegacy-DTDVSSHF.js (removed) 364 B 🟢 -364 B 🟢 -235 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-BMi-Aksj.js 99 kB 99 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CqR8skJT.js 73.1 kB 73.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Cw9RZWRY.js 89 B 89 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DcRHAFEy.js 81.7 kB 81.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DdFdLxku.js 72.2 kB 72.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DJAtuVu5.js 84.3 kB 84.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DK8I9Rk3.js 114 kB 114 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-gP_ssnMb.js 83.4 kB 83.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-nxXY9vGp.js 94 kB 94 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Ycd3gqkA.js 86.5 kB 86.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaAudioTop-taU5Yj_Q.js 1.46 kB 1.46 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaImageTop-BoT3yC-l.js 1.75 kB 1.75 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaVideoTop-Csf8f_9c.js 2.65 kB 2.65 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-_qLI3Y-X.js 317 kB 317 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BoBMp_wf.js 307 kB 307 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Bw_Jitw_.js 101 B 101 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Ce9u3PlO.js 342 kB 342 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CgjGEDDp.js 285 kB 285 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CL3A8ieS.js 306 kB 306 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DNUc-sw4.js 303 kB 303 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DxUbhTnC.js 282 kB 282 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-i8mv_3Jj.js 369 kB 369 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-wCFicyab.js 310 kB 310 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetChart-CWEwKtMY.js 2.48 kB 2.48 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetImageCompare-DSf2ZEwg.js 2.21 kB 2.21 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetPropFilter-BIbGSUAt.js 1.28 kB 1.28 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 18 added / 18 removed

@christian-byrne
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 13, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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 (5)
src/composables/node/useNodePricing.ts (4)

64-82: Fix env-check in safePricingExecution: process.env may be undefined in the browser/Vite, causing the catch-path to throw again.

If a pricing function throws, the catch block can itself throw (e.g., process is not defined), defeating the fallback and potentially breaking rendering.

 function safePricingExecution(
   fn: PricingFunction,
   node: LGraphNode,
   fallback: string = ''
 ): string {
   try {
     return fn(node)
   } catch (error) {
     // Log error in development but don't throw to avoid breaking node rendering
-    if (process.env.NODE_ENV === 'development') {
+    if (import.meta.env.DEV) {
       console.warn(
         'Pricing calculation failed for node:',
         node.constructor?.nodeData?.name,
         error
       )
     }
     return fallback
   }
 }

89-101: Comment/logic mismatch around NaN duration in calculateRunwayDurationPrice.

Line 97 says “If duration is 0 or NaN … use 0”, but Line 98 explicitly falls back NaN to 5 seconds (isNaN(duration) ? 5 : duration). Either update the comment or change the behavior (tests appear to expect the 5s fallback).


182-243: Guard invalid/negative duration to avoid NaN credits/Run in ByteDance video pricing.

seconds (Line 197) can be NaN/Infinity/negative; the function will currently flow into formatCreditsRangeLabel(minCost, maxCost) and can display NaN to users.

   const model = String(modelWidget.value).toLowerCase()
   const resolution = String(resolutionWidget.value).toLowerCase()
-  const seconds = parseFloat(String(durationWidget.value))
+  const seconds = parseFloat(String(durationWidget.value))
+  if (!Number.isFinite(seconds) || seconds < 0) return 'Token-based'
   const priceByModel: Record<string, Record<string, [number, number]>> = {
     'seedance-1-0-pro': {
       '480p': [0.23, 0.24],
       '720p': [0.51, 0.56],
       '1080p': [1.18, 1.22]
     },
     ...
   }

(Also: you can drop the minCost === maxCost early return (Lines 241-242); formatCreditsRangeLabel already collapses when formatted min==max.)


245-285: Guard invalid duration in ltxvPricingCalculator to avoid NaN credits/Run.

seconds (Line 263) is not validated; pps * seconds can become NaN.

   const model = String(modelWidget.value).toLowerCase()
   const resolution = String(resolutionWidget.value).toLowerCase()
   const seconds = parseFloat(String(durationWidget.value))
+  if (!Number.isFinite(seconds) || seconds < 0) return fallback
   const priceByModel: Record<string, Record<string, number>> = {
     'ltx-2 (pro)': {
       '1920x1080': 0.06,
       '2560x1440': 0.12,
       '3840x2160': 0.24
     },
     ...
   }
tests-ui/tests/composables/node/useNodePricing.test.ts (1)

290-321: Fix stale test titles that still claim USD amounts (and one is numerically wrong).

Example: “should return $0.16 for 1792x1024 hd quality” (Line 290) asserts creditsLabel(0.12) (Line 298). The title should match the asserted pricing (and ideally stop referencing $ if the UI is now credits).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aab9a30 and 6e50933.

📒 Files selected for processing (2)
  • src/composables/node/useNodePricing.ts (67 hunks)
  • tests-ui/tests/composables/node/useNodePricing.test.ts (136 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
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/node/useNodePricing.ts
src/**/*.ts

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

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

Minimize the surface area (exported values) of each module and composable

Files:

  • src/composables/node/useNodePricing.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/node/useNodePricing.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/node/useNodePricing.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/node/useNodePricing.ts
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/composables/node/useNodePricing.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/node/useNodePricing.ts
src/composables/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Composable files must follow the naming pattern useXyz.ts

Files:

  • src/composables/node/useNodePricing.ts
**/*.{ts,tsx,js,jsx,vue,json}

📄 CodeRabbit inference engine (AGENTS.md)

Code style: Use 2-space indentation, single quotes, no trailing semicolons, and 80-character line width (see .prettierrc)

Files:

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

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Imports must be sorted and grouped by plugin; run pnpm format before committing
Use TypeScript for type safety; never use any type - use proper TypeScript types
Never use as any type assertions; fix the underlying type issue instead
Use es-toolkit for utility functions
Write code that is expressive and self-documenting; avoid comments unless absolutely necessary; do not add or retain redundant comments
Keep functions short and functional
Minimize nesting in code (e.g., deeply nested if or for statements); apply the Arrow Anti-Pattern principle
Avoid mutable state; prefer immutability and assignment at point of declaration
Favor pure functions, especially testable ones

Files:

  • src/composables/node/useNodePricing.ts
  • tests-ui/tests/composables/node/useNodePricing.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/composables/node/useNodePricing.test.ts
**/*.test.ts

📄 CodeRabbit inference engine (AGENTS.md)

**/*.test.ts: Write tests for all changes, especially bug fixes to catch future regressions
Unit/component test files must be named **/*.test.ts or in tests-ui/ directory
Do not write change detector tests that just assert default values
Do not write tests dependent on non-behavioral features like utility classes or styles
Be parsimonious in testing; do not write redundant tests; see composable tests approach
Follow 'Don't Mock What You Don't Own' principle - avoid mocking external dependencies
Do not write tests that just test the mocks; ensure tests fail when code behaves unexpectedly
Leverage Vitest's mocking utilities where possible for test mocking
Keep module mocks contained in test files; do not use global mutable state within test files; use vi.hoisted() if necessary
For Component testing, use Vue Test Utils and follow advice about making components easy to test
Aim for behavioral coverage of critical and new features in unit tests

Files:

  • tests-ui/tests/composables/node/useNodePricing.test.ts
🧠 Learnings (18)
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.

Applied to files:

  • src/composables/node/useNodePricing.ts
  • tests-ui/tests/composables/node/useNodePricing.test.ts
📚 Learning: 2025-12-13T11:03:11.264Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7416
File: src/stores/imagePreviewStore.ts:5-7
Timestamp: 2025-12-13T11:03:11.264Z
Learning: In the ComfyUI_frontend repository, lint rules require keeping 'import type' statements separate from non-type imports, even if importing from the same module. Do not suggest consolidating them into a single import statement. Ensure type imports remain on their own line (import type { ... } from 'module') and regular imports stay on separate lines.

Applied to files:

  • src/composables/node/useNodePricing.ts
  • tests-ui/tests/composables/node/useNodePricing.test.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.

Applied to files:

  • src/composables/node/useNodePricing.ts
  • tests-ui/tests/composables/node/useNodePricing.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/composables/node/useNodePricing.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/node/useNodePricing.test.ts
📚 Learning: 2025-12-09T20:22:23.620Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : Write tests for all changes, especially bug fixes to catch future regressions

Applied to files:

  • tests-ui/tests/composables/node/useNodePricing.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/node/useNodePricing.test.ts
📚 Learning: 2025-12-09T20:22:23.620Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : Be parsimonious in testing; do not write redundant tests; see composable tests approach

Applied to files:

  • tests-ui/tests/composables/node/useNodePricing.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/node/useNodePricing.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} : Use `test` instead of `it` for defining test cases in vitest

Applied to files:

  • tests-ui/tests/composables/node/useNodePricing.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/composables/node/useNodePricing.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} : Use `vitest` for unit testing in this project

Applied to files:

  • tests-ui/tests/composables/node/useNodePricing.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}.{js,ts,jsx,tsx} : When adding features, always write vitest unit tests using cursor rules in @.cursor

Applied to files:

  • tests-ui/tests/composables/node/useNodePricing.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} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`

Applied to files:

  • tests-ui/tests/composables/node/useNodePricing.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} : When writing tests for subgraph-related code, always import from the barrel export at `@/lib/litegraph/src/litegraph` to avoid circular dependency issues

Applied to files:

  • tests-ui/tests/composables/node/useNodePricing.test.ts
📚 Learning: 2025-12-09T20:22:23.620Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : Leverage Vitest's mocking utilities where possible for test mocking

Applied to files:

  • tests-ui/tests/composables/node/useNodePricing.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/composables/node/useNodePricing.test.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.

Applied to files:

  • tests-ui/tests/composables/node/useNodePricing.test.ts
🧬 Code graph analysis (2)
src/composables/node/useNodePricing.ts (2)
src/base/credits/comfyCredits.ts (1)
  • formatCreditsFromUsd (84-93)
src/lib/litegraph/src/types/widgets.ts (1)
  • IComboWidget (133-140)
tests-ui/tests/composables/node/useNodePricing.test.ts (2)
src/composables/node/useNodePricing.ts (1)
  • useNodePricing (2120-2235)
src/base/credits/comfyCredits.ts (1)
  • formatCreditsFromUsd (84-93)
🔇 Additional comments (2)
tests-ui/tests/composables/node/useNodePricing.test.ts (1)

1-3: Use test instead of it in Vitest tests (repo rule).

This file imports/uses it (Line 1). Repo learnings indicate preferring test for test cases. Consider swapping imports and usage in a follow-up to match the project’s Vitest conventions. Based on learnings, prefer test over it.

⛔ Skipped due to learnings
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} : Use `test` instead of `it` for defining test cases in vitest
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} : Use `vitest` for unit testing in this project
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} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : Leverage Vitest's mocking utilities where possible for test mocking
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
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : Be parsimonious in testing; do not write redundant tests; see composable tests approach
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
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: Check tests-ui/README.md for test guidelines
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}.{js,ts,jsx,tsx} : When adding features, always write vitest unit tests using cursor rules in @.cursor
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : For Component testing, use Vue Test Utils and follow advice about making components easy to test
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
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
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
src/composables/node/useNodePricing.ts (1)

330-332: Rounding precision concern is valid, but edge case in practice. The formatRunPrice function rounds to 2 decimals before conversion to credits via usdToCredits(), which can cause slight over-rounding. Example: a product of 0.286 USD would round up to 0.29 via toFixed(2), then convert to 61 credits instead of the correct 60. However, this function is only called with pre-computed fixed values (e.g., 0.1, 0.5), so the boundary issue is unlikely to manifest. Consider either rounding after the credit conversion or adding a test case for this edge case to document intended behavior.

Comment on lines +5 to +53
const DEFAULT_NUMBER_OPTIONS: Intl.NumberFormatOptions = {
minimumFractionDigits: 0,
maximumFractionDigits: 0
}

type CreditFormatOptions = {
suffix?: string
note?: string
approximate?: boolean
separator?: string
}

const formatCreditsValue = (usd: number): string =>
formatCreditsFromUsd({
usd,
numberOptions: DEFAULT_NUMBER_OPTIONS
})

const makePrefix = (approximate?: boolean) => (approximate ? '~' : '')

const makeSuffix = (suffix?: string) => suffix ?? '/Run'

const appendNote = (note?: string) => (note ? ` ${note}` : '')

const formatCreditsLabel = (
usd: number,
{ suffix, note, approximate }: CreditFormatOptions = {}
): string =>
`${makePrefix(approximate)}${formatCreditsValue(usd)} credits${makeSuffix(suffix)}${appendNote(note)}`

const formatCreditsRangeLabel = (
minUsd: number,
maxUsd: number,
{ suffix, note, approximate }: CreditFormatOptions = {}
): string => {
const min = formatCreditsValue(minUsd)
const max = formatCreditsValue(maxUsd)
const rangeValue = min === max ? min : `${min}-${max}`
return `${makePrefix(approximate)}${rangeValue} credits${makeSuffix(suffix)}${appendNote(note)}`
}

const formatCreditsListLabel = (
usdValues: number[],
{ suffix, note, approximate, separator }: CreditFormatOptions = {}
): string => {
const parts = usdValues.map((value) => formatCreditsValue(value))
const value = parts.join(separator ?? '/')
return `${makePrefix(approximate)}${value} credits${makeSuffix(suffix)}${appendNote(note)}`
}
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

Good centralization of credit formatting; consider normalizing note the same way everywhere.

Right now appendNote(note) blindly appends ${note} (Line 27). In this PR, many call sites pass note already wrapped in parentheses, but tests also accept unwrapped notes. Consider normalizing in one place (e.g., auto-wrap when not already (…)) to keep call sites consistent and reduce future drift.

🤖 Prompt for AI Agents
In src/composables/node/useNodePricing.ts around lines 5 to 53, appendNote
currently just returns " ${note}" which allows callers to pass notes
inconsistently; change appendNote to normalize the note by trimming it, and if
non-empty wrap it in parentheses unless it already starts with '(' and ends with
')', returning a single leading space plus the normalized note (or an empty
string when note is falsy) so all formatting functions can rely on a consistent
parenthesized note.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants