diff --git a/packages/cli/src/ui/components/HistoryItemDisplay.test.tsx b/packages/cli/src/ui/components/HistoryItemDisplay.test.tsx index d0c28fa11f..f603e9616a 100644 --- a/packages/cli/src/ui/components/HistoryItemDisplay.test.tsx +++ b/packages/cli/src/ui/components/HistoryItemDisplay.test.tsx @@ -55,6 +55,18 @@ describe('', () => { expect(lastFrame()).toContain('/theme'); }); + it('renders InfoMessage for "info" type with multi-line text', () => { + const item: HistoryItem = { + ...baseItem, + type: MessageType.INFO, + text: '⚡ Line 1\n⚡ Line 2\n⚡ Line 3', + }; + const { lastFrame } = renderWithProviders( + , + ); + expect(lastFrame()).toMatchSnapshot(); + }); + it('renders StatsDisplay for "stats" type', () => { const item: HistoryItem = { ...baseItem, diff --git a/packages/cli/src/ui/components/__snapshots__/HistoryItemDisplay.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/HistoryItemDisplay.test.tsx.snap index de25e153e7..b9c4b5e8bb 100644 --- a/packages/cli/src/ui/components/__snapshots__/HistoryItemDisplay.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/HistoryItemDisplay.test.tsx.snap @@ -1,5 +1,12 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[` > renders InfoMessage for "info" type with multi-line text 1`] = ` +" +ℹ ⚡ Line 1 + ⚡ Line 2 + ⚡ Line 3" +`; + exports[` > should render a full gemini item when using availableTerminalHeightGemini 1`] = ` "✦ Example code block: 1 Line 1 diff --git a/packages/cli/src/ui/components/messages/InfoMessage.tsx b/packages/cli/src/ui/components/messages/InfoMessage.tsx index b8da1a4e20..2d8fd2564b 100644 --- a/packages/cli/src/ui/components/messages/InfoMessage.tsx +++ b/packages/cli/src/ui/components/messages/InfoMessage.tsx @@ -22,10 +22,12 @@ export const InfoMessage: React.FC = ({ text }) => { {prefix} - - - - + + {text.split('\n').map((line, index) => ( + + + + ))} ); diff --git a/packages/cli/src/ui/hooks/useQuotaAndFallback.ts b/packages/cli/src/ui/hooks/useQuotaAndFallback.ts index 194f5f27fc..3bdaff4295 100644 --- a/packages/cli/src/ui/hooks/useQuotaAndFallback.ts +++ b/packages/cli/src/ui/hooks/useQuotaAndFallback.ts @@ -66,42 +66,57 @@ export function useQuotaAndFallback({ if (error instanceof TerminalQuotaError) { // Pro Quota specific messages (Interactive) if (isPaidTier) { - message = `⚡ You have reached your daily ${failedModel} quota limit. -⚡ You can choose to authenticate with a paid API key or continue with the fallback model. -⚡ To continue accessing the ${failedModel} model today, consider using /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey`; + message = [ + `⚡ You have reached your daily ${failedModel} quota limit.`, + `⚡ You can choose to authenticate with a paid API key or continue with the fallback model.`, + `⚡ To continue accessing the ${failedModel} model today, consider using /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey}`, + ].join('\n'); } else { - message = `⚡ You have reached your daily ${failedModel} quota limit. -⚡ You can choose to authenticate with a paid API key or continue with the fallback model. -⚡ To increase your limits, upgrade to a Gemini Code Assist Standard or Enterprise plan with higher limits at https://goo.gle/set-up-gemini-code-assist -⚡ Or you can utilize a Gemini API Key. See: https://goo.gle/gemini-cli-docs-auth#gemini-api-key -⚡ You can switch authentication methods by typing /auth`; + message = [ + `⚡ You have reached your daily ${failedModel} quota limit.`, + `⚡ You can choose to authenticate with a paid API key or continue with the fallback model.`, + `⚡ To increase your limits, upgrade to a Gemini Code Assist Standard or Enterprise plan with higher limits at https://goo.gle/set-up-gemini-code-assist`, + `⚡ Or you can utilize a Gemini API Key. See: https://goo.gle/gemini-cli-docs-auth#gemini-api-key`, + `⚡ You can switch authentication methods by typing /auth`, + ].join('\n'); } } else if (error instanceof RetryableQuotaError) { // Short term quota retries exhausted (Automatic fallback) - const actionMessage = `⚡ Your requests are being throttled right now due to server being at capacity for ${failedModel}.\n⚡ Automatically switching from ${failedModel} to ${fallbackModel} for the remainder of this session.`; + const actionMessage = [ + `⚡ Your requests are being throttled right now due to server being at capacity for ${failedModel}.`, + `⚡ Automatically switching from ${failedModel} to ${fallbackModel} for the remainder of this session.`, + ].join('\n'); if (isPaidTier) { - message = `${actionMessage} -⚡ To continue accessing the ${failedModel} model, retry your request after some time or consider using /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey`; + message = [ + actionMessage, + `⚡ To continue accessing the ${failedModel} model, retry your request after some time or consider using /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey}`, + ].join('\n'); } else { - message = `${actionMessage} -⚡ Retry your requests after some time. Otherwise consider upgrading to a Gemini Code Assist Standard or Enterprise plan with higher limits at https://goo.gle/set-up-gemini-code-assist -⚡ You can switch authentication methods by typing /auth`; + message = [ + actionMessage, + `⚡ Retry your requests after some time. Otherwise consider upgrading to a Gemini Code Assist Standard or Enterprise plan with higher limits at https://goo.gle/set-up-gemini-code-assist`, + `⚡ You can switch authentication methods by typing /auth`, + ].join('\n'); } } else { // Other errors (Automatic fallback) const actionMessage = `⚡ Automatically switching from ${failedModel} to ${fallbackModel} for faster responses for the remainder of this session.`; if (isPaidTier) { - message = `${actionMessage} -⚡ Your requests are being throttled temporarily due to server being at capacity for ${failedModel} or there is a service outage. -⚡ To continue accessing the ${failedModel} model, you can retry your request after some time or consider using /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey`; + message = [ + actionMessage, + `⚡ Your requests are being throttled temporarily due to server being at capacity for ${failedModel} or there is a service outage.`, + `⚡ To continue accessing the ${failedModel} model, you can retry your request after some time or consider using /auth to switch to using a paid API key from AI Studio at https://aistudio.google.com/apikey}`, + ].join('\n'); } else { - message = `${actionMessage} -⚡ Your requests are being throttled temporarily due to server being at capacity for ${failedModel} or there is a service outage. -⚡ To avoid being throttled, you can retry your request after some time or upgrade to a Gemini Code Assist Standard or Enterprise plan with higher limits at https://goo.gle/set-up-gemini-code-assist -⚡ Or you can utilize a Gemini API Key. See: https://goo.gle/gemini-cli-docs-auth#gemini-api-key -⚡ You can switch authentication methods by typing /auth`; + message = [ + actionMessage, + `⚡ Your requests are being throttled temporarily due to server being at capacity for ${failedModel} or there is a service outage.`, + `⚡ To avoid being throttled, you can retry your request after some time or upgrade to a Gemini Code Assist Standard or Enterprise plan with higher limits at https://goo.gle/set-up-gemini-code-assist`, + `⚡ Or you can utilize a Gemini API Key. See: https://goo.gle/gemini-cli-docs-auth#gemini-api-key`, + `⚡ You can switch authentication methods by typing /auth`, + ].join('\n'); } }