fix: preload credentials to avoid long running tasks on EDT

This commit is contained in:
Carl-Robert Linnupuu 2024-03-27 23:04:30 +02:00
parent b72ddfccd6
commit 6255bf9eb6
29 changed files with 176 additions and 312 deletions

View file

@ -2,11 +2,6 @@ package ee.carlrobert.codegpt.actions;
import static com.intellij.openapi.ui.Messages.OK;
import static com.intellij.util.ObjectUtils.tryCast;
import static ee.carlrobert.codegpt.settings.service.ServiceType.ANTHROPIC;
import static ee.carlrobert.codegpt.settings.service.ServiceType.AZURE;
import static ee.carlrobert.codegpt.settings.service.ServiceType.CUSTOM_OPENAI;
import static ee.carlrobert.codegpt.settings.service.ServiceType.LLAMA_CPP;
import static ee.carlrobert.codegpt.settings.service.ServiceType.OPENAI;
import static ee.carlrobert.codegpt.settings.service.ServiceType.YOU;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
@ -34,10 +29,7 @@ import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.EncodingManager;
import ee.carlrobert.codegpt.Icons;
import ee.carlrobert.codegpt.completions.CompletionRequestService;
import ee.carlrobert.codegpt.credentials.AzureCredentialsManager;
import ee.carlrobert.codegpt.credentials.OpenAICredentialManager;
import ee.carlrobert.codegpt.settings.GeneralSettings;
import ee.carlrobert.codegpt.settings.service.ServiceType;
import ee.carlrobert.codegpt.ui.OverlayUtil;
import ee.carlrobert.llm.client.openai.completion.ErrorDetails;
import ee.carlrobert.llm.completion.CompletionEventListener;
@ -79,19 +71,14 @@ public class GenerateGitCommitMessageAction extends AnAction {
var includedUnversionedChangesFilePaths = getIncludedUnversionedFilePaths(event);
var filesSelected =
!includedChangesFilePaths.isEmpty() || !includedUnversionedChangesFilePaths.isEmpty();
var callAllowed = isCallAllowed(selectedService);
var callAllowed = CompletionRequestService.isRequestAllowed(
GeneralSettings.getCurrentState().getSelectedService());
event.getPresentation().setEnabled(callAllowed && filesSelected);
event.getPresentation().setText(CodeGPTBundle.get(callAllowed
? "action.generateCommitMessage.title"
: "action.generateCommitMessage.missingCredentials"));
}
private boolean isCallAllowed(ServiceType serviceType) {
return (serviceType == OPENAI && OpenAICredentialManager.getInstance().isCredentialSet())
|| (serviceType == AZURE && AzureCredentialsManager.getInstance().isCredentialSet())
|| List.of(LLAMA_CPP, ANTHROPIC, CUSTOM_OPENAI).contains(serviceType);
}
@Override
public void actionPerformed(@NotNull AnActionEvent event) {
var project = event.getProject();

View file

@ -2,10 +2,8 @@ package ee.carlrobert.codegpt.completions;
import ee.carlrobert.codegpt.CodeGPTPlugin;
import ee.carlrobert.codegpt.completions.you.YouUserManager;
import ee.carlrobert.codegpt.credentials.AnthropicCredentialsManager;
import ee.carlrobert.codegpt.credentials.AzureCredentialsManager;
import ee.carlrobert.codegpt.credentials.LlamaCredentialManager;
import ee.carlrobert.codegpt.credentials.OpenAICredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
import ee.carlrobert.codegpt.settings.advanced.AdvancedSettings;
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettings;
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
@ -23,18 +21,23 @@ import java.net.Proxy;
import java.util.concurrent.TimeUnit;
import okhttp3.Credentials;
import okhttp3.OkHttpClient;
import org.jetbrains.annotations.Nullable;
public class CompletionClientProvider {
private static @Nullable String getCredential(CredentialKey key) {
return CredentialsStore.INSTANCE.getCredential(key);
}
public static OpenAIClient getOpenAIClient() {
return new OpenAIClient.Builder(OpenAICredentialManager.getInstance().getCredential())
return new OpenAIClient.Builder(getCredential(CredentialKey.OPENAI_API_KEY))
.setOrganization(OpenAISettings.getCurrentState().getOrganization())
.build(getDefaultClientBuilder());
}
public static ClaudeClient getClaudeClient() {
return new ClaudeClient(
AnthropicCredentialsManager.getInstance().getCredential(),
getCredential(CredentialKey.ANTHROPIC_API_KEY),
AnthropicSettings.getCurrentState().getApiVersion(),
getDefaultClientBuilder());
}
@ -45,8 +48,12 @@ public class CompletionClientProvider {
settings.getResourceName(),
settings.getDeploymentId(),
settings.getApiVersion());
return new AzureClient.Builder(AzureCredentialsManager.getInstance().getCredential(), params)
.setActiveDirectoryAuthentication(settings.isUseAzureActiveDirectoryAuthentication())
var useAzureActiveDirectoryAuthentication = settings.isUseAzureActiveDirectoryAuthentication();
var credential = useAzureActiveDirectoryAuthentication
? getCredential(CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN)
: getCredential(CredentialKey.AZURE_OPENAI_API_KEY);
return new AzureClient.Builder(credential, params)
.setActiveDirectoryAuthentication(useAzureActiveDirectoryAuthentication)
.build(getDefaultClientBuilder());
}
@ -77,7 +84,7 @@ public class CompletionClientProvider {
.setPort(llamaSettings.getServerPort());
if (!llamaSettings.isRunLocalServer()) {
builder.setHost(llamaSettings.getBaseHost());
String apiKey = LlamaCredentialManager.getInstance().getCredential();
String apiKey = getCredential(CredentialKey.LLAMA_API_KEY);
if (apiKey != null && !apiKey.isBlank()) {
builder.setApiKey(apiKey);
}

View file

@ -1,5 +1,6 @@
package ee.carlrobert.codegpt.completions;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.CUSTOM_SERVICE_API_KEY;
import static ee.carlrobert.codegpt.util.file.FileUtil.getResourceContent;
import static java.lang.String.format;
import static java.util.stream.Collectors.joining;
@ -16,7 +17,7 @@ import ee.carlrobert.codegpt.completions.llama.PromptTemplate;
import ee.carlrobert.codegpt.conversations.Conversation;
import ee.carlrobert.codegpt.conversations.ConversationsState;
import ee.carlrobert.codegpt.conversations.message.Message;
import ee.carlrobert.codegpt.credentials.CustomServiceCredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.settings.GeneralSettings;
import ee.carlrobert.codegpt.settings.IncludedFilesSettings;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
@ -202,9 +203,9 @@ public class CompletionRequestProvider {
var requestBuilder = new Request.Builder().url(customConfiguration.getUrl().trim());
for (var entry : customConfiguration.getHeaders().entrySet()) {
String value = entry.getValue();
if (value.contains("$CUSTOM_SERVICE_API_KEY")) {
value = value.replace("$CUSTOM_SERVICE_API_KEY",
CustomServiceCredentialManager.getInstance().getCredential());
var credential = CredentialsStore.INSTANCE.getCredential(CUSTOM_SERVICE_API_KEY);
if (value.contains("$CUSTOM_SERVICE_API_KEY") && credential != null) {
value = value.replace("$CUSTOM_SERVICE_API_KEY", credential);
}
requestBuilder.addHeader(entry.getKey(), value);
}

View file

@ -1,5 +1,6 @@
package ee.carlrobert.codegpt.completions;
import static ee.carlrobert.codegpt.settings.service.ServiceType.ANTHROPIC;
import static ee.carlrobert.codegpt.settings.service.ServiceType.AZURE;
import static ee.carlrobert.codegpt.settings.service.ServiceType.CUSTOM_OPENAI;
import static ee.carlrobert.codegpt.settings.service.ServiceType.LLAMA_CPP;
@ -13,11 +14,13 @@ import ee.carlrobert.codegpt.codecompletions.CodeCompletionRequestProvider;
import ee.carlrobert.codegpt.codecompletions.InfillRequestDetails;
import ee.carlrobert.codegpt.completions.llama.LlamaModel;
import ee.carlrobert.codegpt.completions.llama.PromptTemplate;
import ee.carlrobert.codegpt.credentials.AzureCredentialsManager;
import ee.carlrobert.codegpt.credentials.OpenAICredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
import ee.carlrobert.codegpt.settings.GeneralSettings;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
import ee.carlrobert.codegpt.settings.service.ServiceType;
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettings;
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
import ee.carlrobert.codegpt.settings.service.custom.CustomServiceSettings;
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettings;
import ee.carlrobert.codegpt.settings.service.openai.OpenAISettings;
@ -197,6 +200,26 @@ public final class CompletionRequestService {
return tryExtractContent(response);
}
public boolean isRequestAllowed() {
return isRequestAllowed(GeneralSettings.getCurrentState().getSelectedService());
}
public static boolean isRequestAllowed(ServiceType serviceType) {
if (serviceType == OPENAI
&& CredentialsStore.INSTANCE.isCredentialSet(CredentialKey.OPENAI_API_KEY)) {
return true;
}
var azureCredentialKey = AzureSettings.getCurrentState().isUseAzureApiKeyAuthentication()
? CredentialKey.AZURE_OPENAI_API_KEY
: CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN;
if (serviceType == AZURE && CredentialsStore.INSTANCE.isCredentialSet(azureCredentialKey)) {
return true;
}
return List.of(LLAMA_CPP, ANTHROPIC, CUSTOM_OPENAI).contains(serviceType);
}
private Optional<String> tryExtractContent(OpenAIChatCompletionResponse response) {
return response
.getChoices()
@ -204,15 +227,4 @@ public final class CompletionRequestService {
.findFirst()
.map(item -> item.getMessage().getContent());
}
public boolean isRequestAllowed() {
var selectedService = GeneralSettings.getCurrentState().getSelectedService();
if (selectedService == AZURE) {
return AzureCredentialsManager.getInstance().isCredentialSet();
}
if (selectedService == OPENAI) {
return OpenAICredentialManager.getInstance().isCredentialSet();
}
return true;
}
}

View file

@ -10,7 +10,8 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiUtilCore;
import ee.carlrobert.codegpt.Icons;
import ee.carlrobert.codegpt.credentials.OpenAICredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
import java.util.Optional;
import org.jetbrains.annotations.Nullable;
@ -21,15 +22,13 @@ public class MethodNameLookupListener implements LookupManagerListener {
public void activeLookupChanged(@Nullable Lookup oldLookup, @Nullable Lookup newLookup) {
var application = ApplicationManager.getApplication();
var configuration = ConfigurationSettings.getCurrentState();
var credentialsManager = OpenAICredentialManager.getInstance();
if (!configuration.isMethodNameGenerationEnabled()
|| !credentialsManager.isCredentialSet()
|| !(newLookup instanceof LookupImpl)) {
|| !CredentialsStore.INSTANCE.isCredentialSet(CredentialKey.OPENAI_API_KEY)
|| !(newLookup instanceof LookupImpl lookup)) {
return;
}
var lookup = (LookupImpl) newLookup;
Optional.ofNullable(lookup.getPsiElement())
.map(PsiElement::getContext)
.ifPresent(context ->

View file

@ -1,55 +0,0 @@
package ee.carlrobert.codegpt.credentials;
import com.intellij.credentialStore.CredentialAttributes;
import com.intellij.credentialStore.CredentialAttributesKt;
import com.intellij.ide.passwordSafe.PasswordSafe;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jetbrains.annotations.Nullable;
abstract class AbstractCredentialsManager {
private final Map<String, CredentialAttributes> credentialMapping;
private final Map<String, String> credentialCache = new ConcurrentHashMap<>();
protected AbstractCredentialsManager(String... keys) {
credentialMapping = Stream.of(keys).collect(Collectors.toConcurrentMap(
key -> key,
key -> new CredentialAttributes(CredentialAttributesKt.generateServiceName("CodeGPT", key))
));
}
public abstract boolean isCredentialSet();
protected boolean isCredentialSet(String key) {
var credential = getCredential(key);
return credential != null && !credential.isEmpty();
}
public abstract String getCredential();
protected @Nullable String getCredential(String key) {
String cachedCredential = credentialCache.get(key);
if (cachedCredential != null) {
return cachedCredential;
}
String credential = PasswordSafe.getInstance().getPassword(credentialMapping.get(key));
if (credential != null) {
credentialCache.put(key, credential);
}
return credential;
}
protected void setCredential(String key, String credential) {
if (credential == null) {
credentialCache.remove(key);
} else {
credentialCache.put(key, credential);
}
PasswordSafe.getInstance().setPassword(credentialMapping.get(key), credential);
}
}

View file

@ -1,16 +0,0 @@
package ee.carlrobert.codegpt.credentials;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.Service;
@Service
public final class AnthropicCredentialsManager extends SingleCredentialManager {
private AnthropicCredentialsManager() {
super("ANTHROPIC_API_KEY");
}
public static AnthropicCredentialsManager getInstance() {
return ApplicationManager.getApplication().getService(AnthropicCredentialsManager.class);
}
}

View file

@ -1,52 +0,0 @@
package ee.carlrobert.codegpt.credentials;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.Service;
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
@Service
public final class AzureCredentialsManager extends AbstractCredentialsManager {
public static final String API_KEY = "AZURE_OPENAI_API_KEY";
public static final String ACTIVE_DIRECTORY_TOKEN = "AZURE_ACTIVE_DIRECTORY_TOKEN";
private AzureCredentialsManager() {
super(API_KEY, ACTIVE_DIRECTORY_TOKEN);
}
public static AzureCredentialsManager getInstance() {
return ApplicationManager.getApplication().getService(AzureCredentialsManager.class);
}
@Override
public boolean isCredentialSet() {
if (AzureSettings.getCurrentState().isUseAzureApiKeyAuthentication()) {
return isCredentialSet(API_KEY);
}
return isCredentialSet(ACTIVE_DIRECTORY_TOKEN);
}
@Override
public String getCredential() {
if (AzureSettings.getCurrentState().isUseAzureActiveDirectoryAuthentication()) {
return getActiveDirectoryToken();
}
return getApiKey();
}
public void setApiKey(String apiKey) {
setCredential(API_KEY, apiKey);
}
public String getApiKey() {
return getCredential(API_KEY);
}
public void setActiveDirectoryToken(String activeDirectoryToken) {
setCredential(ACTIVE_DIRECTORY_TOKEN, activeDirectoryToken);
}
public String getActiveDirectoryToken() {
return getCredential(ACTIVE_DIRECTORY_TOKEN);
}
}

View file

@ -1,16 +0,0 @@
package ee.carlrobert.codegpt.credentials;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.Service;
@Service
public final class CustomServiceCredentialManager extends SingleCredentialManager {
private CustomServiceCredentialManager() {
super("CUSTOM_SERVICE_API_KEY");
}
public static CustomServiceCredentialManager getInstance() {
return ApplicationManager.getApplication().getService(CustomServiceCredentialManager.class);
}
}

View file

@ -1,16 +0,0 @@
package ee.carlrobert.codegpt.credentials;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.Service;
@Service
public final class LlamaCredentialManager extends SingleCredentialManager {
private LlamaCredentialManager() {
super("LLAMA_API_KEY");
}
public static LlamaCredentialManager getInstance() {
return ApplicationManager.getApplication().getService(LlamaCredentialManager.class);
}
}

View file

@ -1,16 +0,0 @@
package ee.carlrobert.codegpt.credentials;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.Service;
@Service
public final class OpenAICredentialManager extends SingleCredentialManager {
private OpenAICredentialManager() {
super("OPENAI_API_KEY");
}
public static OpenAICredentialManager getInstance() {
return ApplicationManager.getApplication().getService(OpenAICredentialManager.class);
}
}

View file

@ -1,25 +0,0 @@
package ee.carlrobert.codegpt.credentials;
abstract class SingleCredentialManager extends AbstractCredentialsManager {
private final String key;
public SingleCredentialManager(String key) {
super(key);
this.key = key;
}
@Override
public boolean isCredentialSet() {
return isCredentialSet(key);
}
@Override
public String getCredential() {
return getCredential(key);
}
public void setCredential(String credential) {
setCredential(key, credential);
}
}

View file

@ -1,16 +0,0 @@
package ee.carlrobert.codegpt.credentials;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.Service;
@Service
public final class YouCredentialManager extends SingleCredentialManager {
private YouCredentialManager() {
super("YOU_ACCOUNT_PASSWORD");
}
public static YouCredentialManager getInstance() {
return ApplicationManager.getApplication().getService(YouCredentialManager.class);
}
}

View file

@ -1,15 +1,18 @@
package ee.carlrobert.codegpt.settings;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.ANTHROPIC_API_KEY;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.AZURE_OPENAI_API_KEY;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.CUSTOM_SERVICE_API_KEY;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.LLAMA_API_KEY;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.OPENAI_API_KEY;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.util.Disposer;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.conversations.ConversationsState;
import ee.carlrobert.codegpt.credentials.AnthropicCredentialsManager;
import ee.carlrobert.codegpt.credentials.AzureCredentialsManager;
import ee.carlrobert.codegpt.credentials.CustomServiceCredentialManager;
import ee.carlrobert.codegpt.credentials.LlamaCredentialManager;
import ee.carlrobert.codegpt.credentials.OpenAICredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettings;
import ee.carlrobert.codegpt.settings.service.anthropic.AnthropicSettingsForm;
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
@ -100,18 +103,20 @@ public class GeneralSettingsConfigurable implements Configurable {
}
private void applyOpenAISettings(OpenAISettingsForm form) {
OpenAICredentialManager.getInstance().setCredential(form.getApiKey());
CredentialsStore.INSTANCE.setCredential(OPENAI_API_KEY, form.getApiKey());
OpenAISettings.getInstance().loadState(form.getCurrentState());
}
private void applyCustomOpenAISettings(CustomServiceForm form) {
CustomServiceCredentialManager.getInstance().setCredential(form.getApiKey());
CredentialsStore.INSTANCE.setCredential(CUSTOM_SERVICE_API_KEY, form.getApiKey());
CustomServiceSettings.getInstance().loadState(form.getCurrentState());
}
private void applyLlamaSettings(LlamaSettingsForm form) {
LlamaCredentialManager.getInstance()
.setCredential(form.getLlamaServerPreferencesForm().getApiKey());
CredentialsStore.INSTANCE.setCredential(
LLAMA_API_KEY,
form.getLlamaServerPreferencesForm().getApiKey());
LlamaSettings.getInstance().loadState(form.getCurrentState());
}
@ -120,15 +125,16 @@ public class GeneralSettingsConfigurable implements Configurable {
}
private void applyAnthropicSettings(AnthropicSettingsForm form) {
CredentialsStore.INSTANCE.setCredential(ANTHROPIC_API_KEY, form.getApiKey());
AnthropicSettings.getInstance().loadState(form.getCurrentState());
AnthropicCredentialsManager.getInstance().setCredential(form.getApiKey());
}
private void applyAzureSettings(AzureSettingsForm form) {
AzureSettings.getInstance().loadState(form.getCurrentState());
var azureCredentials = AzureCredentialsManager.getInstance();
azureCredentials.setApiKey(form.getApiKey());
azureCredentials.setActiveDirectoryToken(form.getActiveDirectoryToken());
CredentialsStore.INSTANCE.setCredential(AZURE_OPENAI_API_KEY, form.getApiKey());
CredentialsStore.INSTANCE.setCredential(
AZURE_ACTIVE_DIRECTORY_TOKEN,
form.getActiveDirectoryToken());
}
@Override

View file

@ -4,7 +4,8 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import ee.carlrobert.codegpt.credentials.AnthropicCredentialsManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
@ -36,6 +37,6 @@ public class AnthropicSettings implements PersistentStateComponent<AnthropicSett
return !form.getCurrentState().equals(state)
|| !StringUtils.equals(
form.getApiKey(),
AnthropicCredentialsManager.getInstance().getCredential());
CredentialsStore.INSTANCE.getCredential(CredentialKey.ANTHROPIC_API_KEY));
}
}

View file

@ -1,5 +1,6 @@
package ee.carlrobert.codegpt.settings.service.anthropic;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.ANTHROPIC_API_KEY;
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
import com.intellij.ui.TitledSeparator;
@ -8,7 +9,7 @@ import com.intellij.ui.components.JBTextField;
import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.UI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.credentials.AnthropicCredentialsManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.ui.UIUtil;
import javax.swing.JPanel;
import org.jetbrains.annotations.Nullable;
@ -22,7 +23,7 @@ public class AnthropicSettingsForm {
public AnthropicSettingsForm(AnthropicSettingsState settings) {
apiKeyField = new JBPasswordField();
apiKeyField.setColumns(30);
apiKeyField.setText(AnthropicCredentialsManager.getInstance().getCredential());
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(ANTHROPIC_API_KEY));
apiVersionField = new JBTextField(settings.getApiVersion(), 35);
modelField = new JBTextField(settings.getModel(), 35);
}
@ -62,7 +63,7 @@ public class AnthropicSettingsForm {
public void resetForm() {
var state = AnthropicSettings.getCurrentState();
apiKeyField.setText(AnthropicCredentialsManager.getInstance().getCredential());
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(ANTHROPIC_API_KEY));
apiVersionField.setText(state.getApiVersion());
modelField.setText(state.getModel());
}

View file

@ -1,10 +1,13 @@
package ee.carlrobert.codegpt.settings.service.azure;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.AZURE_OPENAI_API_KEY;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import ee.carlrobert.codegpt.credentials.AzureCredentialsManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
@ -33,11 +36,12 @@ public class AzureSettings implements PersistentStateComponent<AzureSettingsStat
}
public boolean isModified(AzureSettingsForm form) {
var credentialsManager = AzureCredentialsManager.getInstance();
return !form.getCurrentState().equals(state)
|| !StringUtils.equals(
form.getActiveDirectoryToken(),
credentialsManager.getActiveDirectoryToken())
|| !StringUtils.equals(form.getApiKey(), credentialsManager.getApiKey());
CredentialsStore.INSTANCE.getCredential(AZURE_ACTIVE_DIRECTORY_TOKEN))
|| !StringUtils.equals(
form.getApiKey(),
CredentialsStore.INSTANCE.getCredential(AZURE_OPENAI_API_KEY));
}
}

View file

@ -9,7 +9,8 @@ import com.intellij.ui.components.JBTextField;
import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.UI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.credentials.AzureCredentialsManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
import java.util.List;
import java.util.Map;
import javax.swing.ButtonGroup;
@ -37,7 +38,8 @@ public class AzureSettingsForm {
settings.isUseAzureActiveDirectoryAuthentication());
azureApiKeyField = new JBPasswordField();
azureApiKeyField.setColumns(30);
azureApiKeyField.setText(AzureCredentialsManager.getInstance().getApiKey());
azureApiKeyField.setText(
CredentialsStore.INSTANCE.getCredential(CredentialKey.AZURE_OPENAI_API_KEY));
azureApiKeyFieldPanel = UI.PanelFactory.panel(azureApiKeyField)
.withLabel(CodeGPTBundle.get("settingsConfigurable.shared.apiKey.label"))
.resizeX(false)
@ -45,7 +47,7 @@ public class AzureSettingsForm {
azureActiveDirectoryTokenField = new JBPasswordField();
azureActiveDirectoryTokenField.setColumns(30);
azureActiveDirectoryTokenField.setText(
AzureCredentialsManager.getInstance().getActiveDirectoryToken());
CredentialsStore.INSTANCE.getCredential(CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN));
azureActiveDirectoryTokenFieldPanel = UI.PanelFactory.panel(azureActiveDirectoryTokenField)
.withLabel(CodeGPTBundle.get("settingsConfigurable.service.azure.bearerToken.label"))
.resizeX(false)
@ -117,9 +119,10 @@ public class AzureSettingsForm {
public void resetForm() {
var state = AzureSettings.getCurrentState();
azureApiKeyField.setText(AzureCredentialsManager.getInstance().getApiKey());
azureApiKeyField.setText(
CredentialsStore.INSTANCE.getCredential(CredentialKey.AZURE_OPENAI_API_KEY));
azureActiveDirectoryTokenField.setText(
AzureCredentialsManager.getInstance().getActiveDirectoryToken());
CredentialsStore.INSTANCE.getCredential(CredentialKey.AZURE_ACTIVE_DIRECTORY_TOKEN));
useAzureApiKeyAuthenticationRadioButton.setSelected(state.isUseAzureApiKeyAuthentication());
useAzureActiveDirectoryAuthenticationRadioButton.setSelected(
state.isUseAzureActiveDirectoryAuthentication());

View file

@ -1,5 +1,6 @@
package ee.carlrobert.codegpt.settings.service.custom;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.CUSTOM_SERVICE_API_KEY;
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
import com.intellij.icons.AllIcons.General;
@ -18,7 +19,7 @@ import ee.carlrobert.codegpt.completions.CompletionRequestProvider;
import ee.carlrobert.codegpt.completions.CompletionRequestService;
import ee.carlrobert.codegpt.conversations.Conversation;
import ee.carlrobert.codegpt.conversations.message.Message;
import ee.carlrobert.codegpt.credentials.CustomServiceCredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.ui.OverlayUtil;
import ee.carlrobert.codegpt.ui.UIUtil;
import ee.carlrobert.llm.client.openai.completion.ErrorDetails;
@ -46,7 +47,7 @@ public class CustomServiceForm {
public CustomServiceForm(CustomServiceSettingsState settings) {
apiKeyField = new JBPasswordField();
apiKeyField.setColumns(30);
apiKeyField.setText(CustomServiceCredentialManager.getInstance().getCredential());
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(CUSTOM_SERVICE_API_KEY));
urlField = new JBTextField(settings.getUrl(), 30);
tabbedPane = new CustomServiceFormTabbedPane(settings);
testConnectionButton = new JButton(CodeGPTBundle.get(
@ -114,7 +115,7 @@ public class CustomServiceForm {
public void resetForm() {
var state = CustomServiceSettings.getCurrentState();
apiKeyField.setText(CustomServiceCredentialManager.getInstance().getCredential());
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(CUSTOM_SERVICE_API_KEY));
urlField.setText(state.getUrl());
templateComboBox.setSelectedItem(state.getTemplate());
tabbedPane.setHeaders(state.getHeaders());

View file

@ -1,10 +1,12 @@
package ee.carlrobert.codegpt.settings.service.custom;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.CUSTOM_SERVICE_API_KEY;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import ee.carlrobert.codegpt.credentials.CustomServiceCredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
@ -38,6 +40,6 @@ public class CustomServiceSettings implements PersistentStateComponent<CustomSer
return !form.getCurrentState().equals(state)
|| !StringUtils.equals(
form.getApiKey(),
CustomServiceCredentialManager.getInstance().getCredential());
CredentialsStore.INSTANCE.getCredential(CUSTOM_SERVICE_API_KEY));
}
}

View file

@ -1,10 +1,12 @@
package ee.carlrobert.codegpt.settings.service.llama;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.LLAMA_API_KEY;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import ee.carlrobert.codegpt.credentials.LlamaCredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.settings.service.llama.form.LlamaSettingsForm;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
@ -37,6 +39,6 @@ public class LlamaSettings implements PersistentStateComponent<LlamaSettingsStat
return !form.getCurrentState().equals(state)
|| !StringUtils.equals(
form.getLlamaServerPreferencesForm().getApiKey(),
LlamaCredentialManager.getInstance().getCredential());
CredentialsStore.INSTANCE.getCredential(LLAMA_API_KEY));
}
}

View file

@ -1,5 +1,6 @@
package ee.carlrobert.codegpt.settings.service.llama.form;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.LLAMA_API_KEY;
import static ee.carlrobert.codegpt.ui.UIUtil.createComment;
import static ee.carlrobert.codegpt.ui.UIUtil.createForm;
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
@ -27,7 +28,7 @@ import ee.carlrobert.codegpt.completions.HuggingFaceModel;
import ee.carlrobert.codegpt.completions.llama.LlamaServerAgent;
import ee.carlrobert.codegpt.completions.llama.LlamaServerStartupParams;
import ee.carlrobert.codegpt.completions.llama.PromptTemplate;
import ee.carlrobert.codegpt.credentials.LlamaCredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.settings.service.llama.LlamaSettingsState;
import ee.carlrobert.codegpt.ui.OverlayUtil;
import ee.carlrobert.codegpt.ui.UIUtil;
@ -83,7 +84,7 @@ public class LlamaServerPreferencesForm {
baseHostField = new JBTextField(settings.getBaseHost(), 30);
apiKeyField = new JBPasswordField();
apiKeyField.setColumns(30);
apiKeyField.setText(LlamaCredentialManager.getInstance().getCredential());
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(LLAMA_API_KEY));
llamaModelPreferencesForm = new LlamaModelPreferencesForm();
runLocalServerRadioButton = new JBRadioButton("Run local server",
@ -127,7 +128,7 @@ public class LlamaServerPreferencesForm {
additionalParametersField.setText(state.getAdditionalParameters());
remotePromptTemplatePanel.setPromptTemplate(state.getRemoteModelPromptTemplate()); // ?
infillPromptTemplatePanel.setPromptTemplate(state.getRemoteModelInfillPromptTemplate());
apiKeyField.setText(LlamaCredentialManager.getInstance().getCredential());
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(LLAMA_API_KEY));
}
public JComponent createUseExistingServerForm() {

View file

@ -1,10 +1,12 @@
package ee.carlrobert.codegpt.settings.service.openai;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.OPENAI_API_KEY;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import ee.carlrobert.codegpt.credentials.OpenAICredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
@ -36,6 +38,6 @@ public class OpenAISettings implements PersistentStateComponent<OpenAISettingsSt
return !form.getCurrentState().equals(state)
|| !StringUtils.equals(
form.getApiKey(),
OpenAICredentialManager.getInstance().getCredential());
CredentialsStore.INSTANCE.getCredential(OPENAI_API_KEY));
}
}

