fix: npe on quota exceeded error (fixes #1007)
Some checks failed
Build / Build (push) Has been cancelled
Build / Verify Plugin (push) Has been cancelled

This commit is contained in:
Carl-Robert Linnupuu 2025-05-13 11:18:39 +01:00
parent c0417e558b
commit 447a0e1940
3 changed files with 51 additions and 86 deletions

View file

@ -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 <a href=\"#\">Settings</a> 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 <a href=\"#\">Settings</a> to set one.";
if (currentlyProcessedTextPane != null) {
currentlyProcessedTextPane.setVisible(true);
currentlyProcessedTextPane.setText(
format("<html><p style=\"margin-top: 4px; margin-bottom: 8px;\">%s</p></html>",
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 <a href=\"#CHANGE_PROVIDER\">change</a> 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("<html>"
+ "<p style=\"margin-top: 4px; margin-bottom: 8px;\">"
+ "You exceeded your current quota, please check your plan and billing details, "
+ "or <a href=\"#CHANGE_PROVIDER\">change</a> to a different LLM provider.</p>"
+ "</html>");
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(
"<html><p style=\"margin-top: 4px; margin-bottom: 8px;\">%s</p></html>",
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(
"<html><p style=\"margin-top: 4px; margin-bottom: 8px;\">%s</p></html>", 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);

View file

@ -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.*

View file

@ -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<PromptsSettings>().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<PromptsSettings>().state.personas.selectedPersona.instructions = "TEST_SYSTEM_PROMPT"
val conversation = ConversationService.getInstance().startConversation()
val firstMessage = createDummyMessage("FIRST_TEST_PROMPT", 500)