From 15a05afc27927a98dec24323428b921bd71513ae Mon Sep 17 00:00:00 2001 From: Alexander Piskun <13381981+bigcat88@users.noreply.github.com> Date: Thu, 8 Jan 2026 23:17:25 +0200 Subject: [PATCH] fix(price-badges): improve Gemini and OpenAI chat nodes (#7900) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Added `~` to the price badges and a correct separator. ## Screenshots (if applicable) Before commit: Screenshot From 2026-01-08 09-53-00 After: Screenshot From 2026-01-08 09-52-09 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7900-fix-price-badges-improve-Gemini-and-OpenAI-chat-nodes-2e26d73d3650812093f2d173de50052d) by [Unito](https://www.unito.io) --- src/composables/node/useNodePricing.test.ts | 102 +++++++++++++------- src/composables/node/useNodePricing.ts | 73 ++++++++++---- 2 files changed, 121 insertions(+), 54 deletions(-) diff --git a/src/composables/node/useNodePricing.test.ts b/src/composables/node/useNodePricing.test.ts index a619f5a19..c811a4796 100644 --- a/src/composables/node/useNodePricing.test.ts +++ b/src/composables/node/useNodePricing.test.ts @@ -1664,31 +1664,41 @@ describe('useNodePricing', () => { { model: 'gemini-2.5-pro-preview-05-06', expected: creditsListLabel([0.00125, 0.01], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gemini-2.5-pro', expected: creditsListLabel([0.00125, 0.01], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gemini-3-pro-preview', expected: creditsListLabel([0.002, 0.012], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gemini-2.5-flash-preview-04-17', expected: creditsListLabel([0.0003, 0.0025], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gemini-2.5-flash', expected: creditsListLabel([0.0003, 0.0025], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'unknown-gemini-model', expected: 'Token-based' } @@ -1702,16 +1712,6 @@ describe('useNodePricing', () => { }) }) - it('should return per-second pricing for Gemini Veo models', () => { - const { getNodeDisplayPrice } = useNodePricing() - const node = createMockNode('GeminiNode', [ - { name: 'model', value: 'veo-2.0-generate-001' } - ]) - - const price = getNodeDisplayPrice(node) - expect(price).toBe(creditsLabel(0.5, { suffix: '/second' })) - }) - it('should return fallback for GeminiNode without model widget', () => { const { getNodeDisplayPrice } = useNodePricing() const node = createMockNode('GeminiNode', []) @@ -1737,73 +1737,97 @@ describe('useNodePricing', () => { { model: 'o4-mini', expected: creditsListLabel([0.0011, 0.0044], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'o1-pro', expected: creditsListLabel([0.15, 0.6], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'o1', expected: creditsListLabel([0.015, 0.06], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'o3-mini', expected: creditsListLabel([0.0011, 0.0044], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'o3', expected: creditsListLabel([0.01, 0.04], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gpt-4o', expected: creditsListLabel([0.0025, 0.01], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gpt-4.1-nano', expected: creditsListLabel([0.0001, 0.0004], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gpt-4.1-mini', expected: creditsListLabel([0.0004, 0.0016], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gpt-4.1', expected: creditsListLabel([0.002, 0.008], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gpt-5-nano', expected: creditsListLabel([0.00005, 0.0004], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gpt-5-mini', expected: creditsListLabel([0.00025, 0.002], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gpt-5', expected: creditsListLabel([0.00125, 0.01], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } ] @@ -1824,37 +1848,49 @@ describe('useNodePricing', () => { { model: 'gpt-4.1-nano-test', expected: creditsListLabel([0.0001, 0.0004], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gpt-4.1-mini-test', expected: creditsListLabel([0.0004, 0.0016], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'gpt-4.1-test', expected: creditsListLabel([0.002, 0.008], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'o1-pro-test', expected: creditsListLabel([0.15, 0.6], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'o1-test', expected: creditsListLabel([0.015, 0.06], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'o3-mini-test', expected: creditsListLabel([0.0011, 0.0044], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) }, { model: 'unknown-model', expected: 'Token-based' } diff --git a/src/composables/node/useNodePricing.ts b/src/composables/node/useNodePricing.ts index ccf51a71c..641d38911 100644 --- a/src/composables/node/useNodePricing.ts +++ b/src/composables/node/useNodePricing.ts @@ -1823,28 +1823,35 @@ const apiNodeCosts: Record = const model = String(modelWidget.value) - // Google Veo video generation - if (model.includes('veo-2.0')) { - return formatCreditsLabel(0.5, { suffix: '/second' }) - } else if (model.includes('gemini-2.5-flash-preview-04-17')) { + if (model.includes('gemini-2.5-flash-preview-04-17')) { return formatCreditsListLabel([0.0003, 0.0025], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('gemini-2.5-flash')) { return formatCreditsListLabel([0.0003, 0.0025], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('gemini-2.5-pro-preview-05-06')) { return formatCreditsListLabel([0.00125, 0.01], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('gemini-2.5-pro')) { return formatCreditsListLabel([0.00125, 0.01], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('gemini-3-pro-preview')) { return formatCreditsListLabel([0.002, 0.012], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } // For other Gemini models, show token-based pricing info @@ -1899,51 +1906,75 @@ const apiNodeCosts: Record = // Specific pricing for exposed models based on official pricing data (converted to per 1K tokens) if (model.includes('o4-mini')) { return formatCreditsListLabel([0.0011, 0.0044], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('o1-pro')) { return formatCreditsListLabel([0.15, 0.6], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('o1')) { return formatCreditsListLabel([0.015, 0.06], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('o3-mini')) { return formatCreditsListLabel([0.0011, 0.0044], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('o3')) { return formatCreditsListLabel([0.01, 0.04], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('gpt-4o')) { return formatCreditsListLabel([0.0025, 0.01], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('gpt-4.1-nano')) { return formatCreditsListLabel([0.0001, 0.0004], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('gpt-4.1-mini')) { return formatCreditsListLabel([0.0004, 0.0016], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('gpt-4.1')) { return formatCreditsListLabel([0.002, 0.008], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('gpt-5-nano')) { return formatCreditsListLabel([0.00005, 0.0004], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('gpt-5-mini')) { return formatCreditsListLabel([0.00025, 0.002], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } else if (model.includes('gpt-5')) { return formatCreditsListLabel([0.00125, 0.01], { - suffix: ' per 1K tokens' + suffix: ' per 1K tokens', + approximate: true, + separator: '-' }) } return 'Token-based'