Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.3.1 fixes #148

Merged
merged 11 commits into from
Jun 3, 2024
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ dependencies {


group = "com.smallcloud"
version = getVersionString("1.3.0")
version = getVersionString("1.3.1")

repositories {
mavenCentral()
Expand Down
6 changes: 2 additions & 4 deletions src/main/kotlin/com/smallcloud/refactai/account/LoginUser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ private fun tryLoginWithApiKey(): String {
val body = gson.fromJson(result.body, JsonObject::class.java)
val retcode = body.get("retcode").asString
val humanReadableMessage = if (body.has("human_readable_message")) body.get("human_readable_message").asString else ""
AccountManager.activePlan = null
AccountManager.user = null
if (retcode == "OK") {
if (body.has("account")) {
AccountManager.user = body.get("account").asString
Expand Down Expand Up @@ -151,14 +153,10 @@ private fun tryLoginWithApiKey(): String {
UsageStats?.addStatistic(false, UsageStatistic("login-failed"), url.toString(), humanReadableMessage)
return "OK"
} else if (retcode == "FAILED") {
AccountManager.user = null
AccountManager.activePlan = null
logError("login-failed", humanReadableMessage)
UsageStats?.addStatistic(false, UsageStatistic("login-failed"), url.toString(), humanReadableMessage)
return ""
} else {
AccountManager.user = null
AccountManager.activePlan = null
logError("login-failed", "unrecognized response")
UsageStats?.addStatistic(false, UsageStatistic("login (2)"), url.toString(), "unrecognized response")
return ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,15 @@ class InferenceGlobalContext : Disposable {
.astFlagChanged(newValue)
}

var astFileLimit: Int
get() { return AppSettingsState.astFileLimit }
set(newValue) {
if (newValue == astFileLimit) return
messageBus
.syncPublisher(InferenceGlobalContextChangedNotifier.TOPIC)
.astFileLimitChanged(newValue)
}

var vecdbIsEnabled: Boolean
get() = AppSettingsState.vecdbIsEnabled
set(newValue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface InferenceGlobalContextChangedNotifier {
fun developerModeEnabledChanged(newValue: Boolean) {}
fun deploymentModeChanged(newMode: DeploymentMode) {}
fun astFlagChanged(newValue: Boolean) {}
fun astFileLimitChanged(newValue: Int) {}
fun vecdbFlagChanged(newValue: Boolean) {}
fun xDebugLSPPortChanged(newPort: Int?) {}

Expand Down
7 changes: 7 additions & 0 deletions src/main/kotlin/com/smallcloud/refactai/lsp/LSPConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ data class LSPConfig(
var useTelemetry: Boolean = false,
var deployment: DeploymentMode = DeploymentMode.CLOUD,
var ast: Boolean = false,
var astFileLimit: Int? = null,
var vecdb: Boolean = false
) {
fun toArgs(): List<String> {
Expand All @@ -36,6 +37,10 @@ data class LSPConfig(
if (ast) {
params.add("--ast")
}
if (astFileLimit != null) {
params.add("--ast-index-max-files")
params.add("$astFileLimit")
}
if (vecdb) {
params.add("--vecdb")
}
Expand All @@ -55,6 +60,7 @@ data class LSPConfig(
if (deployment != other.deployment) return false
if (ast != other.ast) return false
if (vecdb != other.vecdb) return false
if (astFileLimit != other.astFileLimit) return false

return true
}
Expand All @@ -64,6 +70,7 @@ data class LSPConfig(
return address != null
&& port != null
&& clientVersion != null
&& (astFileLimit != null && astFileLimit!! > 0)
// token must be if we are not selfhosted
&& (deployment == DeploymentMode.SELF_HOSTED ||
(apiKey != null && (deployment == DeploymentMode.CLOUD || deployment == DeploymentMode.HF)))
Expand Down
37 changes: 31 additions & 6 deletions src/main/kotlin/com/smallcloud/refactai/lsp/LSPProcessHolder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class LSPProcessHolder(val project: Project): Disposable {
private var process: Process? = null
private var lastConfig: LSPConfig? = null
private val logger = Logger.getInstance("LSPProcessHolder")
private val scheduler = AppExecutorUtil.createBoundedScheduledExecutorService(
private val loggerScheduler = AppExecutorUtil.createBoundedScheduledExecutorService(
"SMCLSPLoggerScheduler", 1
)
private var loggerTask: Future<*>? = null
Expand All @@ -63,7 +63,9 @@ class LSPProcessHolder(val project: Project): Disposable {
private var capsTask: Future<*>? = null
private val messageBus: MessageBus = ApplicationManager.getApplication().messageBus
private var isWorking = false

private val healthCheckerScheduler = AppExecutorUtil.createBoundedScheduledExecutorService(
"SMCLSHealthCheckerScheduler", 1
)

init {
messageBus
Expand All @@ -74,6 +76,12 @@ class LSPProcessHolder(val project: Project): Disposable {
settingsChanged()
}
}

override fun planStatusChanged(newPlan: String?) {
AppExecutorUtil.getAppScheduledExecutorService().submit {
settingsChanged()
}
}
})
messageBus
.connect(this)
Expand All @@ -88,6 +96,11 @@ class LSPProcessHolder(val project: Project): Disposable {
settingsChanged()
}
}
override fun astFileLimitChanged(newValue: Int) {
AppExecutorUtil.getAppScheduledExecutorService().submit {
settingsChanged()
}
}
override fun vecdbFlagChanged(newValue: Boolean) {
AppExecutorUtil.getAppScheduledExecutorService().submit {
settingsChanged()
Expand Down Expand Up @@ -121,6 +134,14 @@ class LSPProcessHolder(val project: Project): Disposable {
}
settingsChanged()

healthCheckerScheduler.scheduleWithFixedDelay({
if (lastConfig == null) return@scheduleWithFixedDelay
if (InferenceGlobalContext.xDebugLSPPort != null) return@scheduleWithFixedDelay
if (process?.isAlive == false) {
startProcess()
}
}, 1, 1, TimeUnit.SECONDS)

capsTask = schedulerCaps.scheduleWithFixedDelay({
capabilities = getCaps()
if (capabilities.cloudName.isNotEmpty()) {
Expand Down Expand Up @@ -168,19 +189,22 @@ class LSPProcessHolder(val project: Project): Disposable {
useTelemetry = true,
deployment = InferenceGlobalContext.deploymentMode,
ast = InferenceGlobalContext.astIsEnabled,
astFileLimit = InferenceGlobalContext.astFileLimit,
vecdb = InferenceGlobalContext.vecdbIsEnabled,
)

if (newConfig == lastConfig) return
val processIsAlive = process?.isAlive == true

if (newConfig == lastConfig && processIsAlive) return

capabilities = LSPCapabilities()
terminate()
if (!newConfig.isValid) return
logger.warn("LSP start_process " + BIN_PATH + " " + newConfig.toArgs())
var attempt = 0
while (attempt < 5) {
try {
newConfig.port = (32000..32199).random()
logger.warn("LSP start_process " + BIN_PATH + " " + newConfig.toArgs())
process = GeneralCommandLine(listOf(BIN_PATH) + newConfig.toArgs())
.withRedirectErrorStream(true)
.createProcess()
Expand All @@ -195,7 +219,7 @@ class LSPProcessHolder(val project: Project): Disposable {
}
}
}
loggerTask = scheduler.submit {
loggerTask = loggerScheduler.submit {
val reader = process!!.inputStream.bufferedReader()
var line = reader.readLine()
while (line != null) {
Expand Down Expand Up @@ -258,8 +282,9 @@ class LSPProcessHolder(val project: Project): Disposable {

override fun dispose() {
terminate()
scheduler.shutdown()
loggerScheduler.shutdown()
schedulerCaps.shutdown()
healthCheckerScheduler.shutdown()
}

private fun getBuildInfo(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,9 @@ class CompletionMode(
completionData: Completion,
animation: Boolean
) {
var modificationStamp: Long = state.modificationStamp
var offset: Int = state.offset
app.invokeAndWait {
modificationStamp = editor.document.modificationStamp
offset = editor.caretModel.offset
}
val modificationStamp = editor.document.modificationStamp
val offset = editor.caretModel.offset

val invalidStamp = state.modificationStamp != modificationStamp
val invalidOffset = state.offset != offset
if (invalidStamp || invalidOffset) {
Expand Down Expand Up @@ -264,10 +261,12 @@ class CompletionMode(
return@streamedInferenceFetch
}
completion.updateCompletion(choice.delta)
synchronized(this) {
renderCompletion(
editorState.editor, editorState, completion, !prediction.cached
)
app.invokeLater {
synchronized(this) {
renderCompletion(
editorState.editor, editorState, completion, !prediction.cached
)
}
}
}?.also {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,15 @@ class ChatWebView(val messageHandler: (event: Events.FromChat) -> Unit): Dispos
}

val webView by lazy {
val osName = System.getProperty("os.name").lowercase()
val useOsr = when {
osName.contains("mac") || osName.contains("darwin") -> false
osName.contains("win") -> false
osName.contains("nix") || osName.contains("nux") || osName.contains("aix") -> true
else -> true
}
// TODO: handle JBCef not being available
val browser = JBCefBrowser()
val browser = JBCefBrowser.createBuilder().setOffScreenRendering(useOsr).build()
browser.jbCefClient.setProperty(
JBCefClient.Properties.JS_QUERY_POOL_SIZE,
jsPoolSize,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ class AppSettingsComponent {
}
private val myContrastUrlText = JBTextField()
private val myModelText = JBTextField()
private val astCheckbox = JCheckBox(RefactAIBundle.message("advancedSettings.useMultipleFilesCompletion"))
private val myAstFileLimitText = JBTextField()
val astCheckbox = JCheckBox(RefactAIBundle.message("advancedSettings.useMultipleFilesCompletion")).apply {
isVisible = true
}
private val developerModeCheckBox = JCheckBox(RefactAIBundle.message("advancedSettings.developerMode")).apply {
isVisible = false
}
Expand All @@ -60,7 +63,7 @@ class AppSettingsComponent {
}
private val defaultSystemPromptTextArea = JBTextArea()

private val vecdbCheckbox = JCheckBox("VECDB").apply {
val vecdbCheckbox = JCheckBox(RefactAIBundle.message("advancedSettings.useVecDB")).apply {
isVisible = true
}

Expand All @@ -87,6 +90,25 @@ class AppSettingsComponent {
JBLabel(
RefactAIBundle.message("advancedSettings.useMultipleFilesCompletionDescription"),
UIUtil.ComponentStyle.SMALL, UIUtil.FontColor.BRIGHTER
).apply {
setCopyable(true)
}, 0
)
addComponent(vecdbCheckbox, UIUtil.LARGE_VGAP)
addComponent(
JBLabel(
RefactAIBundle.message("advancedSettings.useVecDBDescription"),
UIUtil.ComponentStyle.SMALL, UIUtil.FontColor.BRIGHTER
).apply {
setCopyable(true)
}, 0
)
addLabeledComponent(JBLabel("${RefactAIBundle.message("advancedSettings.astFileLimit")}: "), myAstFileLimitText,
(UIUtil.DEFAULT_VGAP * 1.5).toInt(), false)
addComponent(
JBLabel(
RefactAIBundle.message("advancedSettings.astFileLimitDescription"),
UIUtil.ComponentStyle.SMALL, UIUtil.FontColor.BRIGHTER
), 0
)
addLabeledComponent(JBLabel("${RefactAIBundle.message("advancedSettings.codeCompletionModel")}: "),
Expand All @@ -109,8 +131,6 @@ class AppSettingsComponent {
addComponent(developerModeCheckBox, UIUtil.LARGE_VGAP)
addLabeledComponent(myXDebugLSPPortLabel, myXDebugLSPPort, UIUtil.LARGE_VGAP)
addLabeledComponent(myStagingVersionLabel, myStagingVersionText, UIUtil.LARGE_VGAP)
addComponent(astCheckbox, UIUtil.LARGE_VGAP)
addComponent(vecdbCheckbox, UIUtil.LARGE_VGAP)
addComponentFillVertically(JPanel(), 0)
}.panel

Expand Down Expand Up @@ -151,6 +171,11 @@ class AppSettingsComponent {
set(newVal) {
astCheckbox.isSelected = newVal
}
var astFileLimit: Int
get() = myAstFileLimitText.text.toIntOrNull() ?: 15000
set(newVal) {
myAstFileLimitText.text = newVal.toString()
}
var vecdbIsEnabled: Boolean
get() = vecdbCheckbox.isSelected
set(newVal) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.smallcloud.refactai.settings

import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.options.Configurable
import com.intellij.openapi.project.ProjectManager
import com.smallcloud.refactai.PluginState
import com.smallcloud.refactai.account.AccountManagerChangedNotifier
import org.jetbrains.annotations.Nls
Expand All @@ -21,10 +20,11 @@ class AppSettingsConfigurable : Configurable {
.subscribe(AccountManagerChangedNotifier.TOPIC, object : AccountManagerChangedNotifier {
override fun apiKeyChanged(newApiKey: String?) {
mySettingsComponent?.myTokenText?.let { it.text = newApiKey }
mySettingsComponent?.astIsEnabled = InferenceGlobalContext.astIsEnabled
mySettingsComponent?.vecdbIsEnabled = InferenceGlobalContext.vecdbIsEnabled
mySettingsComponent?.splitter?.revalidate()
}
})
val project = ProjectManager.getInstance().openProjects.first()
}

// A default constructor with no arguments is required because this implementation
Expand Down Expand Up @@ -53,12 +53,12 @@ class AppSettingsConfigurable : Configurable {
override fun isModified(): Boolean {
var modified =
(mySettingsComponent!!.tokenText.isNotEmpty() && (AccountManager.apiKey == null ||
mySettingsComponent!!.tokenText.trim() != AccountManager.apiKey))
mySettingsComponent!!.tokenText.trim() != AccountManager.apiKey))
modified = modified || (mySettingsComponent!!.tokenText.isEmpty() && AccountManager.apiKey != null)

modified =
modified || (mySettingsComponent!!.contrastUrlText.isNotEmpty() &&
mySettingsComponent!!.contrastUrlText != InferenceGlobalContext.inferenceUri)
mySettingsComponent!!.contrastUrlText != InferenceGlobalContext.inferenceUri)
modified =
modified || (mySettingsComponent!!.contrastUrlText.isEmpty() && !InferenceGlobalContext.isCloud)

Expand All @@ -67,12 +67,15 @@ class AppSettingsConfigurable : Configurable {
modified = modified || mySettingsComponent!!.xDebugLSPPort != InferenceGlobalContext.xDebugLSPPort

modified = modified || mySettingsComponent!!.stagingVersion != InferenceGlobalContext.stagingVersion
modified = modified || mySettingsComponent!!.defaultSystemPrompt != AppSettingsState.instance.defaultSystemPrompt
modified =
modified || mySettingsComponent!!.defaultSystemPrompt != AppSettingsState.instance.defaultSystemPrompt

modified = modified || mySettingsComponent!!.astIsEnabled != InferenceGlobalContext.astIsEnabled
modified = modified || mySettingsComponent!!.astFileLimit != InferenceGlobalContext.astFileLimit
modified = modified || mySettingsComponent!!.vecdbIsEnabled != InferenceGlobalContext.vecdbIsEnabled

modified = modified || mySettingsComponent!!.inferenceModel?.trim()?.ifEmpty { null } != InferenceGlobalContext.model
modified =
modified || mySettingsComponent!!.inferenceModel?.trim()?.ifEmpty { null } != InferenceGlobalContext.model

return modified
}
Expand All @@ -87,6 +90,7 @@ class AppSettingsConfigurable : Configurable {
InferenceGlobalContext.xDebugLSPPort = mySettingsComponent!!.xDebugLSPPort
AppSettingsState.instance.defaultSystemPrompt = mySettingsComponent!!.defaultSystemPrompt
InferenceGlobalContext.astIsEnabled = mySettingsComponent!!.astIsEnabled
InferenceGlobalContext.astFileLimit = mySettingsComponent!!.astFileLimit
InferenceGlobalContext.vecdbIsEnabled = mySettingsComponent!!.vecdbIsEnabled
InferenceGlobalContext.model = mySettingsComponent!!.inferenceModel?.trim()?.ifEmpty { null }
}
Expand All @@ -99,6 +103,7 @@ class AppSettingsConfigurable : Configurable {
mySettingsComponent!!.xDebugLSPPort = InferenceGlobalContext.xDebugLSPPort
mySettingsComponent!!.defaultSystemPrompt = AppSettingsState.instance.defaultSystemPrompt
mySettingsComponent!!.astIsEnabled = InferenceGlobalContext.astIsEnabled
mySettingsComponent!!.astFileLimit = InferenceGlobalContext.astFileLimit
mySettingsComponent!!.vecdbIsEnabled = InferenceGlobalContext.vecdbIsEnabled
mySettingsComponent!!.inferenceModel = InferenceGlobalContext.model
}
Expand Down
Loading
Loading