Skip to content

Commit

Permalink
fix(124): support stop chat
Browse files Browse the repository at this point in the history
  • Loading branch information
hanrw committed Apr 16, 2024
1 parent 2908e41 commit 6ad68aa
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/main/kotlin/cc/unitmesh/devti/gui/chat/AutoDevInput.kt
Expand Up @@ -37,6 +37,7 @@ enum class AutoDevInputTrigger {
interface AutoDevInputListener : EventListener {
fun editorAdded(editor: EditorEx) {}
fun onSubmit(component: AutoDevInputSection, trigger: AutoDevInputTrigger) {}
fun onStop(component: AutoDevInputSection) {}
}

class AutoDevInput(
Expand Down
57 changes: 47 additions & 10 deletions src/main/kotlin/cc/unitmesh/devti/gui/chat/AutoDevInputSection.kt
Expand Up @@ -32,15 +32,16 @@ import com.intellij.util.ui.JBEmptyBorder
import com.intellij.util.ui.JBUI
import com.intellij.util.ui.UIUtil
import com.intellij.util.ui.components.BorderLayoutPanel
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import java.awt.CardLayout
import java.awt.Color
import java.awt.Dimension
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.util.function.Supplier
import javax.swing.Box
import javax.swing.JComponent
import javax.swing.JPanel
import kotlin.math.max
import kotlin.math.min

Expand All @@ -50,8 +51,11 @@ import kotlin.math.min
class AutoDevInputSection(private val project: Project, val disposable: Disposable?) : BorderLayoutPanel() {
private val input: AutoDevInput
private val documentListener: DocumentListener
private val buttonPresentation: Presentation
private val button: ActionButton
private val sendButtonPresentation: Presentation
private val stopButtonPresentation: Presentation
private val sendButton: ActionButton
private val stopButton: ActionButton
private val buttonPanel = JPanel(CardLayout())

private val defaultRag: CustomAgentConfig = CustomAgentConfig("<Select Custom Agent>", "Normal")
private var customRag: ComboBox<CustomAgentConfig> = ComboBox(MutableCollectionComboBoxModel(listOf()))
Expand All @@ -70,18 +74,37 @@ class AutoDevInputSection(private val project: Project, val disposable: Disposab
}

init {
val presentation = Presentation(AutoDevBundle.message("chat.panel.send"))
presentation.setIcon(AutoDevIcons.Send)
buttonPresentation = presentation
button = ActionButton(
val sendButtonPresentation = Presentation(AutoDevBundle.message("chat.panel.send"))
sendButtonPresentation.setIcon(AutoDevIcons.Send)
this.sendButtonPresentation = sendButtonPresentation

val stopButtonPresentation = Presentation("Stop")
stopButtonPresentation.setIcon(AutoDevIcons.Idea)
this.stopButtonPresentation = stopButtonPresentation

sendButton = ActionButton(
DumbAwareAction.create {
object : DumbAwareAction("") {
override fun actionPerformed(e: AnActionEvent) {
showStopButton()
editorListeners.multicaster.onSubmit(this@AutoDevInputSection, AutoDevInputTrigger.Button)
}
}.actionPerformed(it)
},
buttonPresentation,
this.sendButtonPresentation,
"",
Dimension(20, 20)
)

stopButton = ActionButton(
DumbAwareAction.create {
object : DumbAwareAction("") {
override fun actionPerformed(e: AnActionEvent) {
editorListeners.multicaster.onStop(this@AutoDevInputSection)
}
}.actionPerformed(it)
},
this.stopButtonPresentation,
"",
Dimension(20, 20)
)
Expand Down Expand Up @@ -125,13 +148,17 @@ class AutoDevInputSection(private val project: Project, val disposable: Disposab
layoutPanel.addToLeft(customRag)
}


buttonPanel.add(sendButton, "Send")
buttonPanel.add(stopButton, "Stop")

layoutPanel.addToCenter(horizontalGlue)
layoutPanel.addToRight(button)
layoutPanel.addToRight(buttonPanel)
addToBottom(layoutPanel)

ComponentValidator(disposable!!).withValidator(Supplier<ValidationInfo?> {
val validationInfo: ValidationInfo? = this.getInputValidationInfo()
button.setEnabled(validationInfo == null)
sendButton.setEnabled(validationInfo == null)
return@Supplier validationInfo
}).installOn((this as JComponent)).revalidate()

Expand All @@ -144,6 +171,16 @@ class AutoDevInputSection(private val project: Project, val disposable: Disposab
tokenizer = TokenizerImpl.INSTANCE
}

fun showStopButton() {
(buttonPanel.layout as? CardLayout)?.show(buttonPanel, "Stop")
stopButton.isEnabled = true
}

fun showSendButton() {
(buttonPanel.layout as? CardLayout)?.show(buttonPanel, "Send")
buttonPanel.isEnabled = true
}

private fun loadRagApps(): List<CustomAgentConfig> {
val ragsJsonConfig = project.customAgentSetting.ragsJsonConfig
if (ragsJsonConfig.isEmpty()) return listOf(defaultRag)
Expand Down
8 changes: 8 additions & 0 deletions src/main/kotlin/cc/unitmesh/devti/gui/chat/ChatCodingPanel.kt
Expand Up @@ -90,10 +90,17 @@ class ChatCodingPanel(private val chatCodingService: ChatCodingService, val disp

inputSection = AutoDevInputSection(chatCodingService.project, disposable)
inputSection.addListener(object : AutoDevInputListener {
override fun onStop(component: AutoDevInputSection) {
chatCodingService.stop()
inputSection.showSendButton()
}

override fun onSubmit(component: AutoDevInputSection, trigger: AutoDevInputTrigger) {
var prompt = component.text
component.text = ""

inputSection.showStopButton()

if (prompt.isEmpty() || prompt == "\n") {
return
}
Expand Down Expand Up @@ -216,6 +223,7 @@ class ChatCodingPanel(private val chatCodingService: ChatCodingService, val disp
var text = ""
content.onCompletion {
logger.info("onCompletion ${it?.message}")
inputSection.showSendButton()
}.catch {
it.printStackTrace()
}.collect {
Expand Down
12 changes: 10 additions & 2 deletions src/main/kotlin/cc/unitmesh/devti/gui/chat/ChatCodingService.kt
Expand Up @@ -13,6 +13,7 @@ import cc.unitmesh.devti.provider.ContextPrompter
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch

Expand All @@ -22,14 +23,21 @@ class ChatCodingService(var actionType: ChatActionType, val project: Project) {

val action = actionType.instruction(project = project).requestText

var currentJob: Job? = null

fun getLabel(): String = "$actionType Code"

fun stop() {
currentJob?.cancel()
}

fun handlePromptAndResponse(
ui: ChatCodingPanel,
prompter: ContextPrompter,
context: ChatContext? = null,
newChatContext: Boolean
) {
currentJob?.cancel()
var requestPrompt = prompter.requestPrompt()
var displayPrompt = prompter.displayPrompt()

Expand Down Expand Up @@ -59,7 +67,7 @@ class ChatCodingService(var actionType: ChatActionType, val project: Project) {

ApplicationManager.getApplication().executeOnPooledThread {
val response = this.makeChatBotRequest(requestPrompt, newChatContext)
LLMCoroutineScope.scope(project).launch {
currentJob = LLMCoroutineScope.scope(project).launch {
when {
actionType === ChatActionType.REFACTOR -> ui.updateReplaceableContent(response) {
context?.postAction?.invoke(it)
Expand All @@ -84,7 +92,7 @@ class ChatCodingService(var actionType: ChatActionType, val project: Project) {
ApplicationManager.getApplication().executeOnPooledThread {
val response = llmProvider.stream(requestPrompt, systemPrompt)

LLMCoroutineScope.scope(project).launch {
currentJob = LLMCoroutineScope.scope(project).launch {
ui.updateMessage(response)
}
}
Expand Down

0 comments on commit 6ad68aa

Please sign in to comment.