Skip to content

Commit

Permalink
Refactor LocalService initialization & ensure newest values of devcha…
Browse files Browse the repository at this point in the history
…t service
  • Loading branch information
pplam committed Sep 20, 2024
1 parent 3a26e29 commit 80e9a31
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 43 deletions.
7 changes: 4 additions & 3 deletions src/main/kotlin/ai/devchat/core/BaseActionHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ abstract class BaseActionHandler(
var payload: JSONObject? = null
) : ActionHandler {
val devChatService: DevChatService = project.getService(DevChatService::class.java)
val wrapper: DevChatWrapper? = devChatService.wrapper
val browser: Browser? = devChatService.browser
val activeConversation: ActiveConversation? = devChatService.activeConversation
val client: DevChatClient? get() = devChatService.client
val wrapper: DevChatWrapper? get() = devChatService.wrapper
val browser: Browser? get() = devChatService.browser
val activeConversation: ActiveConversation? get() = devChatService.activeConversation
private val jsCallback: String = metadata?.getString("callback") ?: DEFAULT_RESPONSE_FUNC

abstract val actionName: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package ai.devchat.core.handlers

import ai.devchat.core.BaseActionHandler
import ai.devchat.core.DevChatActions
import ai.devchat.plugin.DevChatService
import com.alibaba.fastjson.JSONObject
import com.intellij.openapi.project.Project

Expand All @@ -15,7 +14,7 @@ class DeleteLastConversationRequestHandler(project: Project, requestAction: Stri
override val actionName: String = DevChatActions.DELETE_LAST_CONVERSATION_RESPONSE
override fun action() {
val promptHash = payload!!.getString("promptHash")
project.getService(DevChatService::class.java).client!!.deleteLog(promptHash)
client!!.deleteLog(promptHash)
send(payload = mapOf("promptHash" to promptHash))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package ai.devchat.core.handlers

import ai.devchat.core.BaseActionHandler
import ai.devchat.core.DevChatActions
import ai.devchat.plugin.DevChatService
import com.alibaba.fastjson.JSONObject
import com.intellij.openapi.project.Project

Expand All @@ -15,7 +14,7 @@ class DeleteTopicRequestHandler(project: Project, requestAction: String, metadat
override val actionName: String = DevChatActions.DELETE_TOPIC_RESPONSE
override fun action() {
val topicHash = payload!!.getString("topicHash")
project.getService(DevChatService::class.java).client!!.deleteTopic(topicHash)
client!!.deleteTopic(topicHash)
send(payload = mapOf("topicHash" to topicHash))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package ai.devchat.core.handlers

import ai.devchat.core.BaseActionHandler
import ai.devchat.core.DevChatActions
import ai.devchat.plugin.DevChatService
import com.alibaba.fastjson.JSONObject
import com.intellij.openapi.project.Project

Expand All @@ -15,7 +14,7 @@ class ListTopicsRequestHandler(project: Project, requestAction: String, metadata
) {
override val actionName: String = DevChatActions.LIST_TOPICS_RESPONSE
override fun action() {
val topics = project.getService(DevChatService::class.java).client!!.getTopics().map {
val topics = client!!.getTopics().map {
val request = it.rootPromptRequest
val response = it.rootPromptResponse
mapOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package ai.devchat.core.handlers

import ai.devchat.core.BaseActionHandler
import ai.devchat.core.DevChatActions
import ai.devchat.plugin.DevChatService
import com.alibaba.fastjson.JSONObject
import com.intellij.openapi.project.Project

Expand All @@ -21,8 +20,8 @@ class LoadConversationRequestHandler(project: Project, requestAction: String, me
topicHash.isNullOrEmpty() -> activeConversation!!.reset()
topicHash == activeConversation!!.topic -> res["reset"] = false
else -> {
val logs = project.getService(DevChatService::class.java).client!!.getTopicLogs(topicHash)
activeConversation.reset(topicHash, logs)
val logs = client!!.getTopicLogs(topicHash)
activeConversation!!.reset(topicHash, logs)
}
}
send(payload=res)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package ai.devchat.core.handlers
import ai.devchat.common.Log
import ai.devchat.common.PathUtils
import ai.devchat.core.*
import ai.devchat.plugin.DevChatService
import ai.devchat.storage.CONFIG
import com.alibaba.fastjson.JSONObject
import com.intellij.openapi.project.Project
Expand Down Expand Up @@ -53,7 +52,7 @@ class SendMessageRequestHandler(project: Project, requestAction: String, metadat
contextContents = contextContents,
)

project.getService(DevChatService::class.java).client!!.message(
client!!.message(
chatRequest,
dataHandler(chatRequest),
::errorHandler,
Expand Down Expand Up @@ -100,11 +99,10 @@ class SendMessageRequestHandler(project: Project, requestAction: String, metadat
}
private fun finishHandler(chatRequest: ChatRequest): (Int) -> Unit {
val response = chatRequest.response!!
val devChatService = project.getService(DevChatService::class.java)
return { exitCode: Int ->
when(exitCode) {
0 -> {
val entry = devChatService.client!!.insertLog(
val entry = client!!.insertLog(
LogEntry(
chatRequest.modelName,
chatRequest.parent,
Expand All @@ -117,12 +115,12 @@ class SendMessageRequestHandler(project: Project, requestAction: String, metadat
promptCallback(response)

val currentTopic = activeConversation!!.topic ?: response.promptHash!!
val logs = devChatService.client!!.getTopicLogs(currentTopic, 0, 1)
val logs = client!!.getTopicLogs(currentTopic, 0, 1)

if (currentTopic == activeConversation.topic) {
activeConversation.addMessage(logs.first())
if (currentTopic == activeConversation!!.topic) {
activeConversation!!.addMessage(logs.first())
} else {
activeConversation.reset(currentTopic, logs)
activeConversation!!.reset(currentTopic, logs)
}
}
-1 -> runWorkflow(chatRequest)
Expand Down
32 changes: 11 additions & 21 deletions src/main/kotlin/ai/devchat/installer/DevChatSetupThread.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,16 @@ import ai.devchat.common.*
import ai.devchat.common.Constants.ASSISTANT_NAME_EN
import ai.devchat.core.DevChatClient
import ai.devchat.plugin.DevChatService
import ai.devchat.plugin.LocalService
import ai.devchat.storage.CONFIG
import ai.devchat.storage.DevChatState
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.ui.content.Content
import java.io.BufferedReader
import java.io.File
import java.nio.file.Paths

class DevChatSetupThread(val project: Project, val toolWindowContent: Content) : Thread() {
class DevChatSetupThread(val project: Project) : Thread() {
private val minimalPythonVersion: String = "3.8"
private val defaultPythonVersion: String = "3.11.4"
private val devChatService = project.getService(DevChatService::class.java)
Expand All @@ -29,34 +26,22 @@ class DevChatSetupThread(val project: Project, val toolWindowContent: Content) :
Notifier.info("Starting $ASSISTANT_NAME_EN initialization...")
try {
Log.info("Start configuring the $ASSISTANT_NAME_EN CLI environment.")
setup(PythonEnvManager())
DevChatState.instance.lastVersion = devChatVersion
startLocalService()
setupPython(PythonEnvManager())
installTools()
updateWorkflows()
devChatService.browser?.executeJS("onInitializationFinish")
DevChatState.instance.lastVersion = devChatVersion
Notifier.info("$ASSISTANT_NAME_EN initialization has completed successfully.")
} catch (e: Exception) {
Log.error("Failed to install $ASSISTANT_NAME_EN CLI: $e\n" + e.stackTrace.joinToString("\n"))
Notifier.error("$ASSISTANT_NAME_EN initialization has failed. Please check the logs for more details.")
}
}

private fun startLocalService() {
try {
val localService = LocalService(project).start()
devChatService.localServicePort = localService.port!!
devChatService.client = DevChatClient(project, localService.port!!)
Disposer.register(toolWindowContent, localService)
} catch(e: Exception) {
Log.error("Failed to start local service: ${e.message}")
e.printStackTrace()
}
}

private fun setup(envManager: PythonEnvManager) {
private fun setupPython(envManager: PythonEnvManager) {
val overwrite = devChatVersion != DevChatState.instance.lastVersion
PathUtils.copyResourceDirToPath("/tools/site-packages", PathUtils.sitePackagePath, overwrite)
"python_for_chat".let{k ->
"python_for_chat".let { k ->
if (OSInfo.isWindows) {
val installDir = Paths.get(PathUtils.workPath, "python-win").toString()
PathUtils.copyResourceDirToPath("/tools/python-3.11.6-embed-amd64", installDir, overwrite)
Expand All @@ -73,6 +58,11 @@ class DevChatSetupThread(val project: Project, val toolWindowContent: Content) :
).pythonCommand
}
}
devChatService.pythonReady = true
}

private fun installTools() {
val overwrite = devChatVersion != DevChatState.instance.lastVersion
PathUtils.copyResourceDirToPath(
"/tools/code-editor/${PathUtils.codeEditorBinary}",
Paths.get(PathUtils.toolsPath, PathUtils.codeEditorBinary).toString(),
Expand Down
40 changes: 38 additions & 2 deletions src/main/kotlin/ai/devchat/plugin/DevChatToolWindowFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.intellij.openapi.wm.ToolWindow
import com.intellij.openapi.wm.ToolWindowFactory
import com.intellij.ui.JBColor
import com.intellij.ui.jcef.JBCefApp
import kotlinx.coroutines.*
import java.awt.BorderLayout
import javax.swing.BorderFactory
import javax.swing.JLabel
Expand All @@ -28,6 +29,7 @@ class DevChatService(project: Project) {
var ideServicePort: Int? = null
var client: DevChatClient? = null
var wrapper: DevChatWrapper? = null
var pythonReady: Boolean = false
var uiLoaded: Boolean = false
}

Expand All @@ -36,6 +38,7 @@ class DevChatToolWindowFactory : ToolWindowFactory, DumbAware, Disposable {
val devChatService = project.getService(DevChatService::class.java)
val browser = Browser(project)
devChatService.browser = browser

val panel = JPanel(BorderLayout())
if (!JBCefApp.isSupported()) {
Log.error("JCEF is not supported.")
Expand All @@ -47,9 +50,20 @@ class DevChatToolWindowFactory : ToolWindowFactory, DumbAware, Disposable {

val content = toolWindow.contentManager.factory.createContent(panel, "", false)
Disposer.register(content, this)
toolWindow.contentManager.addContent(content)
DevChatSetupThread(project, content).start()
Disposer.register(content, browser)

DevChatSetupThread(project).start()

CoroutineScope(Dispatchers.IO).launch {
withTimeoutOrNull(5000) {
while (!devChatService.pythonReady) { delay(100) }
LocalService(project).start()
}?.let {
Disposer.register(content, it)
devChatService.localServicePort = it.port!!
devChatService.client = DevChatClient(project, it.port!!)
}
}
IDEServer(project).start().let {
Disposer.register(content, it)
devChatService.ideServicePort = it.port
Expand All @@ -59,7 +73,29 @@ class DevChatToolWindowFactory : ToolWindowFactory, DumbAware, Disposable {
devChatService.wrapper = it
}
devChatService.activeConversation = ActiveConversation()

toolWindow.contentManager.addContent(content)
}

// private fun startLocalService() {
// val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
// Log.error("Failed to start local service: ${exception.message}")
// }
// coroutineScope = CoroutineScope(Dispatchers.Default)
// coroutineScope!!.launch(coroutineExceptionHandler) {
// try {
// while (!pythonReady) {
// delay(100)
// ensureActive()
// }
// localService = LocalService().start()
// awaitCancellation()
// } finally {
// localService?.stop()
// }
// }
// }


override fun dispose() {}
}

0 comments on commit 80e9a31

Please sign in to comment.