From 447a0e1940b45bb3edab79426840a8d64f96fb60 Mon Sep 17 00:00:00 2001 From: Carl-Robert Linnupuu Date: Tue, 13 May 2025 11:18:39 +0100 Subject: [PATCH] fix: npe on quota exceeded error (fixes #1007) --- .../chat/ui/ChatMessageResponseBody.java | 131 +++++++----------- .../factory/OpenAIRequestFactory.kt | 2 - .../CompletionRequestProviderTest.kt | 4 +- 3 files changed, 51 insertions(+), 86 deletions(-) diff --git a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ChatMessageResponseBody.java b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ChatMessageResponseBody.java index df27d0dd..3c73f3ba 100644 --- a/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ChatMessageResponseBody.java +++ b/src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ui/ChatMessageResponseBody.java @@ -57,6 +57,7 @@ import javax.swing.JEditorPane; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextPane; +import javax.swing.event.HyperlinkListener; import org.jetbrains.annotations.NotNull; public class ChatMessageResponseBody extends JPanel { @@ -153,98 +154,31 @@ public class ChatMessageResponseBody extends JPanel { } public void displayMissingCredential() { - ApplicationManager.getApplication().invokeLater(() -> { - if (loadingLabel.isVisible()) { - loadingLabel.setVisible(false); + String message = "API key not provided. Open Settings to set one."; + displayErrorMessage(message, e -> { + if (e.getEventType() == ACTIVATED) { + ShowSettingsUtil.getInstance() + .showSettingsDialog(project, GeneralSettingsConfigurable.class); } - - if (webpageListPanel != null) { - webpageListPanel.setVisible(false); - } - - if (currentlyProcessedTextPane == null) { - currentlyProcessedTextPane = createTextPane(""); - contentPanel.add(currentlyProcessedTextPane); - } - - var message = "API key not provided. Open Settings to set one."; - if (currentlyProcessedTextPane != null) { - currentlyProcessedTextPane.setVisible(true); - currentlyProcessedTextPane.setText( - format("

%s

", - message)); - currentlyProcessedTextPane.addHyperlinkListener(e -> { - if (e.getEventType() == ACTIVATED) { - ShowSettingsUtil.getInstance() - .showSettingsDialog(project, GeneralSettingsConfigurable.class); - } - }); - hideCaret(); - } - - revalidate(); - repaint(); }); } public void displayQuotaExceeded() { - ApplicationManager.getApplication().invokeLater(() -> { - if (loadingLabel.isVisible()) { - loadingLabel.setVisible(false); + String message = "You exceeded your current quota, please check your plan and billing details, " + + "or change to a different LLM provider."; + displayErrorMessage(message, e -> { + if (e.getEventType() == ACTIVATED) { + ShowSettingsUtil.getInstance() + .showSettingsDialog(project, GeneralSettingsConfigurable.class); + TelemetryAction.IDE_ACTION.createActionMessage() + .property("action", ActionType.CHANGE_PROVIDER.name()) + .send(); } - - if (webpageListPanel != null) { - webpageListPanel.setVisible(false); - } - - if (currentlyProcessedTextPane != null) { - currentlyProcessedTextPane.setVisible(true); - currentlyProcessedTextPane.setText("" - + "

" - + "You exceeded your current quota, please check your plan and billing details, " - + "or change to a different LLM provider.

" - + ""); - - currentlyProcessedTextPane.addHyperlinkListener(e -> { - if (e.getEventType() == ACTIVATED) { - ShowSettingsUtil.getInstance() - .showSettingsDialog(project, GeneralSettingsConfigurable.class); - TelemetryAction.IDE_ACTION.createActionMessage() - .property("action", ActionType.CHANGE_PROVIDER.name()) - .send(); - } - }); - hideCaret(); - } - - revalidate(); - repaint(); }); } public void displayError(String message) { - ApplicationManager.getApplication().invokeLater(() -> { - if (loadingLabel.isVisible()) { - loadingLabel.setVisible(false); - } - if (webpageListPanel != null) { - webpageListPanel.setVisible(false); - } - - var errorText = format( - "

%s

", - message); - if (currentlyProcessedTextPane == null) { - contentPanel.add(createTextPane(errorText)); - } else { - currentlyProcessedTextPane.setVisible(true); - currentlyProcessedTextPane.setText(errorText); - } - hideCaret(); - - revalidate(); - repaint(); - }); + displayErrorMessage(message, null); } public void handleCodeGPTEvent(CodeGPTEvent codegptEvent) { @@ -294,6 +228,39 @@ public class ChatMessageResponseBody extends JPanel { revalidate(); } + private void displayErrorMessage(String message, HyperlinkListener hyperlinkListener) { + ApplicationManager.getApplication().invokeLater(() -> { + if (loadingLabel.isVisible()) { + loadingLabel.setVisible(false); + } + if (webpageListPanel != null) { + webpageListPanel.setVisible(false); + } + + if (currentlyProcessedTextPane == null) { + currentlyProcessedTextPane = createTextPane(""); + contentPanel.add(currentlyProcessedTextPane); + } + + String formattedMessage = format( + "

%s

", message); + currentlyProcessedTextPane.setVisible(true); + currentlyProcessedTextPane.setText(formattedMessage); + + if (hyperlinkListener != null) { + for (HyperlinkListener listener : currentlyProcessedTextPane.getHyperlinkListeners()) { + currentlyProcessedTextPane.removeHyperlinkListener(listener); + } + currentlyProcessedTextPane.addHyperlinkListener(hyperlinkListener); + } + + hideCaret(); + + revalidate(); + repaint(); + }); + } + private void processThinkingOutput(String thoughtProcess) { progressPanel.setVisible(false); diff --git a/src/main/kotlin/ee/carlrobert/codegpt/completions/factory/OpenAIRequestFactory.kt b/src/main/kotlin/ee/carlrobert/codegpt/completions/factory/OpenAIRequestFactory.kt index 83d1fd3a..f1be4191 100644 --- a/src/main/kotlin/ee/carlrobert/codegpt/completions/factory/OpenAIRequestFactory.kt +++ b/src/main/kotlin/ee/carlrobert/codegpt/completions/factory/OpenAIRequestFactory.kt @@ -1,8 +1,6 @@ package ee.carlrobert.codegpt.completions.factory -import com.intellij.ide.impl.ProjectUtil import com.intellij.openapi.components.service -import com.intellij.openapi.project.guessProjectDir import ee.carlrobert.codegpt.EncodingManager import ee.carlrobert.codegpt.ReferencedFile import ee.carlrobert.codegpt.completions.* diff --git a/src/test/kotlin/ee/carlrobert/codegpt/completions/CompletionRequestProviderTest.kt b/src/test/kotlin/ee/carlrobert/codegpt/completions/CompletionRequestProviderTest.kt index 257cd295..f9f69b6e 100644 --- a/src/test/kotlin/ee/carlrobert/codegpt/completions/CompletionRequestProviderTest.kt +++ b/src/test/kotlin/ee/carlrobert/codegpt/completions/CompletionRequestProviderTest.kt @@ -13,7 +13,7 @@ import testsupport.IntegrationTest class CompletionRequestProviderTest : IntegrationTest() { fun testChatCompletionRequestWithSystemPromptOverride() { - useOpenAIService(OpenAIChatCompletionModel.GPT_3_5.code) + useOpenAIService(OpenAIChatCompletionModel.GPT_4_O.code) service().state.personas.selectedPersona.instructions = "TEST_SYSTEM_PROMPT" val conversation = ConversationService.getInstance().startConversation() val firstMessage = createDummyMessage(500) @@ -39,7 +39,7 @@ class CompletionRequestProviderTest : IntegrationTest() { } fun testChatCompletionRequestRetry() { - useOpenAIService(OpenAIChatCompletionModel.GPT_3_5.code) + useOpenAIService(OpenAIChatCompletionModel.GPT_4_O.code) service().state.personas.selectedPersona.instructions = "TEST_SYSTEM_PROMPT" val conversation = ConversationService.getInstance().startConversation() val firstMessage = createDummyMessage("FIRST_TEST_PROMPT", 500)