View file

@ -1,5 +1,6 @@
package ee.carlrobert.codegpt.settings.service.openai;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.OPENAI_API_KEY;
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
import com.intellij.openapi.ui.ComboBox;
@ -10,7 +11,7 @@ import com.intellij.ui.components.JBTextField;
import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.UI;
import ee.carlrobert.codegpt.CodeGPTBundle;
import ee.carlrobert.codegpt.credentials.OpenAICredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.ui.UIUtil;
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionModel;
import javax.swing.JPanel;
@ -25,7 +26,7 @@ public class OpenAISettingsForm {
public OpenAISettingsForm(OpenAISettingsState settings) {
apiKeyField = new JBPasswordField();
apiKeyField.setColumns(30);
apiKeyField.setText(OpenAICredentialManager.getInstance().getCredential());
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(OPENAI_API_KEY));
organizationField = new JBTextField(settings.getOrganization(), 30);
completionModelComboBox = new ComboBox<>(
new EnumComboBoxModel<>(OpenAIChatCompletionModel.class));
@ -77,7 +78,7 @@ public class OpenAISettingsForm {
public void resetForm() {
var state = OpenAISettings.getCurrentState();
apiKeyField.setText(OpenAICredentialManager.getInstance().getCredential());
apiKeyField.setText(CredentialsStore.INSTANCE.getCredential(OPENAI_API_KEY));
completionModelComboBox.setSelectedItem(
OpenAIChatCompletionModel.findByCode(state.getModel()));
organizationField.setText(state.getOrganization());

View file

@ -1,5 +1,6 @@
package ee.carlrobert.codegpt.settings.service.you;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.YOU_ACCOUNT_PASSWORD;
import static ee.carlrobert.codegpt.ui.UIUtil.withEmptyLeftBorder;
import com.intellij.openapi.Disposable;
@ -23,7 +24,8 @@ import ee.carlrobert.codegpt.completions.you.auth.YouAuthenticationError;
import ee.carlrobert.codegpt.completions.you.auth.YouAuthenticationService;
import ee.carlrobert.codegpt.completions.you.auth.response.YouAuthenticationResponse;
import ee.carlrobert.codegpt.completions.you.auth.response.YouUser;
import ee.carlrobert.codegpt.credentials.YouCredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
import ee.carlrobert.codegpt.ui.UIUtil;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
@ -51,7 +53,7 @@ public class YouSettingsForm extends JPanel {
passwordField = new JBPasswordField();
passwordField.setColumns(25);
if (!settings.getEmail().isEmpty()) {
passwordField.setText(YouCredentialManager.getInstance().getCredential());
passwordField.setText(CredentialsStore.INSTANCE.getCredential(YOU_ACCOUNT_PASSWORD));
}
signInButton = new JButton(CodeGPTBundle.get("settingsConfigurable.service.you.signIn.label"));
signUpTextPane = createSignUpTextPane();
@ -255,7 +257,9 @@ public class YouSettingsForm extends JPanel {
var email = emailField.getText();
var password = passwordField.getPassword();
YouSettings.getCurrentState().setEmail(email);
YouCredentialManager.getInstance().setCredential(new String(password));
CredentialsStore.INSTANCE.setCredential(
CredentialKey.YOU_ACCOUNT_PASSWORD,
new String(password));
refreshView(createUserInformationPanel(authenticationResponse.getData().getUser()));
});
}

View file

@ -10,7 +10,9 @@ import ee.carlrobert.codegpt.completions.you.auth.AuthenticationHandler
import ee.carlrobert.codegpt.completions.you.auth.YouAuthenticationError
import ee.carlrobert.codegpt.completions.you.auth.YouAuthenticationService
import ee.carlrobert.codegpt.completions.you.auth.response.YouAuthenticationResponse
import ee.carlrobert.codegpt.credentials.YouCredentialManager
import ee.carlrobert.codegpt.credentials.CredentialsStore
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey
import ee.carlrobert.codegpt.credentials.CredentialsStore.getCredential
import ee.carlrobert.codegpt.settings.service.you.YouSettings
import ee.carlrobert.codegpt.ui.OverlayUtil
@ -18,6 +20,7 @@ class CodeGPTProjectActivity : ProjectActivity {
override suspend fun execute(project: Project) {
EditorActionsUtil.refreshActions()
CredentialsStore.loadAll()
if (YouUserManager.getInstance().authenticationResponse == null) {
ApplicationManager.getApplication()
@ -27,8 +30,8 @@ class CodeGPTProjectActivity : ProjectActivity {
private fun handleYouServiceAuthentication() {
val settings = YouSettings.getCurrentState()
val password = YouCredentialManager.getInstance().credential
if (settings.email.isNotEmpty() && password != null && password.isNotEmpty()) {
val password = getCredential(CredentialKey.YOU_ACCOUNT_PASSWORD)
if (settings.email.isNotEmpty() && !password.isNullOrEmpty()) {
YouAuthenticationService.getInstance()
.signInAsync(settings.email, password, object : AuthenticationHandler {
override fun handleAuthenticated(authenticationResponse: YouAuthenticationResponse) {

View file

@ -0,0 +1,36 @@
package ee.carlrobert.codegpt.credentials
import com.intellij.credentialStore.CredentialAttributes
import com.intellij.credentialStore.generateServiceName
import com.intellij.ide.passwordSafe.PasswordSafe
object CredentialsStore {
private val credentialsMap = mutableMapOf<CredentialKey, String?>()
fun loadAll() {
CredentialKey.values().forEach {
val credentialAttributes = CredentialAttributes(generateServiceName("CodeGPT", it.name))
val password = PasswordSafe.instance.getPassword(credentialAttributes)
setCredential(it, password)
}
}
fun getCredential(key: CredentialKey): String? = credentialsMap[key]
fun setCredential(key: CredentialKey, password: String?) {
credentialsMap[key] = password
}
fun isCredentialSet(key: CredentialKey): Boolean = !getCredential(key).isNullOrEmpty()
enum class CredentialKey {
OPENAI_API_KEY,
CUSTOM_SERVICE_API_KEY,
ANTHROPIC_API_KEY,
AZURE_OPENAI_API_KEY,
AZURE_ACTIVE_DIRECTORY_TOKEN,
YOU_ACCOUNT_PASSWORD,
LLAMA_API_KEY
}
}

View file

@ -6,7 +6,8 @@ import static org.assertj.core.groups.Tuple.tuple;
import ee.carlrobert.codegpt.conversations.ConversationService;
import ee.carlrobert.codegpt.conversations.message.Message;
import ee.carlrobert.codegpt.credentials.OpenAICredentialManager;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
import ee.carlrobert.llm.client.openai.completion.OpenAIChatCompletionModel;
import testsupport.IntegrationTest;
@ -14,7 +15,7 @@ import testsupport.IntegrationTest;
public class CompletionRequestProviderTest extends IntegrationTest {
public void testChatCompletionRequestWithSystemPromptOverride() {
OpenAICredentialManager.getInstance().setCredential("TEST_API_KEY");
CredentialsStore.INSTANCE.setCredential(CredentialKey.OPENAI_API_KEY, "TEST_API_KEY");
ConfigurationSettings.getCurrentState().setSystemPrompt("TEST_SYSTEM_PROMPT");
var conversation = ConversationService.getInstance().startConversation();
var firstMessage = createDummyMessage(500);

View file

@ -1,7 +1,9 @@
package testsupport.mixin;
import ee.carlrobert.codegpt.credentials.AzureCredentialsManager;
import ee.carlrobert.codegpt.credentials.OpenAICredentialManager;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.AZURE_OPENAI_API_KEY;
import static ee.carlrobert.codegpt.credentials.CredentialsStore.CredentialKey.OPENAI_API_KEY;
import ee.carlrobert.codegpt.credentials.CredentialsStore;
import ee.carlrobert.codegpt.settings.GeneralSettings;
import ee.carlrobert.codegpt.settings.service.ServiceType;
import ee.carlrobert.codegpt.settings.service.azure.AzureSettings;
@ -12,13 +14,13 @@ public interface ShortcutsTestMixin {
default void useOpenAIService() {
GeneralSettings.getCurrentState().setSelectedService(ServiceType.OPENAI);
OpenAICredentialManager.getInstance().setCredential("TEST_API_KEY");
CredentialsStore.INSTANCE.setCredential(OPENAI_API_KEY, "TEST_API_KEY");
OpenAISettings.getCurrentState().setModel("gpt-4");
}
default void useAzureService() {
GeneralSettings.getCurrentState().setSelectedService(ServiceType.AZURE);
AzureCredentialsManager.getInstance().setApiKey("TEST_API_KEY");
CredentialsStore.INSTANCE.setCredential(AZURE_OPENAI_API_KEY, "TEST_API_KEY");
var azureSettings = AzureSettings.getCurrentState();
azureSettings.setResourceName("TEST_RESOURCE_NAME");
azureSettings.setApiVersion("TEST_API_VERSION");