Skip to content

Commit

Permalink
Add support for local symf context (#326)
Browse files Browse the repository at this point in the history
Fixes #259

## Test plan

Manual testing using full QA guide.

Other than that:
1) Enable context
2) Ask repo-specific question
3) Check if response is based on the understanding of the local context

4) Disable context
5) Ask repo-specific question
6) Check if response is lacking previous insight

7) Click on refresh button and check if reindexing is in progress
8) Click on help button and check if it opens proper documentation page

<!-- All pull requests REQUIRE a test plan:
https://sourcegraph.com/docs/dev/background-information/testing_principles

Why does it matter?

These test plans are there to demonstrate that are following industry
standards which are important or critical for our customers.
They might be read by customers or an auditor. There are meant be simple
and easy to read. Simply explain what you did to ensure
your changes are correct!

Here are a non exhaustive list of test plan examples to help you:

- Making changes on a given feature or component:
- "Covered by existing tests" or "CI" for the shortest possible plan if
there is zero ambiguity
  - "Added new tests"
- "Manually tested" (if non trivial, share some output, logs, or
screenshot)
- Updating docs:
  - "previewed locally"
  - share a screenshot if you want to be thorough
- Updating deps, that would typically fail immediately in CI if
incorrect
  - "CI"
  - "locally tested"
-->
  • Loading branch information
