diff --git a/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/ChatCompletionTask.kt b/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/ChatCompletionTask.kt index 8b49d99d..6d9d815b 100644 --- a/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/ChatCompletionTask.kt +++ b/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/ChatCompletionTask.kt @@ -21,7 +21,7 @@ import java.awt.event.KeyEvent import javax.swing.KeyStroke open class ChatCompletionTask(private val request: CodeCompletionRequest) : - Task.Backgroundable(request.project, ShireCoreBundle.message("intentions.chat.code.complete.name")) { + ShireInteractionTask(request.project, ShireCoreBundle.message("intentions.chat.code.complete.name"), request.postExecute) { private val logger = logger() private var isCanceled: Boolean = false @@ -87,7 +87,7 @@ open class ChatCompletionTask(private val request: CodeCompletionRequest) : indicator.fraction = 0.8 logger.info("Suggestion: $suggestion") - val textRange: TextRange = TextRange(modifyStart, modifyEnd) + val textRange = TextRange(modifyStart, modifyEnd) request.postExecute.invoke(suggestion.toString(), textRange) indicator.fraction = 1.0 diff --git a/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/CodeCompletionTask.kt b/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/CodeCompletionTask.kt index 13cfc066..95f937ac 100644 --- a/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/CodeCompletionTask.kt +++ b/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/CodeCompletionTask.kt @@ -21,7 +21,7 @@ import kotlinx.coroutines.flow.cancellable import kotlinx.coroutines.launch class CodeCompletionTask(private val request: CodeCompletionRequest) : - Task.Backgroundable(request.project, ShireCoreBundle.message("intentions.chat.code.complete.name")) { + ShireInteractionTask(request.project, ShireCoreBundle.message("intentions.chat.code.complete.name"), request.postExecute) { private var isCanceled: Boolean = false diff --git a/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/FileGenerateTask.kt b/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/FileGenerateTask.kt index fe0741f6..ccef2bb0 100644 --- a/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/FileGenerateTask.kt +++ b/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/FileGenerateTask.kt @@ -27,9 +27,9 @@ open class FileGenerateTask( val fileName: String?, private val codeOnly: Boolean = false, private val taskName: String = ShireCoreBundle.message("intentions.request.background.process.title"), - val postExecute: PostFunction, + postExecute: PostFunction, ) : - Task.Backgroundable(project, taskName) { + ShireInteractionTask(project, taskName, postExecute) { private val projectRoot = project.guessProjectDir()!! override fun run(indicator: ProgressIndicator) { @@ -74,7 +74,7 @@ open class FileGenerateTask( refreshAndOpenInEditor(Path(projectRoot.path), projectRoot) } - postExecute.invoke(result, null) + postExecute?.invoke(result, null) } private fun refreshAndOpenInEditor(file: Path, parentDir: VirtualFile) = runBlocking { diff --git a/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/ShireInteractionTask.kt b/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/ShireInteractionTask.kt new file mode 100644 index 00000000..1fc8b7fc --- /dev/null +++ b/core/src/main/kotlin/com/phodal/shirecore/config/interaction/task/ShireInteractionTask.kt @@ -0,0 +1,22 @@ +package com.phodal.shirecore.config.interaction.task + +import com.intellij.openapi.progress.Task.Backgroundable +import com.intellij.openapi.project.Project +import com.phodal.shirecore.config.interaction.PostFunction +import java.util.concurrent.CompletableFuture + +/** + * @author lk + */ +abstract class ShireInteractionTask(project: Project, taskName: String, val postExecute: PostFunction?): Backgroundable(project, taskName) { + + /** + * An unexpected exception occurred, causing the shire process cannot be canceled, + * postExecute was not executed,it may have used the [CompletableFuture]. + */ + override fun onThrowable(error: Throwable) { + super.onThrowable(error) + postExecute?.invoke(null, null) + } + +} \ No newline at end of file diff --git a/shirelang/src/main/kotlin/com/phodal/shirelang/actions/ShireRunFileAction.kt b/shirelang/src/main/kotlin/com/phodal/shirelang/actions/ShireRunFileAction.kt index eb6d480b..c341db46 100644 --- a/shirelang/src/main/kotlin/com/phodal/shirelang/actions/ShireRunFileAction.kt +++ b/shirelang/src/main/kotlin/com/phodal/shirelang/actions/ShireRunFileAction.kt @@ -134,7 +134,7 @@ class ShireRunFileAction : DumbAwareAction() { val hintDisposable = Disposer.newDisposable() val connection = ApplicationManager.getApplication().messageBus.connect(hintDisposable) connection.subscribe(ShireRunListener.TOPIC, object : ShireRunListener { - override fun runFinish(allOutput: String, llmOutput: String, event: ProcessEvent, scriptPath: String) { + override fun runFinish(allOutput: String, llmOutput: String, event: ProcessEvent, scriptPath: String, consoleView: ShireConsoleView?) { future.complete(llmOutput) } }) diff --git a/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireProcessHandler.kt b/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireProcessHandler.kt index 912d03b1..2773a7b5 100644 --- a/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireProcessHandler.kt +++ b/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireProcessHandler.kt @@ -4,7 +4,7 @@ import com.intellij.build.process.BuildProcessHandler import java.io.OutputStream class ShireProcessHandler(private val myExecutionName: String) : BuildProcessHandler() { - override fun detachIsDefault(): Boolean = false + override fun detachIsDefault(): Boolean = true override fun destroyProcessImpl() = Unit override fun detachProcessImpl() { try { diff --git a/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireProgramRunner.kt b/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireProgramRunner.kt index 8bda78c0..6f2b1b67 100644 --- a/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireProgramRunner.kt +++ b/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireProgramRunner.kt @@ -29,14 +29,13 @@ class ShireProgramRunner : GenericProgramRunner(), Disposable { if (environment.runProfile !is ShireConfiguration) return null val shireState = state as ShireRunConfigurationProfileState - var executeResult: ExecutionResult? = null + var executeResult: ExecutionResult? val result = AtomicReference() if (!isSubscribed) { connection.subscribe(ShireRunListener.TOPIC, object : ShireRunListener { - override fun runFinish(allOutput: String, llmOutput: String, event: ProcessEvent, scriptPath: String) { - val consoleView = (environment.state as? ShireRunConfigurationProfileState)?.console + override fun runFinish(allOutput: String, llmOutput: String, event: ProcessEvent, scriptPath: String, consoleView: ShireConsoleView?) { environment.project.getService(ShireProcessProcessor::class.java) .process(allOutput, event, scriptPath, consoleView) diff --git a/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireRunConfigurationProfileState.kt b/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireRunConfigurationProfileState.kt index 3fd597d8..7c6b3ebd 100644 --- a/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireRunConfigurationProfileState.kt +++ b/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireRunConfigurationProfileState.kt @@ -36,28 +36,21 @@ open class ShireRunConfigurationProfileState( private val myProject: Project, private val configuration: ShireConfiguration, ) : RunProfileState, Disposable { - private var executionConsole: ConsoleViewImpl? = null + private var executionConsole: ShireExecutionConsole? = null var console: ShireConsoleView? = null var isShowRunContent = true override fun execute(executor: Executor?, runner: ProgramRunner<*>): ExecutionResult { - executionConsole = ConsoleViewImpl(myProject, true) + executionConsole = ShireExecutionConsole(myProject, true) console = ShireConsoleView(executionConsole!!) val processHandler = ShireProcessHandler(configuration.name) ProcessTerminatedListener.attach(processHandler) - val sb = StringBuilder() - val processAdapter = ShireProcessAdapter(sb, configuration) + val processAdapter = ShireProcessAdapter(configuration, console) processHandler.addProcessListener(processAdapter) - // start message log in here - console!!.addMessageFilter { line, _ -> - sb.append(line) - null - } - console!!.attachToProcess(processHandler) val shireFile: ShireFile? = ShireFile.lookup(myProject, configuration.getScriptPath()) @@ -97,7 +90,7 @@ open class ShireRunConfigurationProfileState( } } -class ShireConsoleView(private val executionConsole: ConsoleViewImpl) : +class ShireConsoleView(private val executionConsole: ShireExecutionConsole) : ConsoleViewWrapperBase(executionConsole) { override fun getComponent(): JComponent = myPanel private var myPanel: NonOpaquePanel = NonOpaquePanel(BorderLayout()) @@ -112,13 +105,15 @@ class ShireConsoleView(private val executionConsole: ConsoleViewImpl) : myPanel.add(toolbar.component, BorderLayout.EAST) } + fun output(clearAndStop: Boolean = true) = executionConsole.getOutput(clearAndStop) + override fun dispose() { super.dispose() executionConsole.dispose() } } -class ShireProcessAdapter(private val sb: StringBuilder, val configuration: ShireConfiguration) : ProcessAdapter() { +class ShireProcessAdapter(val configuration: ShireConfiguration, val consoleView: ShireConsoleView?) : ProcessAdapter() { var result = "" private var llmOutput: String = "" @@ -127,12 +122,12 @@ class ShireProcessAdapter(private val sb: StringBuilder, val configuration: Shir ApplicationManager.getApplication().messageBus .syncPublisher(ShireRunListener.TOPIC) - .runFinish(result, llmOutput, event, configuration.getScriptPath()) + .runFinish(result, llmOutput, event, configuration.getScriptPath(), consoleView) } override fun onTextAvailable(event: ProcessEvent, outputType: Key<*>) { super.onTextAvailable(event, outputType) - result = sb.toString() + result = consoleView?.output().toString() } fun setLlmOutput(llmOutput: String?) { @@ -141,3 +136,24 @@ class ShireProcessAdapter(private val sb: StringBuilder, val configuration: Shir } } } + +class ShireExecutionConsole(project: Project, viewer: Boolean, var isStopped: Boolean = false): ConsoleViewImpl(project, viewer) { + + private val output = StringBuilder() + + override fun print(text: String, contentType: ConsoleViewContentType) { + super.print(text, contentType) + if (!isStopped) output.append(text) + } + + fun getOutput(clearAndStop: Boolean): String { + val o = output.toString() + if (clearAndStop) { + isStopped = true + output.clear() + } + + return o + } + +} \ No newline at end of file diff --git a/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireRunListener.kt b/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireRunListener.kt index 9be449fa..627a1060 100644 --- a/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireRunListener.kt +++ b/shirelang/src/main/kotlin/com/phodal/shirelang/run/ShireRunListener.kt @@ -13,8 +13,9 @@ interface ShireRunListener : EventListener { * @param llmOutput LLM output * @param event ProcessEvent * @param scriptPath script path + * @param consoleView shire consoleView */ - fun runFinish(allOutput: String, llmOutput: String, event: ProcessEvent, scriptPath: String) + fun runFinish(allOutput: String, llmOutput: String, event: ProcessEvent, scriptPath: String, consoleView: ShireConsoleView?) companion object { @Topic.AppLevel diff --git a/shirelang/src/main/kotlin/com/phodal/shirelang/run/executor/ShireDefaultLlmExecutor.kt b/shirelang/src/main/kotlin/com/phodal/shirelang/run/executor/ShireDefaultLlmExecutor.kt index 80456699..e00b3dad 100644 --- a/shirelang/src/main/kotlin/com/phodal/shirelang/run/executor/ShireDefaultLlmExecutor.kt +++ b/shirelang/src/main/kotlin/com/phodal/shirelang/run/executor/ShireDefaultLlmExecutor.kt @@ -84,7 +84,7 @@ class ShireDefaultLlmExecutor( postFunction(response, null) context.processHandler.detachProcess() } - }, ModalityState.NON_MODAL) + }, ModalityState.nonModal()) } } diff --git a/shirelang/src/main/kotlin/com/phodal/shirelang/run/runner/ShireRunner.kt b/shirelang/src/main/kotlin/com/phodal/shirelang/run/runner/ShireRunner.kt index 25a2f2dc..bd96c011 100644 --- a/shirelang/src/main/kotlin/com/phodal/shirelang/run/runner/ShireRunner.kt +++ b/shirelang/src/main/kotlin/com/phodal/shirelang/run/runner/ShireRunner.kt @@ -256,8 +256,7 @@ class ShireRunner( currentFile = file, editor = editor, compiledVariables = compiledVariables, - ) - PostCodeHandleContext.updateContextAndVariables(context) + ).also { PostCodeHandleContext.updateContextAndVariables(it) } hobbitHole?.setupStreamingEndProcessor(project, context) }