fix(kilo-jetbrains): address config review feedback

This commit is contained in:
kirillk
2026-06-02 23:59:53 -04:00
parent 7d1f6ae5ff
commit 3462fa0122
4 changed files with 86 additions and 81 deletions
@@ -35,7 +35,6 @@ class KiloBackendCliManager(
companion object {
private const val STARTUP_TIMEOUT_MS = 30_000L
private const val KILL_TIMEOUT_SECONDS = 5L
private const val DEFAULT_CONFIG = """{"permission":{"edit":"ask","bash":"ask"}}"""
private val PORT_REGEX = Regex("""listening on http://[\w.]+:(\d+)""")
}
@@ -123,47 +122,8 @@ class KiloBackendCliManager(
}
// Must be called from a background thread — devStorageEnv() performs blocking I/O (mkdirs).
internal fun buildEnv(pwd: String, base: Map<String, String> = System.getenv()): Map<String, String> = buildMap {
putAll(base)
put("KILO_SERVER_PASSWORD", pwd)
put("KILO_CLIENT", "jetbrains")
put("KILO_ENABLE_QUESTION_TOOL", "true")
put("KILO_PLATFORM", "jetbrains")
put("KILO_APP_NAME", "kilo-code")
put("KILO_TELEMETRY_LEVEL", if (KiloDevMode.enabled()) "off" else "all")
put("KILO_DISABLE_CLAUDE_CODE", "true")
put("KILOCODE_FEATURE", "jetbrains-plugin")
putIfAbsent("KILO_CONFIG_CONTENT", DEFAULT_CONFIG)
ideEnv().forEach { (k, v) -> put(k, v) }
devStorageEnv()?.forEach { (k, v) -> put(k, v) }
}
private fun devStorageEnv(): Map<String, String>? {
val enabled = System.getProperty("kilo.dev.storage.isolated", "false").toBoolean()
if (!enabled) return null
val root = System.getProperty("kilo.dev.worktree.root") ?: run {
log.warn("kilo.dev.storage.isolated=true but kilo.dev.worktree.root is not set; skipping dev storage isolation")
return null
}
val dev = File(root, ".kilo-dev")
val data = File(dev, "data")
val config = File(dev, "config")
val state = File(dev, "state")
val cache = File(dev, "cache")
for (dir in listOf(data, config, state, cache)) {
if (!dir.mkdirs() && !dir.isDirectory) {
log.warn("Failed to create dev storage dir ${dir.absolutePath}; skipping dev storage isolation")
return null
}
}
log.info("Dev storage isolation enabled under ${dev.absolutePath}")
return mapOf(
"XDG_DATA_HOME" to data.absolutePath,
"XDG_CONFIG_HOME" to config.absolutePath,
"XDG_STATE_HOME" to state.absolutePath,
"XDG_CACHE_HOME" to cache.absolutePath,
)
}
internal fun buildEnv(pwd: String, base: Map<String, String> = System.getenv()): Map<String, String> =
buildKiloCliEnv(pwd, base, log)
private suspend fun spawn(cli: File): CliServer.State =
withContext(Dispatchers.IO) {
@@ -285,37 +245,86 @@ class KiloBackendCliManager(
return "$os-$arch"
}
private fun ideEnv(): Map<String, String> = buildMap {
runCatching {
val info = ApplicationInfo.getInstance()
val name = info.fullApplicationName
val build = info.build.asString()
put("KILO_EDITOR_NAME", name)
put("KILOCODE_EDITOR_NAME", "$name $build")
}.onFailure { log.info("Could not read ApplicationInfo: ${it.message}") }
runCatching {
val version = KiloPlugin.version()
if (version != null) put("KILO_APP_VERSION", version)
}.onFailure { log.info("Could not read plugin version: ${it.message}") }
runCatching {
put("KILO_MACHINE_ID", machineId())
}.onFailure { log.info("Could not read machine ID: ${it.message}") }
}
private fun machineId(): String {
val file = File(PathManager.getSystemPath(), "kilo/machine-id")
if (file.exists()) return file.readText().trim()
val id = UUID.randomUUID().toString()
file.parentFile.mkdirs()
file.writeText(id)
return id
}
private fun generatePassword(): String {
val bytes = ByteArray(32)
SecureRandom().nextBytes(bytes)
return bytes.joinToString("") { "%02x".format(it) }
}
}
private const val DEFAULT_CONFIG = """{"permission":{"edit":"ask","bash":"ask"}}"""
// Must be called from a background thread — devStorageEnv() performs blocking I/O (mkdirs).
internal fun buildKiloCliEnv(
pwd: String,
base: Map<String, String> = System.getenv(),
log: KiloLog = KiloLog.create(KiloBackendCliManager::class.java),
): Map<String, String> = buildMap {
putAll(base)
put("KILO_SERVER_PASSWORD", pwd)
put("KILO_CLIENT", "jetbrains")
put("KILO_ENABLE_QUESTION_TOOL", "true")
put("KILO_PLATFORM", "jetbrains")
put("KILO_APP_NAME", "kilo-code")
put("KILO_TELEMETRY_LEVEL", if (KiloDevMode.enabled()) "off" else "all")
put("KILO_DISABLE_CLAUDE_CODE", "true")
put("KILOCODE_FEATURE", "jetbrains-plugin")
putIfAbsent("KILO_CONFIG_CONTENT", DEFAULT_CONFIG)
ideEnv(log).forEach { entry -> put(entry.key, entry.value) }
devStorageEnv(log)?.forEach { entry -> put(entry.key, entry.value) }
}
private fun ideEnv(log: KiloLog): Map<String, String> = buildMap {
runCatching {
val info = ApplicationInfo.getInstance()
val name = info.fullApplicationName
val build = info.build.asString()
put("KILO_EDITOR_NAME", name)
put("KILOCODE_EDITOR_NAME", "$name $build")
}.onFailure { log.info("Could not read ApplicationInfo: ${it.message}") }
runCatching {
val version = KiloPlugin.version()
if (version != null) put("KILO_APP_VERSION", version)
}.onFailure { log.info("Could not read plugin version: ${it.message}") }
runCatching {
put("KILO_MACHINE_ID", machineId())
}.onFailure { log.info("Could not read machine ID: ${it.message}") }
}
private fun machineId(): String {
val file = File(PathManager.getSystemPath(), "kilo/machine-id")
if (file.exists()) return file.readText().trim()
val id = UUID.randomUUID().toString()
file.parentFile.mkdirs()
file.writeText(id)
return id
}
private fun devStorageEnv(log: KiloLog): Map<String, String>? {
val enabled = System.getProperty("kilo.dev.storage.isolated", "false").toBoolean()
if (!enabled) return null
val root = System.getProperty("kilo.dev.worktree.root") ?: run {
log.warn("kilo.dev.storage.isolated=true but kilo.dev.worktree.root is not set; skipping dev storage isolation")
return null
}
val dev = File(root, ".kilo-dev")
val data = File(dev, "data")
val config = File(dev, "config")
val state = File(dev, "state")
val cache = File(dev, "cache")
for (dir in listOf(data, config, state, cache)) {
if (!dir.mkdirs() && !dir.isDirectory) {
log.warn("Failed to create dev storage dir ${dir.absolutePath}; skipping dev storage isolation")
return null
}
}
log.info("Dev storage isolation enabled under ${dev.absolutePath}")
return mapOf(
"XDG_DATA_HOME" to data.absolutePath,
"XDG_CONFIG_HOME" to config.absolutePath,
"XDG_STATE_HOME" to state.absolutePath,
"XDG_CACHE_HOME" to cache.absolutePath,
)
}
@@ -6,7 +6,7 @@ import ai.kilocode.backend.app.KiloAppState
import ai.kilocode.backend.app.KiloBackendAppService
import ai.kilocode.backend.app.LoadError
import ai.kilocode.backend.cli.KiloCliDataParser
import ai.kilocode.backend.cli.KiloBackendCliManager
import ai.kilocode.backend.cli.buildKiloCliEnv
import ai.kilocode.backend.cli.KiloCliConfigPath
import ai.kilocode.backend.workspace.AgentData
import ai.kilocode.backend.workspace.AgentInfo
@@ -226,7 +226,7 @@ class KiloWorkspaceRpcApiImpl : KiloWorkspaceRpcApi {
}
private fun globalConfig(): Path {
val env = KiloBackendCliManager().buildEnv("config")
val env = buildKiloCliEnv("config")
val root = KiloCliConfigPath.resolve(env).toPath().normalize()
return GLOBAL.asSequence()
.map { root.resolve(it) }
@@ -11,7 +11,6 @@ import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.components.service
import com.intellij.openapi.project.DumbAware
import kotlinx.coroutines.runBlocking
abstract class ConfigAction(
private val open: String,
@@ -40,9 +39,7 @@ class OpenLocalConfigAction : ConfigAction(
override fun update(e: AnActionEvent) {
val dir = directory(e)
e.presentation.isEnabled = dir != null
e.presentation.text = text(dir?.let {
runBlocking { service<KiloWorkspaceService>().localConfigTarget(it) }
})
e.presentation.text = text(dir?.let { service<KiloWorkspaceService>().localConfig[it] })
}
override fun actionPerformed(e: AnActionEvent) {
@@ -65,9 +62,7 @@ class OpenGlobalConfigAction : ConfigAction(
description = KiloBundle.message("action.Kilo.OpenGlobalConfig.description"),
) {
override fun update(e: AnActionEvent) {
e.presentation.text = text(
runBlocking { service<KiloWorkspaceService>().globalConfigTarget() },
)
e.presentation.text = text(service<KiloWorkspaceService>().globalConfig)
}
override fun actionPerformed(e: AnActionEvent) {
@@ -42,10 +42,11 @@ class KiloWorkspaceService internal constructor(
}
private val workspaces = ConcurrentHashMap<String, Workspace>()
private val localConfig = ConcurrentHashMap<String, ConfigTargetDto>()
internal val localConfig = ConcurrentHashMap<String, ConfigTargetDto>()
@Volatile
private var globalConfig: ConfigTargetDto? = null
internal var globalConfig: ConfigTargetDto? = null
private set
// ------ RPC helpers ------