diff --git a/src/composables/node/useNodePricing.ts b/src/composables/node/useNodePricing.ts index f61dccc709..b2e417415a 100644 --- a/src/composables/node/useNodePricing.ts +++ b/src/composables/node/useNodePricing.ts @@ -418,7 +418,12 @@ const apiNodeCosts: Record = const modeValue = String(modeWidget.value) // Pricing matrix from CSV data based on mode string content - if (modeValue.includes('v2-master')) { + if (modeValue.includes('v2-1-master')) { + if (modeValue.includes('10s')) { + return '$2.80/Run' // price is the same as for v2-master model + } + return '$1.40/Run' // price is the same as for v2-master model + } else if (modeValue.includes('v2-master')) { if (modeValue.includes('10s')) { return '$2.80/Run' } @@ -558,6 +563,32 @@ const apiNodeCosts: Record = MinimaxTextToVideoNode: { displayPrice: '$0.43/Run' }, + MinimaxHailuoVideoNode: { + displayPrice: (node: LGraphNode): string => { + const resolutionWidget = node.widgets?.find( + (w) => w.name === 'resolution' + ) as IComboWidget + const durationWidget = node.widgets?.find( + (w) => w.name === 'duration' + ) as IComboWidget + + if (!resolutionWidget || !durationWidget) { + return '$0.28-0.56/Run (varies with resolution & duration)' + } + + const resolution = String(resolutionWidget.value) + const duration = String(durationWidget.value) + + if (resolution.includes('768P')) { + if (duration.includes('6')) return '$0.28/Run' + if (duration.includes('10')) return '$0.56/Run' + } else if (resolution.includes('1080P')) { + if (duration.includes('6')) return '$0.49/Run' + } + + return '$0.43/Run' // default median + } + }, OpenAIDalle2: { displayPrice: (node: LGraphNode): string => { const sizeWidget = node.widgets?.find( @@ -1358,6 +1389,7 @@ export const useNodePricing = () => { KlingDualCharacterVideoEffectNode: ['mode', 'model_name', 'duration'], KlingSingleImageVideoEffectNode: ['effect_scene'], KlingStartEndFrameNode: ['mode', 'model_name', 'duration'], + MinimaxHailuoVideoNode: ['resolution', 'duration'], OpenAIDalle3: ['size', 'quality'], OpenAIDalle2: ['size', 'n'], OpenAIGPTImage1: ['quality', 'n'], diff --git a/tests-ui/tests/composables/node/useNodePricing.test.ts b/tests-ui/tests/composables/node/useNodePricing.test.ts index cdb6454f19..140272e9f1 100644 --- a/tests-ui/tests/composables/node/useNodePricing.test.ts +++ b/tests-ui/tests/composables/node/useNodePricing.test.ts @@ -64,6 +64,16 @@ describe('useNodePricing', () => { }) describe('dynamic pricing - KlingTextToVideoNode', () => { + it('should return high price for kling-v2-1-master model', () => { + const { getNodeDisplayPrice } = useNodePricing() + const node = createMockNode('KlingTextToVideoNode', [ + { name: 'mode', value: 'standard / 5s / v2-1-master' } + ]) + + const price = getNodeDisplayPrice(node) + expect(price).toBe('$1.40/Run') + }) + it('should return high price for kling-v2-master model', () => { const { getNodeDisplayPrice } = useNodePricing() const node = createMockNode('KlingTextToVideoNode', [ @@ -219,6 +229,49 @@ describe('useNodePricing', () => { }) }) + describe('dynamic pricing - MinimaxHailuoVideoNode', () => { + it('should return $0.28 for 6s duration and 768P resolution', () => { + const { getNodeDisplayPrice } = useNodePricing() + const node = createMockNode('MinimaxHailuoVideoNode', [ + { name: 'duration', value: '6' }, + { name: 'resolution', value: '768P' } + ]) + + const price = getNodeDisplayPrice(node) + expect(price).toBe('$0.28/Run') + }) + + it('should return $0.60 for 10s duration and 768P resolution', () => { + const { getNodeDisplayPrice } = useNodePricing() + const node = createMockNode('MinimaxHailuoVideoNode', [ + { name: 'duration', value: '10' }, + { name: 'resolution', value: '768P' } + ]) + + const price = getNodeDisplayPrice(node) + expect(price).toBe('$0.56/Run') + }) + + it('should return $0.49 for 6s duration and 1080P resolution', () => { + const { getNodeDisplayPrice } = useNodePricing() + const node = createMockNode('MinimaxHailuoVideoNode', [ + { name: 'duration', value: '6' }, + { name: 'resolution', value: '1080P' } + ]) + + const price = getNodeDisplayPrice(node) + expect(price).toBe('$0.49/Run') + }) + + it('should return range when duration widget is missing', () => { + const { getNodeDisplayPrice } = useNodePricing() + const node = createMockNode('MinimaxHailuoVideoNode', []) + + const price = getNodeDisplayPrice(node) + expect(price).toBe('$0.28-0.56/Run (varies with resolution & duration)') + }) + }) + describe('dynamic pricing - OpenAIDalle2', () => { it('should return $0.02 for 1024x1024 size', () => { const { getNodeDisplayPrice } = useNodePricing()