-
Notifications
You must be signed in to change notification settings - Fork 477
Move price badges to python nodes #7816
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughReplaces static node pricing with a JSONata-driven runtime: adds the jsonata dependency, introduces a price_badge schema and store field, implements async compile/evaluate/caching in a new composable, and updates badge rendering to subscribe to pricingRevision and batch canvas redraws. Changes
Sequence DiagramssequenceDiagram
autonumber
participant Badge as Badge Renderer
participant Pricing as useNodePricing
participant Store as NodeDefStore
participant Cache as Compiled Rule Cache
participant Jsonata as JSONata Engine
participant UI as Canvas Renderer
Note over Badge,Pricing: getNodeDisplayPrice (fast-path vs async)
Badge->>Pricing: getNodeDisplayPrice(node)
alt cached label available
Pricing-->>Badge: return cached label
else
Pricing->>Store: fetch node definition (price_badge)
Store-->>Pricing: return price_badge
Pricing->>Cache: lookup compiled rule for node type
alt compiled rule cached
Cache-->>Pricing: compiled rule
else
Pricing->>Jsonata: compile rule.expr
Jsonata-->>Pricing: compiled rule
Pricing->>Cache: store compiled rule
end
Pricing->>Jsonata: evaluate rule with context (async)
Jsonata-->>Pricing: evaluation result
Pricing->>Pricing: format & cache display label
Pricing->>Badge: increment pricingRevision (reactive)
end
Badge->>UI: queue redraw (requestAnimationFrame)
UI->>UI: batch render on next frame
Possibly related PRs
Suggested reviewers
✨ Finishing touches
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. Comment |
|
@coderabbitai review full |
|
@DrJKL I'll perform a full review of all the changes in this PR. ✅ Actions performedFull review triggered. |
1 similar comment
|
@DrJKL I'll perform a full review of all the changes in this PR. ✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
Fix all issues with AI Agents 🤖
In @src/composables/node/useNodePricing.ts:
- Around line 408-436: In getNodeDisplayPrice, the bare read pricingTick.value
is an intentional reactive dependency for Vue but looks like a no-op; add a
short inline comment immediately above or on the same line explaining that the
read is deliberate to trigger recomputation (e.g., "intentional reactive
dependency to bump computed re-evaluation; do not remove") so future readers
won't remove it; keep the comment concise and reference pricingTick.value and
the purpose of scheduling async evaluation via scheduleEvaluation.
- Around line 336-374: Add a timeout wrapper around the JSONata evaluation so
rule._compiled.evaluate(ctx) cannot hang indefinitely: create a withTimeout
helper that races the evaluation promise against a setTimeout rejection (e.g.,
1s or configurable), then replace the current
Promise.resolve(rule._compiled.evaluate(...)) call with withTimeout(...). Ensure
the resulting promise is still stored in inflight via inflight.set(node, { sig,
promise }) and that the existing .catch and .finally logic that updates cache,
desiredSig checks, and increments pricingTick.value handles timeout rejections
the same as other errors (i.e., log in development and cache an empty label for
the same sig).
- Around line 166-170: Remove the explicit any in the filter callback so
TypeScript infers the input type from node.inputs; update the connectedCount
computation to use a typed callback like node.inputs?.filter(inp =>
inp?.name?.startsWith(prefix) && inp?.link != null).length ?? 0 (or add a proper
Input type and annotate node.inputs as Input[] if needed) and leave g[groupName]
= connectedCount unchanged.
- Around line 151-160: The loop uses unsafe any types for widget/input lookups;
replace (x: any) with the actual types for node.widgets and node.inputs (e.g.,
Widget and Input or the project's defined interfaces) so the find callbacks and
subsequent access (x?.name, widget?.value, slot?.link) are type-checked; update
the variable declarations for widget and slot in the block referencing
rule.depends_on.widgets and rule.depends_on.inputs, ensure normalizeWidgetValue
accepts the Widget.value type, and adjust the i Record type if needed to reflect
the real Input shape rather than relying on any.
- Around line 255-263: compileRule currently forces the jsonata(...) result to
any which bypasses typings; change this to use jsonata's proper Expression type
(or create a local alias) and update CompiledJsonataPricingRule._compiled to
Expression | null; then replace the cast "as any" with a typed assignment like
const compiled: Expression = jsonata(rule.expr) and return { ...rule, _compiled:
compiled } so the code uses correct jsonata types without any casting while
keeping the catch path returning _compiled: null.
- Around line 453-472: Add a readonly price_badge?: PriceBadge property to the
ComfyNodeDefImpl class so price_badge is properly typed (remove the need for the
as any cast in getRelevantWidgetNames), and change the getRelevantWidgetNames
const arrow function into a named function declaration (function
getRelevantWidgetNames(nodeType: string): string[]) keeping the same body and
behavior; locate ComfyNodeDefImpl to add the property and replace the const
getRelevantWidgetNames = (...) => { ... } with a function declaration to match
codebase conventions.
In @src/schemas/nodeDefSchema.ts:
- Around line 222-228: The default value for the depends_on field on zPriceBadge
omits input_groups which can cause type mismatches with zPriceBadgeDepends;
update the default object used in zPriceBadge.depends_on to include
input_groups: [] (so the default becomes { widgets: [], inputs: [],
input_groups: [] }) and ensure the shape matches zPriceBadgeDepends to avoid
narrowing issues.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/composables/node/useNodeBadge.ts (1)
148-156: Clarify the intent of the discarded computed value.The call to
computedWithWidgetWatch(() => 0)registers widget listeners but discards the returned computed. While the comments explain this, the pattern is unusual and could confuse future maintainers.Consider extracting this into a dedicated function in
useWatchWidgetthat explicitly only registers listeners without returning a computed, or add a more prominent comment explaining why this pattern is necessary.
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (5)
package.jsonpnpm-workspace.yamlsrc/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.tssrc/schemas/nodeDefSchema.ts
🧰 Additional context used
📓 Path-based instructions (11)
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/useNodeBadge.tssrc/schemas/nodeDefSchema.tssrc/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
Files:
src/composables/node/useNodeBadge.tssrc/schemas/nodeDefSchema.tssrc/composables/node/useNodePricing.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/node/useNodeBadge.tssrc/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/useNodeBadge.tssrc/schemas/nodeDefSchema.tssrc/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/useNodeBadge.tssrc/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/useNodeBadge.tssrc/schemas/nodeDefSchema.tssrc/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/useNodeBadge.tssrc/composables/node/useNodePricing.ts
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not useanytype oras anytype assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code
Files:
src/composables/node/useNodeBadge.tssrc/schemas/nodeDefSchema.tssrc/composables/node/useNodePricing.ts
**/**/use[A-Z]*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables using the pattern
useXyz.ts
Files:
src/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.ts
**/*.{ts,tsx,vue,js,jsx,json,css}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width
Files:
src/composables/node/useNodeBadge.tssrc/schemas/nodeDefSchema.tspackage.jsonsrc/composables/node/useNodePricing.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Minimize the surface area (exported values) of each module and composable
Files:
src/composables/node/useNodeBadge.tssrc/schemas/nodeDefSchema.tssrc/composables/node/useNodePricing.ts
🧠 Learnings (5)
📚 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/useNodeBadge.tssrc/schemas/nodeDefSchema.tssrc/composables/node/useNodePricing.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/useNodeBadge.tssrc/schemas/nodeDefSchema.tssrc/composables/node/useNodePricing.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).
Applied to files:
src/composables/node/useNodeBadge.tssrc/schemas/nodeDefSchema.tssrc/composables/node/useNodePricing.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().
Applied to files:
src/composables/node/useNodeBadge.tssrc/schemas/nodeDefSchema.tssrc/composables/node/useNodePricing.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/useNodeBadge.tssrc/schemas/nodeDefSchema.tssrc/composables/node/useNodePricing.ts
🧬 Code graph analysis (2)
src/composables/node/useNodeBadge.ts (3)
src/scripts/app.ts (1)
app(1772-1772)src/utils/migration/migrateReroute.ts (1)
node(91-107)src/stores/commandStore.ts (1)
label(52-54)
src/composables/node/useNodePricing.ts (3)
src/schemas/nodeDefSchema.ts (1)
PriceBadge(230-230)src/stores/commandStore.ts (1)
label(52-54)src/stores/nodeDefStore.ts (2)
useNodeDefStore(293-455)nodeDef(82-108)
🔇 Additional comments (9)
package.json (1)
174-174: LGTM!The
jsonatadependency addition aligns with the PR's objective to use JSONata expressions for pricing evaluation. The catalog reference correctly points to the version defined inpnpm-workspace.yaml.src/schemas/nodeDefSchema.ts (2)
200-215: Schema and documentation look good.The
zPriceBadgeDependsschema is well-documented, explaining the autogrow input group behavior and how the count is exposed in the JSONata context. The use ofoptional().default([])for array fields ensures safe access.
259-266: LGTM!The
price_badgefield is appropriately added as optional tozComfyNodeDefwith clear documentation explaining its purpose for API node pricing.src/composables/node/useNodeBadge.ts (3)
76-84: LGTM! Clean debouncing implementation.The
queueCanvasRedrawfunction properly batches multiple redraw requests within a single animation frame using a guard flag. This prevents excessive redraws when multiple pricing evaluations complete in quick succession.
86-93: LGTM! Reactive pricing revision watcher.The watcher correctly triggers canvas redraws only when
showApiPricingBadgeis enabled. Usingflush: 'sync'ensures immediate response to pricing changes.
158-170: LGTM! Efficient badge caching strategy.The
creditsBadgeGetterpattern correctly caches the badge instance and only recreates it when the price label actually changes. This avoids unnecessary object allocations on each badge access while maintaining reactivity.src/composables/node/useNodePricing.ts (2)
1-12: LGTM! Clear documentation of async behavior.The header comment effectively documents the JSONata v2.x async nature and explains the implementation strategy (sync getter, async evaluation, reactive tick). This context is valuable for future maintainers.
474-479: LGTM! Clean public API surface.The composable exposes a minimal, well-documented API: sync getter, config accessor, widget names helper, and a readonly reactive signal for UI updates.
pnpm-workspace.yaml (1)
67-67: LGTM!The
jsonataversion^2.1.0is appropriately pinned to the latest release in the workspace catalog. The caret allows for minor and patch updates, which is the correct approach. The placement maintains alphabetical ordering.
| ?.value | ||
| ) | ||
| // Reactive tick to force UI updates when async evaluations resolve. | ||
| // We purposely read pricingTick.value inside getNodeDisplayPrice to create a dependency. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
Fix all issues with AI Agents 🤖
In @src/composables/node/useNodePricing.ts:
- Around line 151-160: The lookup loops use (x: any) which violates the no-any
rule; replace the explicit any annotations by using the correct domain types
(e.g., Widget and InputSlot or whatever concrete interfaces represent
node.widgets and node.inputs) or let TypeScript infer types by removing the
inline annotations; update the .find callbacks and local variables (widget,
slot, i) to use those types and keep the existing logic calling
normalizeWidgetValue and checking slot.link so behavior is unchanged (refer to
rule.depends_on.widgets, node.widgets, normalizeWidgetValue,
rule.depends_on.inputs, node.inputs, i, widget, slot to find the exact spots).
- Around line 166-170: The filter callback currently uses the unsafe any type
for inp; remove the ": any" and let TypeScript infer the type from node.inputs
(or explicitly cast node.inputs to the correct element type, e.g., Input[] or
NodeInput[] if that type exists) so the predicate becomes (inp) =>
inp?.name?.startsWith(prefix) && inp?.link != null; update the surrounding
typing of node or import/declare the proper input type if needed to ensure
node.inputs is strongly typed before computing connectedCount and assigning
g[groupName].
- Line 336: Repeated casts using (node.constructor as any)?.nodeData should be
replaced by a small typed helper to avoid any and centralize access; add a
getNodeData(node: LGraphNode): NodeData | undefined (with NodeData containing
name?, api_node?, price_badge?) that returns (node.constructor as { nodeData?:
NodeData })?.nodeData, then update all usages such as the nodeName assignment
(currently using (node.constructor as any)?.nodeData?.name ?? '') and other
occurrences (lines referencing api_node and price_badge) to call
getNodeData(node) and read properties from its result.
- Around line 255-263: The compileRule function currently uses an unsafe 'as
any' cast for the jsonata(rule.expr) result; import the jsonata Expression type
and change the compiled field typing so _compiled is typed as Expression | null
(update CompiledJsonataPricingRule accordingly) and cast jsonata(rule.expr) to
Expression instead of any, keeping the try/catch behavior in compileRule.
In @src/schemas/nodeDefSchema.ts:
- Around line 222-228: The default value for the depends_on property in
zPriceBadge omits input_groups, causing inconsistency with zPriceBadgeDepends;
update the default object in the zPriceBadge declaration (depends_on) to include
input_groups: [] alongside widgets: [] and inputs: [] so the default matches
zPriceBadgeDepends and avoids type narrowing issues.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/composables/node/useNodeBadge.ts (1)
148-156: Clarify the intent of discarding the computed return value.The
computedWithWidgetWatch(() => 0)call discards its return value, which is unusual. While the comment explains this registers widget listeners, consider adding a more explicit comment or using a dedicated function if the composable supports it.🔎 Suggested clarification
- // Ensure watchers are installed; ignore the returned value. - // (This call is what registers the widget listeners in most implementations.) - computedWithWidgetWatch(() => 0) + // Register widget change listeners to trigger canvas redraws. + // The returned computed value is intentionally unused; we only need + // the side effect of installing widget watchers. + void computedWithWidgetWatch(() => 0)
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (5)
package.jsonpnpm-workspace.yamlsrc/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.tssrc/schemas/nodeDefSchema.ts
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx,vue,js,jsx,json,css}
📄 CodeRabbit inference engine (AGENTS.md)
Apply Prettier formatting with 2-space indentation, single quotes, no trailing semicolons, and 80-character line width
Files:
package.jsonsrc/schemas/nodeDefSchema.tssrc/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.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/schemas/nodeDefSchema.tssrc/composables/node/useNodeBadge.tssrc/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
Files:
src/schemas/nodeDefSchema.tssrc/composables/node/useNodeBadge.tssrc/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/schemas/nodeDefSchema.tssrc/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/schemas/nodeDefSchema.tssrc/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.ts
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,vue}: Use TypeScript exclusively; do not write new JavaScript code
Use sorted and grouped imports organized by plugin/source
Enforce ESLint rules including Vue + TypeScript rules, disallow floating promises, disallow unused imports, and restrict i18n raw text in templates
Do not useanytype oras anytype assertions; fix the underlying type issue instead
Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Keep functions short and functional; minimize nesting and follow the arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Use function declarations instead of function expressions when possible
Use es-toolkit for utility functions
Implement proper error handling in code
Files:
src/schemas/nodeDefSchema.tssrc/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Minimize the surface area (exported values) of each module and composable
Files:
src/schemas/nodeDefSchema.tssrc/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/node/useNodeBadge.tssrc/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/useNodeBadge.tssrc/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/useNodeBadge.tssrc/composables/node/useNodePricing.ts
**/**/use[A-Z]*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables using the pattern
useXyz.ts
Files:
src/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.ts
🧠 Learnings (13)
📚 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/schemas/nodeDefSchema.tssrc/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.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/schemas/nodeDefSchema.tssrc/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.ts
📚 Learning: 2025-12-17T00:40:09.635Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7537
File: src/components/ui/button/Button.stories.ts:45-55
Timestamp: 2025-12-17T00:40:09.635Z
Learning: Prefer pure function declarations over function expressions (e.g., use function foo() { ... } instead of const foo = () => { ... }) for pure functions in the repository. Function declarations are more functional-leaning, offer better hoisting clarity, and can improve readability and tooling consistency. Apply this guideline across TypeScript files in Comfy-Org/ComfyUI_frontend, including story and UI component code, except where a function expression is semantically required (e.g., callbacks, higher-order functions with closures).
Applied to files:
src/schemas/nodeDefSchema.tssrc/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.ts
📚 Learning: 2025-12-30T22:22:33.836Z
Learnt from: kaili-yang
Repo: Comfy-Org/ComfyUI_frontend PR: 7805
File: src/composables/useCoreCommands.ts:439-439
Timestamp: 2025-12-30T22:22:33.836Z
Learning: When accessing reactive properties from Pinia stores in TypeScript files, avoid using .value on direct property access (e.g., useStore().isOverlayExpanded). Pinia auto-wraps refs when accessed directly, returning the primitive value. The .value accessor is only needed when destructuring store properties or when using storeToRefs().
Applied to files:
src/schemas/nodeDefSchema.tssrc/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.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/schemas/nodeDefSchema.tssrc/composables/node/useNodeBadge.tssrc/composables/node/useNodePricing.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.{ts,tsx,vue} : Do not use `any` type or `as any` type assertions; fix the underlying type issue instead
Applied to files:
src/composables/node/useNodePricing.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/**/*.{ts,tsx,vue} : Avoid using ts-expect-error; use proper TypeScript types instead
Applied to files:
src/composables/node/useNodePricing.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/**/*.{js,ts,jsx,tsx} : Do not replace `&&=` or `||=` with `=` when there is no reason to do so. If you do find a reason to remove either `&&=` or `||=`, leave a comment explaining why the removal occurred
Applied to files:
src/composables/node/useNodePricing.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/**/*.{ts,tsx,vue} : Implement proper TypeScript types throughout the codebase
Applied to files:
src/composables/node/useNodePricing.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/**/*.{ts,tsx} : Type assertions are an absolute last resort. In almost all cases, they are a crutch that leads to brittle code
Applied to files:
src/composables/node/useNodePricing.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.{ts,tsx,vue} : Use function declarations instead of function expressions when possible
Applied to files:
src/composables/node/useNodePricing.ts
📚 Learning: 2025-12-13T05:34:22.209Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7415
File: browser_tests/tests/mobileBaseline.spec.ts:7-15
Timestamp: 2025-12-13T05:34:22.209Z
Learning: In Playwright tests in the Comfy-Org/ComfyUI_frontend repository, the `toPass()` assertion method implements incremental backoff during retries, so increasing the timeout value (e.g., to 5000ms) is sufficient for handling async operations without being overly aggressive.
Applied to files:
src/composables/node/useNodePricing.ts
📚 Learning: 2025-12-21T06:04:12.562Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T06:04:12.562Z
Learning: Applies to **/*.{ts,tsx,vue} : Write code that is expressive and self-documenting; avoid redundant comments and clean as you go
Applied to files:
src/composables/node/useNodePricing.ts
🧬 Code graph analysis (1)
src/composables/node/useNodePricing.ts (2)
src/schemas/nodeDefSchema.ts (1)
PriceBadge(230-230)src/stores/nodeDefStore.ts (2)
useNodeDefStore(293-455)nodeDef(82-108)
🔇 Additional comments (8)
package.json (1)
174-174: LGTM!The
jsonatadependency is appropriately added to runtime dependencies using the catalog specifier, consistent with the project's dependency management pattern.src/schemas/nodeDefSchema.ts (2)
200-215: LGTM!The
zPriceBadgeDependsschema is well-documented with clear explanations for each field, especially theinput_groupsfield which includes a helpful usage example for autogrow inputs.
259-265: LGTM!The
price_badgefield is appropriately added tozComfyNodeDefas an optional field with clear documentation explaining its purpose for API node pricing.src/composables/node/useNodePricing.ts (1)
408-436: LGTM with note on intentional reactive dependency.The bare
pricingTick.valueread on line 411 is an intentional reactive dependency pattern. Consider usingvoid pricingTick.valueto make the intent clearer and prevent accidental removal.The sync getter with async fallback pattern is well-designed for avoiding flicker while handling JSONata's async evaluation.
src/composables/node/useNodeBadge.ts (3)
76-93: LGTM!Good optimization using
requestAnimationFrameto batch canvas redraws. TheredrawQueuedflag prevents redundant RAF calls, and the watch with{ flush: 'sync' }ensures pricing updates are immediately reflected.
158-170: Mutable closure state for badge caching.The
lastLabelandlastBadgevariables create mutable closure state. This is acceptable here since it's a simple memoization pattern, but consider using aWeakMapfor consistency with the caching pattern inuseNodePricing.tsif this grows in complexity.
132-139: LGTM!The
hasDynamicPricingcheck correctly identifies nodes with widget or input dependencies, aligning with the JSONata-based pricing system.pnpm-workspace.yaml (1)
67-67: The jsonata version^2.1.0is the current stable release on npm and is actively maintained. The catalog entry is appropriate.
7d3f77e to
110224b
Compare
🎨 Storybook Build Status✅ Build completed successfully! ⏰ Completed at: 01/22/2026, 06:38:08 AM UTC 🔗 Links🎉 Your Storybook is ready for review! |
🎭 Playwright Tests:
|
Bundle Size ReportSummary
Category Glance Per-category breakdownApp Entry Points — 22.3 kB (baseline 22.3 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 946 kB (baseline 1.01 MB) • 🟢 -64.3 kBGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed Views & Navigation — 80.7 kB (baseline 80.7 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 11 added / 11 removed Panels & Settings — 430 kB (baseline 430 kB) • 🔴 +4 BConfiguration panels, inspectors, and settings screens
Status: 21 added / 21 removed User & Accounts — 3.94 kB (baseline 3.94 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 3 added / 3 removed Editors & Dialogs — 2.8 kB (baseline 2.8 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 2 added / 2 removed UI Components — 32.8 kB (baseline 32.8 kB) • 🔴 +1 BReusable component library chunks
Status: 8 added / 8 removed Data & Services — 3.12 MB (baseline 3.11 MB) • 🔴 +13.1 kBStores, services, APIs, and repositories
Status: 8 added / 8 removed Utilities & Hooks — 18.1 kB (baseline 18.1 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 8 added / 8 removed Vendor & Third-Party — 10.7 MB (baseline 10.5 MB) • 🔴 +181 kBExternal libraries and shared vendor chunks
Status: 8 added / 8 removed Other — 6.3 MB (baseline 6.3 MB) • 🔴 +213 BBundles that do not match a named category
Status: 80 added / 80 removed |
🔧 Auto-fixes AppliedThis PR has been automatically updated to fix linting and formatting issues.
Changes made:
|
5ab4187 to
ff49062
Compare
There was a problem hiding this 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
🤖 Fix all issues with AI agents
In `@package.json`:
- Line 176: The package.json dependency for "jsonata" is catalog-resolved and
may resolve to a vulnerable version (per CVE-2024-27307); run npm ls jsonata to
determine the actual installed version, and if it falls in the vulnerable ranges
(>=1.4.0 <1.8.7 or >=2.0.0 <2.0.4) update the package resolution to a safe
release (preferably "2.1.0" or any >=1.8.7 / >=2.0.4), update the lockfile (npm
install or npm ci) and re-run tests and npm audit to ensure no transitive
packages still pull a vulnerable jsonata—change the "jsonata" entry in
package.json from the catalog spec to the explicit safe version and commit the
updated lockfile.
AustinMroz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a lot, but the code, bleeding edge autogrow stuff, and reactivity handling all look good to me.
There was a problem hiding this 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
🤖 Fix all issues with AI agents
In `@src/composables/node/useNodeBadge.ts`:
- Around line 187-199: The cached badge only updates when
nodePricing.getNodeDisplayPrice(node) changes; include styling/settings in the
invalidation by adding a dependency (e.g. a badgeRevision or
themePaletteRevision) used alongside lastLabel inside the creditsBadgeGetter, or
reset the cache when those settings change via a watcher; update
creditsBadgeGetter to compare both label and revision (or clear
lastLabel/lastBadge in the watcher) so priceBadge.getCreditsBadge(label) is
re-run when palette/theme/badge settings change before pushing the getter onto
node.badges.
Summary
Backend part: Comfy-Org/ComfyUI#11582
price_badgefield to node definition schema containing JSONata expression and dependency declarationsScreenshots (if applicable)
┆Issue is synchronized with this Notion page by Unito