diff --git a/src/composables/node/useNodeBadge.ts b/src/composables/node/useNodeBadge.ts index 419beb3c4..b34da8ed9 100644 --- a/src/composables/node/useNodeBadge.ts +++ b/src/composables/node/useNodeBadge.ts @@ -6,6 +6,7 @@ import { import _ from 'lodash' import { computed, onMounted, watch } from 'vue' +import { useNodePricing } from '@/composables/node/useNodePricing' import { app } from '@/scripts/app' import { useExtensionStore } from '@/stores/extensionStore' import { ComfyNodeDefImpl, useNodeDefStore } from '@/stores/nodeDefStore' @@ -42,9 +43,21 @@ export const useNodeBadge = () => { ) as NodeBadgeMode ) - watch([nodeSourceBadgeMode, nodeIdBadgeMode, nodeLifeCycleBadgeMode], () => { - app.graph?.setDirtyCanvas(true, true) - }) + const showApiPricingBadge = computed(() => + settingStore.get('Comfy.NodeBadge.ShowApiPricing') + ) + + watch( + [ + nodeSourceBadgeMode, + nodeIdBadgeMode, + nodeLifeCycleBadgeMode, + showApiPricingBadge + ], + () => { + app.graph?.setDirtyCanvas(true, true) + } + ) const nodeDefStore = useNodeDefStore() function badgeTextVisible( @@ -58,6 +71,8 @@ export const useNodeBadge = () => { } onMounted(() => { + const nodePricing = useNodePricing() + extensionStore.registerExtension({ name: 'Comfy.NodeBadge', nodeCreated(node: LGraphNode) { @@ -95,13 +110,15 @@ export const useNodeBadge = () => { node.badges.push(() => badge.value) - if (node.constructor.nodeData?.api_node) { + if (node.constructor.nodeData?.api_node && showApiPricingBadge.value) { + const price = nodePricing.getNodeDisplayPrice(node) + // Always add the badge for API nodes, with or without price text const creditsBadge = computed(() => { // Use dynamic background color based on the theme const isLightTheme = colorPaletteStore.completedActivePalette.light_theme return new LGraphBadge({ - text: '', + text: price, iconOptions: { unicode: '\ue96b', fontFamily: 'PrimeIcons', diff --git a/src/composables/node/useNodePricing.ts b/src/composables/node/useNodePricing.ts new file mode 100644 index 000000000..7bf92d928 --- /dev/null +++ b/src/composables/node/useNodePricing.ts @@ -0,0 +1,426 @@ +import type { LGraphNode } from '@comfyorg/litegraph' + +import { ApiNodeCostRecord } from '@/types/apiNodeTypes' + +const apiNodeCosts: ApiNodeCostRecord = { + FluxProCannyNode: { + vendor: 'BFL', + nodeName: 'Flux 1: Canny Control Image', + pricingParams: '-', + pricePerRunRange: '$0.05', + displayPrice: '$0.05/Run' + }, + FluxProDepthNode: { + vendor: 'BFL', + nodeName: 'Flux 1: Depth Control Image', + pricingParams: '-', + pricePerRunRange: '$0.05', + displayPrice: '$0.05/Run' + }, + FluxProExpandNode: { + vendor: 'BFL', + nodeName: 'Flux 1: Expand Image', + pricingParams: '-', + pricePerRunRange: '$0.05', + rateDocumentationUrl: 'https://docs.bfl.ml/pricing/', + displayPrice: '$0.05/Run' + }, + FluxProFillNode: { + vendor: 'BFL', + nodeName: 'Flux 1: Fill Image', + pricingParams: '-', + pricePerRunRange: '$0.05', + displayPrice: '$0.05/Run' + }, + FluxProUltraImageNode: { + vendor: 'BFL', + nodeName: 'Flux 1.1: [pro] Ultra Image', + pricingParams: '-', + pricePerRunRange: '$0.06', + displayPrice: '$0.06/Run' + }, + IdeogramV1: { + vendor: 'Ideogram', + nodeName: 'Ideogram V1', + pricingParams: '-', + pricePerRunRange: '$0.06', + rateDocumentationUrl: 'https://about.ideogram.ai/api-pricing', + displayPrice: '$0.06/Run' + }, + IdeogramV2: { + vendor: 'Ideogram', + nodeName: 'Ideogram V2', + pricingParams: '-', + pricePerRunRange: '$0.08', + displayPrice: '$0.08/Run' + }, + IdeogramV3: { + vendor: 'Ideogram', + nodeName: 'Ideogram V3', + pricingParams: 'rendering_speed', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (low to medium)' + }, + KlingCameraControlI2VNode: { + vendor: 'Kling', + nodeName: 'Kling Image to Video (Camera Control)', + pricingParams: '-', + pricePerRunRange: '$0.49', + displayPrice: '$0.49/Run' + }, + KlingCameraControlT2VNode: { + vendor: 'Kling', + nodeName: 'Kling Text to Video (Camera Control)', + pricingParams: '-', + pricePerRunRange: '$0.14', + displayPrice: '$0.14/Run' + }, + KlingDualCharacterVideoEffectNode: { + vendor: 'Kling', + nodeName: 'Kling Dual Character Video Effects', + pricingParams: 'Priced the same as t2v based on mode, model, and duration.', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (medium)' + }, + KlingImage2VideoNode: { + vendor: 'Kling', + nodeName: 'Kling Image to Video', + pricingParams: 'Same as Text to Video', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (medium)' + }, + KlingImageGenerationNode: { + vendor: 'Kling', + nodeName: 'Kling Image Generation', + pricingParams: 'modality | model', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (low)' + }, + KlingLipSyncAudioToVideoNode: { + vendor: 'Kling', + nodeName: 'Kling Lip Sync Video with Audio', + pricingParams: 'duration of input video', + pricePerRunRange: '$0.07', + displayPrice: '$0.07/Run' + }, + KlingLipSyncTextToVideoNode: { + vendor: 'Kling', + nodeName: 'Kling Lip Sync Video with Text', + pricingParams: 'duration of input video', + pricePerRunRange: '$0.07', + displayPrice: '$0.07/Run' + }, + KlingSingleImageVideoEffectNode: { + vendor: 'Kling', + nodeName: 'Kling Video Effects', + pricingParams: 'effect_scene', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (medium)' + }, + KlingStartEndFrameNode: { + vendor: 'Kling', + nodeName: 'Kling Start-End Frame to Video', + pricingParams: 'Same as text to video', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (medium)' + }, + KlingTextToVideoNode: { + vendor: 'Kling', + nodeName: 'Kling Text to Video', + pricingParams: 'model | duration | mode', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (medium to high)' + }, + KlingVideoExtendNode: { + vendor: 'Kling', + nodeName: 'Kling Video Extend', + pricingParams: '-', + pricePerRunRange: '$0.28', + displayPrice: '$0.28/Run' + }, + KlingVirtualTryOnNode: { + vendor: 'Kling', + nodeName: 'Kling Virtual Try On', + pricingParams: '-', + pricePerRunRange: '$0.07', + displayPrice: '$0.07/Run' + }, + LumaImageToVideoNode: { + vendor: 'Luma', + nodeName: 'Luma Image to Video', + pricingParams: 'Same as Text to Video', + pricePerRunRange: 'dynamic', + rateDocumentationUrl: 'https://lumalabs.ai/api/pricing', + displayPrice: 'Variable pricing (medium to high)' + }, + LumaVideoNode: { + vendor: 'Luma', + nodeName: 'Luma Text to Video', + pricingParams: 'model | resolution | duration', + pricePerRunRange: 'dynamic', + rateDocumentationUrl: 'https://lumalabs.ai/api/pricing', + displayPrice: 'Variable pricing (medium to high)' + }, + MinimaxImageToVideoNode: { + vendor: 'Minimax', + nodeName: 'MiniMax Image to Video', + pricingParams: '-', + pricePerRunRange: '$0.43', + rateDocumentationUrl: 'https://www.minimax.io/price', + displayPrice: '$0.43/Run' + }, + MinimaxTextToVideoNode: { + vendor: 'Minimax', + nodeName: 'MiniMax Text to Video', + pricingParams: '-', + pricePerRunRange: '$0.43', + rateDocumentationUrl: 'https://www.minimax.io/price', + displayPrice: '$0.43/Run' + }, + OpenAIDalle2: { + vendor: 'OpenAI', + nodeName: 'dall-e-2', + pricingParams: 'size', + pricePerRunRange: 'dynamic', + rateDocumentationUrl: 'https://platform.openai.com/docs/pricing', + displayPrice: 'Variable pricing (low)' + }, + OpenAIDalle3: { + vendor: 'OpenAI', + nodeName: 'dall-e-3', + pricingParams: 'size | quality', + pricePerRunRange: 'dynamic', + rateDocumentationUrl: 'https://platform.openai.com/docs/pricing', + displayPrice: 'Variable pricing (medium)' + }, + OpenAIGPTImage1: { + vendor: 'OpenAI', + nodeName: 'gpt-image-1', + pricingParams: 'quality', + pricePerRunRange: 'dynamic', + rateDocumentationUrl: 'https://platform.openai.com/docs/pricing', + displayPrice: 'Variable pricing (low to high)' + }, + PikaImageToVideoNode2_2: { + vendor: 'Pika', + nodeName: 'Pika Image to Video', + pricingParams: 'duration | resolution', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (medium)' + }, + PikaScenesV2_2: { + vendor: 'Pika', + nodeName: 'Pika Scenes (Video Image Composition)', + pricingParams: 'duration | resolution', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (medium)' + }, + PikaStartEndFrameNode2_2: { + vendor: 'Pika', + nodeName: 'Pika Start and End Frame to Video', + pricingParams: 'duration | resolution', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (medium)' + }, + PikaTextToVideoNode2_2: { + vendor: 'Pika', + nodeName: 'Pika Text to Video', + pricingParams: 'duration | resolution', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (medium)' + }, + Pikadditions: { + vendor: 'Pika', + nodeName: 'Pikadditions (Video Object Insertion)', + pricingParams: '-', + pricePerRunRange: '$0.3', + displayPrice: '$0.3/Run' + }, + Pikaffects: { + vendor: 'Pika', + nodeName: 'Pikaffects (Video Effects)', + pricingParams: '-', + pricePerRunRange: '$0.45', + displayPrice: '$0.45/Run' + }, + Pikaswaps: { + vendor: 'Pika', + nodeName: 'Pika Swaps (Video Object Replacement)', + pricingParams: '-', + pricePerRunRange: '$0.3', + displayPrice: '$0.3/Run' + }, + PixverseImageToVideoNode: { + vendor: 'Pixverse', + nodeName: 'PixVerse Image to Video', + pricingParams: 'same as text to video', + pricePerRunRange: '$0.9', + displayPrice: '$0.9/Run' + }, + PixverseTextToVideoNode: { + vendor: 'Pixverse', + nodeName: 'PixVerse Text to Video', + pricingParams: 'duration | quality | motion_mode', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (medium to high)' + }, + PixverseTransitionVideoNode: { + vendor: 'Pixverse', + nodeName: 'PixVerse Transition Video', + pricingParams: 'same as text to video', + pricePerRunRange: '$0.9', + displayPrice: '$0.9/Run' + }, + RecraftCreativeUpscaleNode: { + vendor: 'Recraft', + nodeName: 'Recraft Creative Upscale Image', + pricingParams: '-', + pricePerRunRange: '$0.25', + rateDocumentationUrl: 'https://www.recraft.ai/docs#pricing', + displayPrice: '$0.25/Run' + }, + RecraftCrispUpscaleNode: { + vendor: 'Recraft', + nodeName: 'Recraft Crisp Upscale Image', + pricingParams: '-', + pricePerRunRange: '$0.004', + rateDocumentationUrl: 'https://www.recraft.ai/docs#pricing', + displayPrice: '$0.004/Run' + }, + RecraftImageInpaintingNode: { + vendor: 'Recraft', + nodeName: 'Recraft Image Inpainting', + pricingParams: 'n', + pricePerRunRange: '$$0.04 x n', + rateDocumentationUrl: 'https://www.recraft.ai/docs#pricing', + displayPrice: '$0.04 x n/Run' + }, + RecraftImageToImageNode: { + vendor: 'Recraft', + nodeName: 'Recraft Image to Image', + pricingParams: 'n', + pricePerRunRange: '$0.04 x n', + rateDocumentationUrl: 'https://www.recraft.ai/docs#pricing', + displayPrice: '$0.04 x n/Run' + }, + RecraftRemoveBackgroundNode: { + vendor: 'Recraft', + nodeName: 'Recraft Remove Background', + pricingParams: '-', + pricePerRunRange: '$0.01', + rateDocumentationUrl: 'https://www.recraft.ai/docs#pricing', + displayPrice: '$0.01/Run' + }, + RecraftReplaceBackgroundNode: { + vendor: 'Recraft', + nodeName: 'Recraft Replace Background', + pricingParams: 'n', + pricePerRunRange: '$0.04', + rateDocumentationUrl: 'https://www.recraft.ai/docs#pricing', + displayPrice: '$0.04/Run' + }, + RecraftTextToImageNode: { + vendor: 'Recraft', + nodeName: 'Recraft Text to Image', + pricingParams: 'model | n', + pricePerRunRange: '$0.04 x n', + rateDocumentationUrl: 'https://www.recraft.ai/docs#pricing', + displayPrice: '$0.04 x n/Run' + }, + RecraftTextToVectorNode: { + vendor: 'Recraft', + nodeName: 'Recraft Text to Vector', + pricingParams: 'model | n', + pricePerRunRange: '$0.08 x n', + rateDocumentationUrl: 'https://www.recraft.ai/docs#pricing', + displayPrice: '$0.08 x n/Run' + }, + RecraftVectorizeImageNode: { + vendor: 'Recraft', + nodeName: 'Recraft Vectorize Image', + pricingParams: '-', + pricePerRunRange: '$0.01', + rateDocumentationUrl: 'https://www.recraft.ai/docs#pricing', + displayPrice: '$0.01/Run' + }, + StabilityStableImageSD_3_5Node: { + vendor: 'Stability', + nodeName: 'Stability AI Stable Diffusion 3.5 Image', + pricingParams: 'model', + pricePerRunRange: 'dynamic', + displayPrice: 'Variable pricing (low)' + }, + StabilityStableImageUltraNode: { + vendor: 'Stability', + nodeName: 'Stability AI Stable Image Ultra', + pricingParams: '-', + pricePerRunRange: '$0.08', + displayPrice: '$0.08/Run' + }, + StabilityUpscaleConservativeNode: { + vendor: 'Stability', + nodeName: 'Stability AI Upscale Conservative', + pricingParams: '-', + pricePerRunRange: '$0.25', + displayPrice: '$0.25/Run' + }, + StabilityUpscaleCreativeNode: { + vendor: 'Stability', + nodeName: 'Stability AI Upscale Creative', + pricingParams: '-', + pricePerRunRange: '$0.25', + displayPrice: '$0.25/Run' + }, + StabilityUpscaleFastNode: { + vendor: 'Stability', + nodeName: 'Stability AI Upscale Fast', + pricingParams: '-', + pricePerRunRange: '$0.01', + displayPrice: '$0.01/Run' + }, + VeoVideoGenerationNode: { + vendor: 'Veo', + nodeName: 'Google Veo2 Video Generation', + pricingParams: 'duration_seconds', + pricePerRunRange: 'dynamic', + rateDocumentationUrl: + 'https://cloud.google.com/vertex-ai/generative-ai/pricing', + displayPrice: 'Variable pricing (high)' + }, + LumaTextToImageNode: { + vendor: 'Luma', + nodeName: 'Luma Text to Image', + pricingParams: 'model | aspect_ratio', + pricePerRunRange: 'dynamic', + rateDocumentationUrl: 'https://lumalabs.ai/api/pricing', + displayPrice: 'Variable pricing (low to medium)' + }, + LumaImageToImageNode: { + vendor: 'Luma', + nodeName: 'Luma Image to Image', + pricingParams: 'Same as Text to Image', + pricePerRunRange: 'dynamic', + rateDocumentationUrl: 'https://lumalabs.ai/api/pricing', + displayPrice: 'Variable pricing (low to medium)' + } +} + +/** + * Composable to get node pricing information for API nodes + */ +export const useNodePricing = () => { + const getNodePrice = (nodeName: string): string => + apiNodeCosts[nodeName]?.displayPrice || '' + + /** + * Get the price display for a node + */ + const getNodeDisplayPrice = (node: LGraphNode): string => { + if (!node.constructor.nodeData?.api_node) return '' + return getNodePrice(node.constructor.nodeData.name) + } + + return { + getNodeDisplayPrice + } +} diff --git a/src/constants/coreSettings.ts b/src/constants/coreSettings.ts index 27a530667..daa187870 100644 --- a/src/constants/coreSettings.ts +++ b/src/constants/coreSettings.ts @@ -322,6 +322,14 @@ export const CORE_SETTINGS: SettingParams[] = [ options: [NodeBadgeMode.None, NodeBadgeMode.ShowAll], defaultValue: NodeBadgeMode.ShowAll }, + { + id: 'Comfy.NodeBadge.ShowApiPricing', + category: ['Comfy', 'API Nodes'], + name: 'Show API node pricing badge', + type: 'boolean', + defaultValue: true, + versionAdded: '1.20.3' + }, { id: 'Comfy.ConfirmClear', category: ['Comfy', 'Workflow', 'ConfirmClear'], diff --git a/src/locales/en/main.json b/src/locales/en/main.json index 12640de4e..45a1c7bad 100644 --- a/src/locales/en/main.json +++ b/src/locales/en/main.json @@ -886,7 +886,8 @@ "3D": "3D", "Light": "Light", "User": "User", - "Credits": "Credits" + "Credits": "Credits", + "API Nodes": "API Nodes" }, "serverConfigItems": { "listen": { diff --git a/src/locales/en/settings.json b/src/locales/en/settings.json index 779f1cbcd..f370bfab8 100644 --- a/src/locales/en/settings.json +++ b/src/locales/en/settings.json @@ -225,6 +225,9 @@ "Hide built-in": "Hide built-in" } }, + "Comfy_NodeBadge_ShowApiPricing": { + "name": "Show API node pricing badge" + }, "Comfy_NodeSearchBoxImpl": { "name": "Node search box implementation", "options": { diff --git a/src/locales/es/main.json b/src/locales/es/main.json index e661a1f5b..b073fd919 100644 --- a/src/locales/es/main.json +++ b/src/locales/es/main.json @@ -1001,6 +1001,7 @@ }, "settingsCategories": { "3D": "3D", + "API Nodes": "Nodos API", "About": "Acerca de", "Appearance": "Apariencia", "BrushAdjustment": "Ajuste de Pincel", diff --git a/src/locales/es/settings.json b/src/locales/es/settings.json index 6bef6d059..ae2a2e957 100644 --- a/src/locales/es/settings.json +++ b/src/locales/es/settings.json @@ -193,6 +193,9 @@ "Show all": "Mostrar todo" } }, + "Comfy_NodeBadge_ShowApiPricing": { + "name": "Mostrar insignia de precios de nodo API" + }, "Comfy_NodeSearchBoxImpl": { "name": "Implementación de la caja de búsqueda de nodos", "options": { diff --git a/src/locales/fr/main.json b/src/locales/fr/main.json index a34c46c4c..319be4d03 100644 --- a/src/locales/fr/main.json +++ b/src/locales/fr/main.json @@ -1001,6 +1001,7 @@ }, "settingsCategories": { "3D": "3D", + "API Nodes": "Nœuds API", "About": "À Propos", "Appearance": "Apparence", "BrushAdjustment": "Ajustement de Brosse", diff --git a/src/locales/fr/settings.json b/src/locales/fr/settings.json index f86ee2e6d..756c0cdde 100644 --- a/src/locales/fr/settings.json +++ b/src/locales/fr/settings.json @@ -193,6 +193,9 @@ "Show all": "Afficher tout" } }, + "Comfy_NodeBadge_ShowApiPricing": { + "name": "Afficher l’insigne de tarification API du nœud" + }, "Comfy_NodeSearchBoxImpl": { "name": "Implémentation de la boîte de recherche de nœud", "options": { diff --git a/src/locales/ja/main.json b/src/locales/ja/main.json index fdacb562a..e9031e653 100644 --- a/src/locales/ja/main.json +++ b/src/locales/ja/main.json @@ -1001,6 +1001,7 @@ }, "settingsCategories": { "3D": "3D", + "API Nodes": "APIノード", "About": "情報", "Appearance": "外観", "BrushAdjustment": "ブラシ調整", diff --git a/src/locales/ja/settings.json b/src/locales/ja/settings.json index 5cc75653d..400ef71dc 100644 --- a/src/locales/ja/settings.json +++ b/src/locales/ja/settings.json @@ -193,6 +193,9 @@ "Show all": "すべて表示" } }, + "Comfy_NodeBadge_ShowApiPricing": { + "name": "APIノードの料金バッジを表示" + }, "Comfy_NodeSearchBoxImpl": { "name": "ノード検索ボックスの実装", "options": { diff --git a/src/locales/ko/main.json b/src/locales/ko/main.json index f55d4077b..8cd1f252c 100644 --- a/src/locales/ko/main.json +++ b/src/locales/ko/main.json @@ -1001,6 +1001,7 @@ }, "settingsCategories": { "3D": "3D", + "API Nodes": "API 노드", "About": "정보", "Appearance": "모양", "BrushAdjustment": "브러시 조정", diff --git a/src/locales/ko/settings.json b/src/locales/ko/settings.json index cc8f86f04..4a857e9a0 100644 --- a/src/locales/ko/settings.json +++ b/src/locales/ko/settings.json @@ -193,6 +193,9 @@ "Show all": "모두 표시" } }, + "Comfy_NodeBadge_ShowApiPricing": { + "name": "API 노드 가격 배지 표시" + }, "Comfy_NodeSearchBoxImpl": { "name": "노드 검색 상자 구현", "options": { diff --git a/src/locales/ru/main.json b/src/locales/ru/main.json index 723d620c1..53c11eee9 100644 --- a/src/locales/ru/main.json +++ b/src/locales/ru/main.json @@ -1001,6 +1001,7 @@ }, "settingsCategories": { "3D": "3D", + "API Nodes": "API-узлы", "About": "О программе", "Appearance": "Внешний вид", "BrushAdjustment": "Настройка кисти", diff --git a/src/locales/ru/settings.json b/src/locales/ru/settings.json index 4004e856b..175bd1455 100644 --- a/src/locales/ru/settings.json +++ b/src/locales/ru/settings.json @@ -193,6 +193,9 @@ "Show all": "Показать все" } }, + "Comfy_NodeBadge_ShowApiPricing": { + "name": "Показать значок стоимости узла API" + }, "Comfy_NodeSearchBoxImpl": { "name": "Реализация поискового поля нод", "options": { diff --git a/src/locales/zh/main.json b/src/locales/zh/main.json index 33dd8f4df..744976f24 100644 --- a/src/locales/zh/main.json +++ b/src/locales/zh/main.json @@ -1001,6 +1001,7 @@ }, "settingsCategories": { "3D": "3D", + "API Nodes": "API 节点", "About": "关于", "Appearance": "外观", "BrushAdjustment": "画笔调整", diff --git a/src/locales/zh/settings.json b/src/locales/zh/settings.json index 737eb2440..1d1ebeb01 100644 --- a/src/locales/zh/settings.json +++ b/src/locales/zh/settings.json @@ -193,6 +193,9 @@ "Show all": "显示全部" } }, + "Comfy_NodeBadge_ShowApiPricing": { + "name": "显示 API 节点定价徽章" + }, "Comfy_NodeSearchBoxImpl": { "name": "节点搜索框", "options": { diff --git a/src/schemas/apiSchema.ts b/src/schemas/apiSchema.ts index 4b5a81ea0..b0615f9b4 100644 --- a/src/schemas/apiSchema.ts +++ b/src/schemas/apiSchema.ts @@ -421,6 +421,7 @@ const zSettings = z.object({ 'Comfy.NodeBadge.NodeSourceBadgeMode': zNodeBadgeMode, 'Comfy.NodeBadge.NodeIdBadgeMode': zNodeBadgeMode, 'Comfy.NodeBadge.NodeLifeCycleBadgeMode': zNodeBadgeMode, + 'Comfy.NodeBadge.ShowApiPricing': z.boolean(), 'Comfy.QueueButton.BatchCountLimit': z.number(), 'Comfy.Queue.MaxHistoryItems': z.number(), 'Comfy.Keybinding.UnsetBindings': z.array(zKeybinding), diff --git a/src/types/apiNodeTypes.ts b/src/types/apiNodeTypes.ts index 44386ac79..e60db27b8 100644 --- a/src/types/apiNodeTypes.ts +++ b/src/types/apiNodeTypes.ts @@ -2,3 +2,23 @@ export interface ApiNodeCost { name: string cost: number } + +/** + * Information about an API node's cost and pricing details + */ +export interface ApiNodeCostData { + /** The vendor/company providing the API service (e.g., 'OpenAI', 'Stability') */ + vendor: string + /** The human-readable name of the node as displayed in the UI */ + nodeName: string + /** Parameters that affect pricing (e.g., 'size | quality', 'duration', '-' if none) */ + pricingParams: string + /** The price range per run (e.g., '$0.05', '$0.04 x n', 'dynamic') */ + pricePerRunRange: string + /** Formatted price string for display in the UI */ + displayPrice: string + /** URL to the vendor's pricing documentation page */ + rateDocumentationUrl?: string +} + +export type ApiNodeCostRecord = Record