From 3462fa0122d17ac3521487742a76df1f2fbe84a6 Mon Sep 17 00:00:00 2001 From: kirillk Date: Tue, 2 Jun 2026 23:59:53 -0400 Subject: [PATCH] fix(kilo-jetbrains): address config review feedback --- .../backend/cli/KiloBackendCliManager.kt | 149 ++++++++++-------- .../backend/rpc/KiloWorkspaceRpcApiImpl.kt | 4 +- .../client/actions/OpenConfigActions.kt | 9 +- .../client/app/KiloWorkspaceService.kt | 5 +- 4 files changed, 86 insertions(+), 81 deletions(-) diff --git a/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/cli/KiloBackendCliManager.kt b/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/cli/KiloBackendCliManager.kt index 564d342590e..4dcef11b973 100644 --- a/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/cli/KiloBackendCliManager.kt +++ b/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/cli/KiloBackendCliManager.kt @@ -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 = System.getenv()): Map = 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? { - 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 = System.getenv()): Map = + 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 = 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 = System.getenv(), + log: KiloLog = KiloLog.create(KiloBackendCliManager::class.java), +): Map = 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 = 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? { + 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, + ) +} diff --git a/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/rpc/KiloWorkspaceRpcApiImpl.kt b/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/rpc/KiloWorkspaceRpcApiImpl.kt index 02ef792bfb0..8c82b37bb8b 100644 --- a/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/rpc/KiloWorkspaceRpcApiImpl.kt +++ b/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/rpc/KiloWorkspaceRpcApiImpl.kt @@ -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) } diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/actions/OpenConfigActions.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/actions/OpenConfigActions.kt index be9162cb942..3a9d9cbe718 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/actions/OpenConfigActions.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/actions/OpenConfigActions.kt @@ -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().localConfigTarget(it) } - }) + e.presentation.text = text(dir?.let { service().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().globalConfigTarget() }, - ) + e.presentation.text = text(service().globalConfig) } override fun actionPerformed(e: AnActionEvent) { diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/app/KiloWorkspaceService.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/app/KiloWorkspaceService.kt index 119b0deec32..969466abc8f 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/app/KiloWorkspaceService.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/app/KiloWorkspaceService.kt @@ -42,10 +42,11 @@ class KiloWorkspaceService internal constructor( } private val workspaces = ConcurrentHashMap() - private val localConfig = ConcurrentHashMap() + internal val localConfig = ConcurrentHashMap() @Volatile - private var globalConfig: ConfigTargetDto? = null + internal var globalConfig: ConfigTargetDto? = null + private set // ------ RPC helpers ------