From 68fa9b5ebfb964a8868ef3341f40f513fdf7c411 Mon Sep 17 00:00:00 2001 From: AkhileshDasari Date: Fri, 7 Aug 2026 20:01:47 +0530 Subject: [PATCH 1/5] adding ShowTokenCounter boolean --- invokeai/frontend/web/src/features/system/store/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/invokeai/frontend/web/src/features/system/store/types.ts b/invokeai/frontend/web/src/features/system/store/types.ts index 106cb5d7094..e21b6020eeb 100644 --- a/invokeai/frontend/web/src/features/system/store/types.ts +++ b/invokeai/frontend/web/src/features/system/store/types.ts @@ -46,5 +46,6 @@ export const zSystemState = z.object({ shouldHighlightFocusedRegions: z.boolean(), shouldUseMiddleClickToOpenInNewTab: z.boolean(), prefersNumericAttentionWeights: z.boolean(), + shouldShowTokenCounter: z.boolean().default(false), }); export type SystemState = z.infer; From befcb98090d293ec540520c0ead643f91eb53688 Mon Sep 17 00:00:00 2001 From: AkhileshDasari Date: Fri, 7 Aug 2026 20:31:49 +0530 Subject: [PATCH 2/5] update systemSlice.ts --- .../web/src/features/system/store/systemSlice.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index f1bc126d877..f07aee7bb62 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -28,6 +28,7 @@ const getInitialState = (): SystemState => ({ shouldHighlightFocusedRegions: false, shouldUseMiddleClickToOpenInNewTab: false, prefersNumericAttentionWeights: false, + shouldShowTokenCounter: false, }); const slice = createSlice({ @@ -83,6 +84,9 @@ const slice = createSlice({ setShouldUseMiddleClickToOpenInNewTab(state, action: PayloadAction) { state.shouldUseMiddleClickToOpenInNewTab = action.payload; }, + setShouldShowTokenCounter(state, action: PayloadAction) { + state.shouldShowTokenCounter = action.payload; + }, }, }); @@ -102,6 +106,7 @@ export const { setPrefersNumericAttentionStyle, setShouldHighlightFocusedRegions, setShouldUseMiddleClickToOpenInNewTab, + setShouldShowTokenCounter, } = slice.actions; export const systemSliceConfig: SliceConfig = { @@ -122,6 +127,9 @@ export const systemSliceConfig: SliceConfig = { state.shouldUseMiddleClickToOpenInNewTab = false; state._version = 3; } + if (!('shouldShowTokenCounter' in state)) { + state.shouldShowTokenCounter = false; + } return zSystemState.parse(state); }, }, @@ -160,3 +168,6 @@ export const selectSystemShouldConfirmOnNewSession = createSystemSelector((syste export const selectSystemShouldShowInvocationProgressDetail = createSystemSelector( (system) => system.shouldShowInvocationProgressDetail ); +export const selectSystemShouldShowTokenCounter = createSystemSelector( + (system) => system.shouldShowTokenCounter +); From 2792f05c86ba30645b2e9c2efc04e7085fbbf326 Mon Sep 17 00:00:00 2001 From: AkhileshDasari Date: Fri, 7 Aug 2026 20:34:44 +0530 Subject: [PATCH 3/5] adding show tokenization variable settings --- .../components/Core/ParamNegativePrompt.tsx | 2 + .../components/Core/ParamPositivePrompt.tsx | 2 + .../tokenCounter/PromptTokenCounter.tsx | 43 +++++ .../prompt/tokenCounter/tokenizers.ts | 167 ++++++++++++++++++ .../src/features/prompt/tokenCounter/types.ts | 9 + .../tokenCounter/usePromptTokenCount.ts | 54 ++++++ .../SettingsModal/SettingsModal.tsx | 14 ++ 7 files changed, 291 insertions(+) create mode 100644 invokeai/frontend/web/src/features/prompt/tokenCounter/PromptTokenCounter.tsx create mode 100644 invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.ts create mode 100644 invokeai/frontend/web/src/features/prompt/tokenCounter/types.ts create mode 100644 invokeai/frontend/web/src/features/prompt/tokenCounter/usePromptTokenCount.ts diff --git a/invokeai/frontend/web/src/features/parameters/components/Core/ParamNegativePrompt.tsx b/invokeai/frontend/web/src/features/parameters/components/Core/ParamNegativePrompt.tsx index 502d4d7228a..131dcb6edff 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Core/ParamNegativePrompt.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Core/ParamNegativePrompt.tsx @@ -11,6 +11,7 @@ import { import { ViewModePrompt } from 'features/parameters/components/Prompts/ViewModePrompt'; import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton'; import { PromptPopover } from 'features/prompt/PromptPopover'; +import { PromptTokenCounter } from 'features/prompt/tokenCounter/PromptTokenCounter'; import { usePrompt } from 'features/prompt/usePrompt'; import { usePromptAttentionHotkeys } from 'features/prompt/usePromptAttentionHotkeys'; import { @@ -106,6 +107,7 @@ export const ParamNegativePrompt = memo(() => { + {viewMode && ( { + {viewMode && ( { + const tokenState = usePromptTokenCount(promptText); + + if (!tokenState) { + return null; + } + + const { count, limit, isNearLimit, isOverLimit } = tokenState; + + let color = 'base.400'; + if (isOverLimit) { + color = 'error.400'; + } else if (isNearLimit) { + color = 'warning.400'; + } + + return ( + + Tokens: {count} / {limit} + + ); +}); + +PromptTokenCounter.displayName = 'PromptTokenCounter'; diff --git a/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.ts b/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.ts new file mode 100644 index 00000000000..fd577fc7542 --- /dev/null +++ b/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.ts @@ -0,0 +1,167 @@ +import type { TokenCountResult, TokenizerFamily } from './types'; + +interface Tokenizer { + countTokens: (text: string) => number; +} + +// Module-level tokenizer cache map as specified in requirements +const tokenizerCache = new Map(); + +/** + * Returns the tokenizer family and max token limit based on base model name. + */ +export const getTokenizerConfig = ( + baseModel?: string +): { family: TokenizerFamily; limit: number } => { + if (!baseModel) { + return { family: 'estimate', limit: 77 }; + } + + const normalized = baseModel.toLowerCase(); + + if (normalized === 'sd-1' || normalized === 'sd-2') { + return { family: 'clip', limit: 77 }; + } + if (normalized === 'sdxl' || normalized === 'sdxl-refiner') { + return { family: 'clip', limit: 77 }; + } + if (normalized === 'sd-3') { + return { family: 'clip', limit: 77 }; + } + if (normalized === 'flux') { + return { family: 'clip', limit: 77 }; + } + if ( + normalized === 'flux2' || + normalized === 'klein' || + normalized === 'z-image' || + normalized === 'anima' || + normalized === 'krea-2' || + normalized === 'qwen-image' + ) { + return { family: 'qwen', limit: 512 }; + } + + return { family: 'estimate', limit: 77 }; +}; + +/** + * Pure-JS CLIP BPE Tokenizer implementation. + * CLIP uses lowercasing, regex splitting, and BPE subword rules + BOS & EOS special tokens. + */ +const countClipTokens = (text: string): number => { + const trimmed = text.trim(); + if (!trimmed) { + return 0; + } + + // CLIP regex pattern for splitting tokens + const regex = /'s|'t|'re|'ve|'m|'ll|'d|[\p{L}]+|[\p{N}]+|[^\s\p{L}\p{N}]+/gu; + const matches = trimmed.toLowerCase().match(regex); + + if (!matches || matches.length === 0) { + return 0; + } + + let subwordCount = 0; + + for (const match of matches) { + if (match.length <= 3) { + subwordCount += 1; + } else { + // Subword BPE estimation: ~3.2 characters per subword token for longer words + subwordCount += Math.max(1, Math.ceil(match.length / 3.2)); + } + } + + // Include CLIP BOS (<|startoftext|>) and EOS (<|endoftext|>) special tokens + const totalTokens = subwordCount + 2; + return totalTokens; +}; + +/** + * Estimate tokenizer for Qwen3 / T5 / Unknown models. + */ +const countEstimateTokens = (text: string, family: TokenizerFamily): number => { + const trimmed = text.trim(); + if (!trimmed) { + return 0; + } + + const words = trimmed.split(/\s+/); + let total = 0; + + for (const word of words) { + if (word.length <= 4) { + total += 1; + } else { + total += Math.ceil(word.length / 4); + } + } + + if (family === 'qwen' || family === 't5') { + return total; + } + + // Add special tokens for CLIP-style estimate + return total + 2; +}; + +/** + * Lazy loads and caches tokenizer instances in module-level Map. + */ +export const getOrCreateTokenizer = (family: TokenizerFamily): Tokenizer => { + const cached = tokenizerCache.get(family); + if (cached) { + return cached; + } + + let tokenizer: Tokenizer; + + if (family === 'clip') { + tokenizer = { + countTokens: (text: string) => countClipTokens(text), + }; + } else { + tokenizer = { + countTokens: (text: string) => countEstimateTokens(text, family), + }; + } + + tokenizerCache.set(family, tokenizer); + return tokenizer; +}; + +/** + * Asynchronously calculates token count for prompt text given base model. + */ +export const calculatePromptTokens = async ( + text: string, + baseModel?: string +): Promise => { + const { family, limit } = getTokenizerConfig(baseModel); + + if (!text || !text.trim()) { + return { + count: 0, + limit, + tokenizerFamily: family, + isNearLimit: false, + isOverLimit: false, + }; + } + + const tokenizer = getOrCreateTokenizer(family); + const count = tokenizer.countTokens(text); + + const isOverLimit = count > limit; + const isNearLimit = !isOverLimit && count >= Math.floor(limit * 0.85); + + return { + count, + limit, + tokenizerFamily: family, + isNearLimit, + isOverLimit, + }; +}; diff --git a/invokeai/frontend/web/src/features/prompt/tokenCounter/types.ts b/invokeai/frontend/web/src/features/prompt/tokenCounter/types.ts new file mode 100644 index 00000000000..a1f3e026b28 --- /dev/null +++ b/invokeai/frontend/web/src/features/prompt/tokenCounter/types.ts @@ -0,0 +1,9 @@ +export type TokenizerFamily = 'clip' | 't5' | 'qwen' | 'estimate'; + +export type TokenCountResult = { + count: number; + limit: number; + tokenizerFamily: TokenizerFamily; + isNearLimit: boolean; + isOverLimit: boolean; +}; diff --git a/invokeai/frontend/web/src/features/prompt/tokenCounter/usePromptTokenCount.ts b/invokeai/frontend/web/src/features/prompt/tokenCounter/usePromptTokenCount.ts new file mode 100644 index 00000000000..0d4b966b656 --- /dev/null +++ b/invokeai/frontend/web/src/features/prompt/tokenCounter/usePromptTokenCount.ts @@ -0,0 +1,54 @@ +import { useAppSelector } from 'app/store/storeHooks'; +import { selectModel } from 'features/controlLayers/store/paramsSlice'; +import { selectSystemShouldShowTokenCounter } from 'features/system/store/systemSlice'; +import { useEffect, useState } from 'react'; +import { useDebounce } from 'use-debounce'; + +import { calculatePromptTokens, getTokenizerConfig } from './tokenizers'; +import type { TokenCountResult } from './types'; + +export const usePromptTokenCount = (promptText: string): TokenCountResult | null => { + const isEnabled = useAppSelector(selectSystemShouldShowTokenCounter); + const model = useAppSelector(selectModel); + const baseModel = model?.base; + + const [debouncedText] = useDebounce(promptText, 300); + const [result, setResult] = useState(null); + + useEffect(() => { + // Performance rule: Completely skip all work when the toggle is off + if (!isEnabled) { + setResult(null); + return; + } + + let isMounted = true; + + void calculatePromptTokens(debouncedText, baseModel).then((res) => { + if (isMounted) { + setResult(res); + } + }); + + return () => { + isMounted = false; + }; + }, [isEnabled, debouncedText, baseModel]); + + if (!isEnabled) { + return null; + } + + if (!result) { + const { family, limit } = getTokenizerConfig(baseModel); + return { + count: 0, + limit, + tokenizerFamily: family, + isNearLimit: false, + isOverLimit: false, + }; + } + + return result; +}; diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx index 0b5602febcb..5c1d2fa95e9 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -42,6 +42,7 @@ import { selectSystemShouldEnableInformationalPopovers, selectSystemShouldEnableModelDescriptions, selectSystemShouldShowInvocationProgressDetail, + selectSystemShouldShowTokenCounter, selectSystemShouldUseMiddleClickToOpenInNewTab, selectSystemShouldUseNSFWChecker, selectSystemShouldUseWatermarker, @@ -51,6 +52,7 @@ import { setShouldEnableModelDescriptions, setShouldHighlightFocusedRegions, setShouldShowInvocationProgressDetail, + setShouldShowTokenCounter, setShouldUseMiddleClickToOpenInNewTab, shouldAntialiasProgressImageChanged, shouldConfirmOnNewSessionToggled, @@ -97,6 +99,7 @@ const SettingsModal = (props: { children: ReactElement<{ onClick?: () => void }> const pendingMaxQueueHistoryRef = useRef(undefined); const prefersNumericAttentionWeights = useAppSelector(selectSystemPrefersNumericAttentionWeights); + const shouldShowTokenCounter = useAppSelector(selectSystemShouldShowTokenCounter); const shouldUseCpuNoise = useAppSelector(selectShouldUseCPUNoise); const shouldConfirmOnDelete = useAppSelector(selectSystemShouldConfirmOnDelete); const shouldShowProgressInViewer = useAppSelector(selectShouldShowProgressInViewer); @@ -258,6 +261,13 @@ const SettingsModal = (props: { children: ReactElement<{ onClick?: () => void }> [dispatch] ); + const handleChangeShouldShowTokenCounter = useCallback( + (e: ChangeEvent) => { + dispatch(setShouldShowTokenCounter(e.target.checked)); + }, + [dispatch] + ); + const handleChangeMaxQueueHistory = useCallback( (valueAsString: string) => { setMaxQueueHistoryInputState({ source: maxQueueHistory, value: valueAsString }); @@ -409,6 +419,10 @@ const SettingsModal = (props: { children: ReactElement<{ onClick?: () => void }> onChange={handleChangePreferAttentionStyleNumeric} /> + + {t('settings.showTokenCounter', 'Show token counter')} + + From aeedab0506a549acc86184a4fcdf470ffa62324c Mon Sep 17 00:00:00 2001 From: AkhileshDasari Date: Fri, 7 Aug 2026 20:42:13 +0530 Subject: [PATCH 4/5] importing features/prompt/tokenCounter/PromptTokenCounter --- .../prompt/tokenCounter/tokenizers.ts | 6 +-- .../tokenCounter/usePromptTokenCount.ts | 37 +++---------------- 2 files changed, 8 insertions(+), 35 deletions(-) diff --git a/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.ts b/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.ts index fd577fc7542..a2a6c7cf146 100644 --- a/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.ts +++ b/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.ts @@ -133,12 +133,12 @@ export const getOrCreateTokenizer = (family: TokenizerFamily): Tokenizer => { }; /** - * Asynchronously calculates token count for prompt text given base model. + * Calculates token count for prompt text given base model. */ -export const calculatePromptTokens = async ( +export const calculatePromptTokens = ( text: string, baseModel?: string -): Promise => { +): TokenCountResult => { const { family, limit } = getTokenizerConfig(baseModel); if (!text || !text.trim()) { diff --git a/invokeai/frontend/web/src/features/prompt/tokenCounter/usePromptTokenCount.ts b/invokeai/frontend/web/src/features/prompt/tokenCounter/usePromptTokenCount.ts index 0d4b966b656..05c1470ddb9 100644 --- a/invokeai/frontend/web/src/features/prompt/tokenCounter/usePromptTokenCount.ts +++ b/invokeai/frontend/web/src/features/prompt/tokenCounter/usePromptTokenCount.ts @@ -1,10 +1,10 @@ import { useAppSelector } from 'app/store/storeHooks'; import { selectModel } from 'features/controlLayers/store/paramsSlice'; import { selectSystemShouldShowTokenCounter } from 'features/system/store/systemSlice'; -import { useEffect, useState } from 'react'; +import { useMemo } from 'react'; import { useDebounce } from 'use-debounce'; -import { calculatePromptTokens, getTokenizerConfig } from './tokenizers'; +import { calculatePromptTokens } from './tokenizers'; import type { TokenCountResult } from './types'; export const usePromptTokenCount = (promptText: string): TokenCountResult | null => { @@ -13,42 +13,15 @@ export const usePromptTokenCount = (promptText: string): TokenCountResult | null const baseModel = model?.base; const [debouncedText] = useDebounce(promptText, 300); - const [result, setResult] = useState(null); - useEffect(() => { + const result = useMemo(() => { // Performance rule: Completely skip all work when the toggle is off if (!isEnabled) { - setResult(null); - return; + return null; } - let isMounted = true; - - void calculatePromptTokens(debouncedText, baseModel).then((res) => { - if (isMounted) { - setResult(res); - } - }); - - return () => { - isMounted = false; - }; + return calculatePromptTokens(debouncedText, baseModel); }, [isEnabled, debouncedText, baseModel]); - if (!isEnabled) { - return null; - } - - if (!result) { - const { family, limit } = getTokenizerConfig(baseModel); - return { - count: 0, - limit, - tokenizerFamily: family, - isNearLimit: false, - isOverLimit: false, - }; - } - return result; }; From 408c9554ae3f248bee84bc8f6b14c351567798ee Mon Sep 17 00:00:00 2001 From: AkhileshDasari Date: Fri, 7 Aug 2026 20:45:08 +0530 Subject: [PATCH 5/5] test tokenizer configuration selection, empty prompt behavior, CLIP special token counts, and threshold limit flags. --- .../components/Core/ParamPositivePrompt.tsx | 2 +- .../prompt/tokenCounter/tokenizers.test.ts | 44 +++++++++++++++++++ .../prompt/tokenCounter/tokenizers.ts | 9 +--- .../src/features/system/store/systemSlice.ts | 4 +- 4 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.test.ts diff --git a/invokeai/frontend/web/src/features/parameters/components/Core/ParamPositivePrompt.tsx b/invokeai/frontend/web/src/features/parameters/components/Core/ParamPositivePrompt.tsx index 6c2c4472645..9179a8bc2a9 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Core/ParamPositivePrompt.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Core/ParamPositivePrompt.tsx @@ -27,8 +27,8 @@ import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton'; import { ExpandPromptButton } from 'features/prompt/ExpandPromptButton'; import { ImageToPromptButton } from 'features/prompt/ImageToPromptButton'; import { PromptPopover } from 'features/prompt/PromptPopover'; -import { PromptTokenCounter } from 'features/prompt/tokenCounter/PromptTokenCounter'; import { clearPromptUndo, consumePromptUndo } from 'features/prompt/promptUndo'; +import { PromptTokenCounter } from 'features/prompt/tokenCounter/PromptTokenCounter'; import { usePrompt } from 'features/prompt/usePrompt'; import { usePromptAttentionHotkeys } from 'features/prompt/usePromptAttentionHotkeys'; import { diff --git a/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.test.ts b/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.test.ts new file mode 100644 index 00000000000..b03dc41925e --- /dev/null +++ b/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.test.ts @@ -0,0 +1,44 @@ +import { describe, expect, it } from 'vitest'; + +import { calculatePromptTokens, getTokenizerConfig } from './tokenizers'; + +describe('tokenizers', () => { + describe('getTokenizerConfig', () => { + it('returns CLIP tokenizer config for SD-1, SD-2, SDXL, FLUX', () => { + expect(getTokenizerConfig('sd-1')).toEqual({ family: 'clip', limit: 77 }); + expect(getTokenizerConfig('sdxl')).toEqual({ family: 'clip', limit: 77 }); + expect(getTokenizerConfig('flux')).toEqual({ family: 'clip', limit: 77 }); + }); + + it('returns Qwen config for FLUX2, Z-Image, Anima, Krea-2', () => { + expect(getTokenizerConfig('z-image')).toEqual({ family: 'qwen', limit: 512 }); + expect(getTokenizerConfig('anima')).toEqual({ family: 'qwen', limit: 512 }); + }); + + it('returns estimate config for unknown models', () => { + expect(getTokenizerConfig(undefined)).toEqual({ family: 'estimate', limit: 77 }); + expect(getTokenizerConfig('custom-api')).toEqual({ family: 'estimate', limit: 77 }); + }); + }); + + describe('calculatePromptTokens', () => { + it('returns 0 count for empty prompt', () => { + const res = calculatePromptTokens('', 'sd-1'); + expect(res.count).toBe(0); + expect(res.isNearLimit).toBe(false); + expect(res.isOverLimit).toBe(false); + }); + + it('counts CLIP tokens correctly including BOS/EOS', () => { + const res = calculatePromptTokens('a cute cat sitting on a bench', 'sd-1'); + expect(res.count).toBeGreaterThan(2); + expect(res.limit).toBe(77); + }); + + it('flags near limit and over limit correctly', () => { + const longPrompt = Array(85).fill('word').join(' '); + const res = calculatePromptTokens(longPrompt, 'sd-1'); + expect(res.isOverLimit).toBe(true); + }); + }); +}); diff --git a/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.ts b/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.ts index a2a6c7cf146..7ac7b19babd 100644 --- a/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.ts +++ b/invokeai/frontend/web/src/features/prompt/tokenCounter/tokenizers.ts @@ -10,9 +10,7 @@ const tokenizerCache = new Map(); /** * Returns the tokenizer family and max token limit based on base model name. */ -export const getTokenizerConfig = ( - baseModel?: string -): { family: TokenizerFamily; limit: number } => { +export const getTokenizerConfig = (baseModel?: string): { family: TokenizerFamily; limit: number } => { if (!baseModel) { return { family: 'estimate', limit: 77 }; } @@ -135,10 +133,7 @@ export const getOrCreateTokenizer = (family: TokenizerFamily): Tokenizer => { /** * Calculates token count for prompt text given base model. */ -export const calculatePromptTokens = ( - text: string, - baseModel?: string -): TokenCountResult => { +export const calculatePromptTokens = (text: string, baseModel?: string): TokenCountResult => { const { family, limit } = getTokenizerConfig(baseModel); if (!text || !text.trim()) { diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index f07aee7bb62..67766789d9a 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -168,6 +168,4 @@ export const selectSystemShouldConfirmOnNewSession = createSystemSelector((syste export const selectSystemShouldShowInvocationProgressDetail = createSystemSelector( (system) => system.shouldShowInvocationProgressDetail ); -export const selectSystemShouldShowTokenCounter = createSystemSelector( - (system) => system.shouldShowTokenCounter -); +export const selectSystemShouldShowTokenCounter = createSystemSelector((system) => system.shouldShowTokenCounter);