Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ public class Conversation {
private LocalDateTime updatedOn;
private boolean discardTokenLimit;
private String projectPath;
private List<ConversationAttachedFile> attachedFiles;

public Conversation() {
this.messages = new ArrayList<>();
this.attachedFiles = new ArrayList<>();
this.id = UUID.randomUUID();
this.createdOn = LocalDateTime.now();
this.updatedOn = LocalDateTime.now();
Expand Down Expand Up @@ -91,4 +93,12 @@ public String getProjectPath() {
public void setProjectPath(String projectPath) {
this.projectPath = projectPath;
}

public List<ConversationAttachedFile> getAttachedFiles() {
return attachedFiles;
}

public void setAttachedFiles(List<ConversationAttachedFile> attachedFiles) {
this.attachedFiles = attachedFiles == null ? new ArrayList<>() : new ArrayList<>(attachedFiles);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package ee.carlrobert.codegpt.conversations;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.Objects;

@JsonIgnoreProperties(ignoreUnknown = true)
public class ConversationAttachedFile {

private String path;
private boolean selected;

public ConversationAttachedFile() {
}

public ConversationAttachedFile(String path, boolean selected) {
this.path = path;
this.selected = selected;
}

public String getPath() {
return path;
}

public void setPath(String path) {
this.path = path;
}

public boolean isSelected() {
return selected;
}

public void setSelected(boolean selected) {
this.selected = selected;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof ConversationAttachedFile other)) {
return false;
}
return selected == other.selected && Objects.equals(path, other.path);
}

@Override
public int hashCode() {
return Objects.hash(path, selected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class ConfigurationComponent {
private final CodeCompletionConfigurationForm codeCompletionForm;
private final ChatCompletionConfigurationForm chatCompletionForm;
private final ScreenshotConfigurationForm screenshotForm;
private final DefaultChatModeConfigurationForm defaultChatModeForm;

public ConfigurationComponent(
Disposable parentDisposable,
Expand Down Expand Up @@ -76,6 +77,7 @@ public void changedUpdate(DocumentEvent e) {
codeCompletionForm = new CodeCompletionConfigurationForm();
chatCompletionForm = new ChatCompletionConfigurationForm();
screenshotForm = new ScreenshotConfigurationForm();
defaultChatModeForm = new DefaultChatModeConfigurationForm();
screenshotForm.loadState(configuration.getScreenshotWatchPaths());

mainPanel = FormBuilder.createFormBuilder()
Expand All @@ -96,6 +98,9 @@ public void changedUpdate(DocumentEvent e) {
.addComponent(new TitledSeparator(
CodeGPTBundle.get("configurationConfigurable.section.chatCompletion.title")))
.addComponent(chatCompletionForm.createPanel())
.addComponent(new TitledSeparator(
CodeGPTBundle.get("configurationConfigurable.section.defaultChatMode.title")))
.addComponent(defaultChatModeForm.createPanel())
.addComponentFillVertically(new JPanel(), 0)
.getPanel();
}
Expand All @@ -112,6 +117,9 @@ public ConfigurationSettingsState getCurrentFormState() {
state.setCheckForNewScreenshots(checkForNewScreenshotsCheckBox.isSelected());
state.setMethodNameGenerationEnabled(methodNameGenerationCheckBox.isSelected());
state.setAutoFormattingEnabled(autoFormattingCheckBox.isSelected());
state.setChatEditModeByDefault(defaultChatModeForm.isEditModeByDefaultEnabled());
state.setRememberAttachedFilesToChat(
defaultChatModeForm.isRememberAttachedFilesToChatEnabled());
state.setCodeCompletionSettings(codeCompletionForm.getFormState());
state.setChatCompletionSettings(chatCompletionForm.getFormState());

Expand All @@ -130,6 +138,7 @@ public void resetForm() {
checkForNewScreenshotsCheckBox.setSelected(configuration.getCheckForNewScreenshots());
methodNameGenerationCheckBox.setSelected(configuration.getMethodNameGenerationEnabled());
autoFormattingCheckBox.setSelected(configuration.getAutoFormattingEnabled());
defaultChatModeForm.resetForm(configuration);
codeCompletionForm.resetForm(configuration.getCodeCompletionSettings());
chatCompletionForm.resetForm(configuration.getChatCompletionSettings());
screenshotForm.loadState(configuration.getScreenshotWatchPaths());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.AnimatedIcon;
import com.intellij.ui.JBColor;
Expand All @@ -29,6 +30,7 @@
import ee.carlrobert.codegpt.completions.ToolApprovalMode;
import ee.carlrobert.codegpt.completions.ToolwindowChatCompletionRequestHandler;
import ee.carlrobert.codegpt.conversations.Conversation;
import ee.carlrobert.codegpt.conversations.ConversationAttachedFile;
import ee.carlrobert.codegpt.conversations.ConversationService;
import ee.carlrobert.codegpt.conversations.message.Message;
import ee.carlrobert.codegpt.mcp.ConnectionStatus;
Expand All @@ -38,6 +40,8 @@
import ee.carlrobert.codegpt.psistructure.models.ClassStructure;
import ee.carlrobert.codegpt.settings.ProxyAISettingsService;
import ee.carlrobert.codegpt.settings.service.FeatureType;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationSettings;
import ee.carlrobert.codegpt.settings.configuration.ConfigurationStateListener;
import ee.carlrobert.codegpt.telemetry.TelemetryAction;
import ee.carlrobert.codegpt.toolwindow.chat.editor.actions.CopyAction;
import ee.carlrobert.codegpt.toolwindow.chat.structure.data.PsiStructureRepository;
Expand All @@ -60,13 +64,15 @@
import ee.carlrobert.codegpt.ui.textarea.header.tag.PersonaTagDetails;
import ee.carlrobert.codegpt.ui.textarea.header.tag.TagDetails;
import ee.carlrobert.codegpt.ui.textarea.header.tag.TagManager;
import ee.carlrobert.codegpt.ui.textarea.header.tag.TagManagerListener;
import ee.carlrobert.codegpt.util.EditorUtil;
import ee.carlrobert.codegpt.util.coroutines.CoroutineDispatchers;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
Expand Down Expand Up @@ -142,6 +148,7 @@ public ChatToolWindowTabPanel(
this::handleSubmit,
this::handleCancel,
true);
initializeRememberedAttachedFiles();
userInputPanel.requestFocus();

mcpApprovalContainer = new JPanel();
Expand Down Expand Up @@ -387,6 +394,100 @@ private ToolApprovalMode getToolApprovalMode() {
return ToolApprovalMode.REQUIRE_APPROVAL;
}

private void initializeRememberedAttachedFiles() {
restoreRememberedAttachedFiles();

tagManager.addListener(new TagManagerListener() {
@Override
public void onTagAdded(TagDetails tag) {
syncRememberedAttachedFiles();
}

@Override
public void onTagRemoved(TagDetails tag) {
syncRememberedAttachedFiles();
}

@Override
public void onTagSelectionChanged(TagDetails tag, SelectionModel selectionModel) {
}

@Override
public void onTagUpdated(TagDetails tag) {
syncRememberedAttachedFiles();
}
});

ApplicationManager.getApplication().getMessageBus().connect(this).subscribe(
ConfigurationStateListener.Companion.getTOPIC(),
newState -> syncRememberedAttachedFiles());
}

private void restoreRememberedAttachedFiles() {
if (!isRememberAttachedFilesEnabled()) {
return;
}

var attachedFiles = conversation.getAttachedFiles();
if (attachedFiles == null || attachedFiles.isEmpty()) {
return;
}

attachedFiles.forEach(attachedFile -> {
var virtualFile = LocalFileSystem.getInstance()
.refreshAndFindFileByPath(attachedFile.getPath());
if (virtualFile == null || !virtualFile.isValid()) {
return;
}

TagDetails tagDetails = virtualFile.isDirectory()
? new FolderTagDetails(virtualFile)
: new FileTagDetails(virtualFile);
tagDetails.setSelected(attachedFile.isSelected());
userInputPanel.addTag(tagDetails);
});
}

private void syncRememberedAttachedFiles() {
if (draftSubmitHandler != null) {
return;
}

var attachedFiles = isRememberAttachedFilesEnabled()
? collectRememberedAttachedFiles()
: List.<ConversationAttachedFile>of();

if (Objects.equals(conversation.getAttachedFiles(), attachedFiles)) {
return;
}

conversation.setAttachedFiles(attachedFiles);
conversationService.saveConversation(conversation);
}

private List<ConversationAttachedFile> collectRememberedAttachedFiles() {
return tagManager.getTags().stream()
.filter(tag -> tag instanceof FileTagDetails || tag instanceof FolderTagDetails)
.sorted(Comparator.comparingLong(TagDetails::getCreatedOn))
.map(this::toConversationAttachedFile)
.filter(Objects::nonNull)
.toList();
}

private ConversationAttachedFile toConversationAttachedFile(TagDetails tag) {
if (tag instanceof FileTagDetails fileTagDetails) {
return new ConversationAttachedFile(fileTagDetails.getVirtualFile().getPath(), tag.getSelected());
}
if (tag instanceof FolderTagDetails folderTagDetails) {
return new ConversationAttachedFile(folderTagDetails.getFolder().getPath(), tag.getSelected());
}
return null;
}

private boolean isRememberAttachedFilesEnabled() {
return ConfigurationSettings.getState().getRememberAttachedFilesToChat();
}

public void sendMessage(Message message, ConversationType conversationType) {
sendMessage(message, conversationType, new HashSet<>());
}
Expand Down
Loading