pkukielka authored Jan 23, 2024
1 parent 03f259a commit e9f4386
Show file tree
Hide file tree
Showing 28 changed files with 235 additions and 492 deletions.
11 changes: 9 additions & 2 deletions src/main/java/com/sourcegraph/cody/CodyFocusChangeListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ public void focusGained(@NotNull Editor editor) {
if (!ConfigUtil.isCodyEnabled()) {
return;
}

Project project = editor.getProject();
if (project == null) {
return;
Expand All @@ -48,7 +47,15 @@ public void focusGained(@NotNull Editor editor) {

CodyAgentService.applyAgentOnBackgroundThread(
project,
agent -> agent.getServer().textDocumentDidFocus(TextDocument.fromPath(file.getPath())));
agent -> {
try {
// TODO: This is bad but needed to avoid race with file context of commands executed
// through context menu
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
agent.getServer().textDocumentDidFocus(TextDocument.fromPath(file.getPath()));
});

CodyAgentCodebase.getInstance(project).onFileOpened(project, file);
}
Expand Down
18 changes: 6 additions & 12 deletions src/main/java/com/sourcegraph/cody/LowerPanel.kt
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
package com.sourcegraph.cody

import com.intellij.ui.ColorUtil
import com.intellij.util.ui.UIUtil
import com.sourcegraph.cody.context.EmbeddingStatusView
import com.intellij.openapi.ui.VerticalFlowLayout
import com.sourcegraph.cody.context.ui.EnhancedContextPanel
import java.awt.BorderLayout
import javax.swing.BorderFactory
import javax.swing.BoxLayout
import javax.swing.JPanel

class LowerPanel(
stopGeneratingButtonPanel: JPanel,
promptPanel: PromptPanel,
embeddingStatusView: EmbeddingStatusView
contextView: EnhancedContextPanel
) : JPanel(BorderLayout()) {
init {
val borderColor = ColorUtil.brighter(UIUtil.getPanelBackground(), 3)
val topBorder = BorderFactory.createMatteBorder(1, 0, 0, 0, borderColor)
embeddingStatusView.border = topBorder
border = embeddingStatusView.border
layout = BoxLayout(this, BoxLayout.Y_AXIS)
border = contextView.border
layout = VerticalFlowLayout()
add(stopGeneratingButtonPanel)
add(promptPanel)
add(embeddingStatusView)
add(contextView)
}
}
6 changes: 4 additions & 2 deletions src/main/java/com/sourcegraph/cody/PromptPanel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import java.awt.event.ComponentAdapter
import java.awt.event.ComponentEvent
import java.awt.event.KeyAdapter
import java.awt.event.KeyEvent
import javax.swing.*
import javax.swing.JButton
import javax.swing.JLayeredPane
import javax.swing.KeyStroke
import javax.swing.border.EmptyBorder
import javax.swing.event.DocumentEvent
import javax.swing.text.DefaultEditorKit
Expand All @@ -28,7 +30,7 @@ class PromptPanel(
) : JLayeredPane() {

private var isInHistoryMode = true
private val autoGrowingTextArea = AutoGrowingTextArea(3, 9, this)
private val autoGrowingTextArea = AutoGrowingTextArea(5, 9, this)
private val scrollPane = autoGrowingTextArea.scrollPane
private val margin = 14
val textArea = autoGrowingTextArea.textArea
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/sourcegraph/cody/SubscriptionTabPanel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class SubscriptionTabPanel : JPanel() {
"</tr>" +
"</table>")
}
if (ApplicationInfo.getInstance().getBuild().baselineVersion <= 223) {
if (ApplicationInfo.getInstance().build.baselineVersion <= 223) {
separator()
} else {
row {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

public enum InlineAutocompleteTriggerKind {
Invoke,
Automatic;
Automatic
}
33 changes: 22 additions & 11 deletions src/main/kotlin/com/sourcegraph/cody/CodyToolWindowContent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import com.sourcegraph.cody.commands.ui.CommandsTabPanel
import com.sourcegraph.cody.config.CodyAccount
import com.sourcegraph.cody.config.CodyApplicationSettings
import com.sourcegraph.cody.config.CodyAuthenticationManager
import com.sourcegraph.cody.context.EmbeddingStatusView
import com.sourcegraph.cody.context.ui.EnhancedContextPanel
import com.sourcegraph.cody.ui.ChatScrollPane
import com.sourcegraph.cody.ui.SendButton
import com.sourcegraph.cody.vscode.CancellationToken
Expand All @@ -48,8 +48,12 @@ class CodyToolWindowContent(private val project: Project) : UpdatableChat {
private val stopGeneratingButton =
JButton("Stop generating", IconUtil.desaturate(AllIcons.Actions.Suspend))
private val commandsPanel: CommandsTabPanel =
CommandsTabPanel(project) { cmdId: CommandId -> sendMessage(project, message = null, cmdId) }
val embeddingStatusView: EmbeddingStatusView
CommandsTabPanel(project) { cmdId: CommandId ->
ApplicationManager.getApplication().invokeLater {
sendMessage(project, message = null, cmdId)
}
}
val contextView: EnhancedContextPanel
override var isChatVisible = false
override var id: String? = null
private var codyOnboardingGuidancePanel: CodyOnboardingGuidancePanel? = null
Expand Down Expand Up @@ -85,9 +89,7 @@ class CodyToolWindowContent(private val project: Project) : UpdatableChat {
sendButton,
isGenerating = stopGeneratingButton::isVisible)
val stopGeneratingButtonPanel = JPanel(FlowLayout(FlowLayout.CENTER, 0, 5))
stopGeneratingButtonPanel.preferredSize =
Dimension(Short.MAX_VALUE.toInt(), stopGeneratingButton.getPreferredSize().height + 10)

stopGeneratingButtonPanel.minimumSize = Dimension(Short.MAX_VALUE.toInt(), 0)
stopGeneratingButton.addActionListener {
inProgressChat.abort()
stopGeneratingButton.isVisible = false
Expand All @@ -99,8 +101,8 @@ class CodyToolWindowContent(private val project: Project) : UpdatableChat {
stopGeneratingButton.isVisible = false
stopGeneratingButtonPanel.add(stopGeneratingButton)
stopGeneratingButtonPanel.isOpaque = false
embeddingStatusView = EmbeddingStatusView(project)
val lowerPanel = LowerPanel(stopGeneratingButtonPanel, promptPanel, embeddingStatusView)
contextView = EnhancedContextPanel(project)
val lowerPanel = LowerPanel(stopGeneratingButtonPanel, promptPanel, contextView)

// Main content panel
contentPanel.layout = BorderLayout(0, 0)
Expand Down Expand Up @@ -128,6 +130,7 @@ class CodyToolWindowContent(private val project: Project) : UpdatableChat {
CodyAgentService.applyAgentOnBackgroundThread(project) { agent ->
fetchSubscriptionPanelData(project, agent.server).thenAccept {
if (it != null) {

ApplicationManager.getApplication().invokeLater { refreshSubscriptionTab(it) }
}
}
Expand All @@ -136,8 +139,10 @@ class CodyToolWindowContent(private val project: Project) : UpdatableChat {

@RequiresEdt
private fun refreshSubscriptionTab(data: SubscriptionTabPanelData) {
val isSubscriptionTabPresent = tabbedPane.tabCount >= SUBSCRIPTION_TAB_INDEX + 1

if (data.isDotcomAccount && data.codyProFeatureFlag) {
if (tabbedPane.tabCount < SUBSCRIPTION_TAB_INDEX + 1) {
if (!isSubscriptionTabPresent) {
tabbedPane.insertTab(
/* title = */ "Subscription",
/* icon = */ null,
Expand All @@ -146,7 +151,7 @@ class CodyToolWindowContent(private val project: Project) : UpdatableChat {
SUBSCRIPTION_TAB_INDEX)
}
subscriptionPanel.update(data.isCurrentUserPro)
} else if (SUBSCRIPTION_TAB_INDEX < tabbedPane.tabCount) {
} else if (isSubscriptionTabPresent) {
tabbedPane.remove(SUBSCRIPTION_TAB_INDEX)
}
}
Expand Down Expand Up @@ -347,7 +352,13 @@ class CodyToolWindowContent(private val project: Project) : UpdatableChat {
ApplicationManager.getApplication().executeOnPooledThread {
val chat = Chat()
try {
chat.sendMessageViaAgent(project, humanMessage, commandId, this, inProgressChat)
chat.sendMessageViaAgent(
project,
humanMessage,
commandId,
this,
inProgressChat,
contextView.isEnhancedContextEnabled.get())
} catch (e: Exception) {
logger.error("Error sending message '$humanMessage' to chat", e)
addMessageToChat(
Expand Down
44 changes: 6 additions & 38 deletions src/main/kotlin/com/sourcegraph/cody/agent/CodyAgentCodebase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,64 +5,32 @@ import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.sourcegraph.cody.CodyToolWindowContent
import com.sourcegraph.cody.config.CodyProjectSettings
import com.sourcegraph.common.ProjectFileUtils
import com.sourcegraph.config.ConfigUtil
import com.sourcegraph.vcs.RepoUtil

@Service(Service.Level.PROJECT)
class CodyAgentCodebase(val project: Project) {

fun initializeRepoName() {
ApplicationManager.getApplication().executeOnPooledThread {
onRepositoryNameChange(RepoUtil.findRepositoryName(project, null))
}
}

// TODO: Support list of repository names instead of just one.
private val application = ApplicationManager.getApplication()
private val settings = CodyProjectSettings.getInstance(project)
private var inferredUrl: String? = null

fun setUrl(url: String) {
settings.remoteUrl = url
onPropagateConfiguration()
}

fun getUrl(): String? = settings.remoteUrl ?: inferredUrl

fun onFileOpened(project: Project, file: VirtualFile) {
fun onFileOpened(project: Project, file: VirtualFile?) {
application.executeOnPooledThread {
onRepositoryNameChange(RepoUtil.findRepositoryName(project, file))
application.runReadAction {
val openedFileName = file.name
val relativeFilePath: String? = ProjectFileUtils.getRelativePathToProjectRoot(project, file)
ApplicationManager.getApplication().invokeLater {
CodyToolWindowContent.executeOnInstanceIfNotDisposed(project) {
embeddingStatusView.setOpenedFileName(openedFileName, relativeFilePath)
}
val repositoryName = RepoUtil.findRepositoryName(project, file)
if (repositoryName != null && inferredUrl != repositoryName) {
inferredUrl = repositoryName
CodyAgentService.applyAgentOnBackgroundThread(project) {
it.server.configurationDidChange(ConfigUtil.getAgentConfiguration(project))
}
}
}
}

private fun onPropagateConfiguration() {
CodyToolWindowContent.executeOnInstanceIfNotDisposed(project) {
embeddingStatusView.updateEmbeddingStatus()
}
CodyAgentService.applyAgentOnBackgroundThread(project) {
it.server.configurationDidChange(ConfigUtil.getAgentConfiguration(project))
}
}

private fun onRepositoryNameChange(repositoryName: String?) {
if (repositoryName != null && inferredUrl != repositoryName) {
inferredUrl = repositoryName
onPropagateConfiguration()
}
}

companion object {
@JvmStatic
fun getInstance(project: Project): CodyAgentCodebase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ package com.sourcegraph.cody.agent.protocol

import com.sourcegraph.cody.agent.WebviewMessage

data class ChatSubmitMessageParams(val id: String, val message: WebviewMessage) {}
data class ChatSubmitMessageParams(val id: String, val message: WebviewMessage)

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class CodyEditorFactoryListener : EditorFactoryListener {
val current = editorManager.getSelectedTextEditor(true)
return current != null && current == editor
}
val current = editorManager.getSelectedEditor()
val current = editorManager.selectedEditor
return current is TextEditor && editor == current.editor
}

Expand Down
Loading

0 comments on commit e9f4386

Please sign in to comment.