moving things

This commit is contained in:
kirillk
2026-04-13 10:07:46 -04:00
parent 23745d2553
commit 7115a4b5ee
13 changed files with 79 additions and 35 deletions
+12
View File
@@ -4,12 +4,24 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<compositeConfiguration>
<compositeBuild compositeDefinitionSource="SCRIPT">
<builds>
<build path="$PROJECT_DIR$/packages/kilo-jetbrains/build-tasks" name="build-tasks">
<projects>
<project path="$PROJECT_DIR$/packages/kilo-jetbrains/build-tasks" />
</projects>
</build>
</builds>
</compositeBuild>
</compositeConfiguration>
<option name="externalProjectPath" value="$PROJECT_DIR$/packages/kilo-jetbrains" />
<option name="gradleJvm" value="#JAVA_HOME" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$/packages/kilo-jetbrains" />
<option value="$PROJECT_DIR$/packages/kilo-jetbrains/backend" />
<option value="$PROJECT_DIR$/packages/kilo-jetbrains/build-tasks" />
<option value="$PROJECT_DIR$/packages/kilo-jetbrains/frontend" />
<option value="$PROJECT_DIR$/packages/kilo-jetbrains/shared" />
</set>
@@ -1,4 +1,4 @@
package ai.kilocode.backend
package ai.kilocode.backend.app
/**
* Abstraction over the CLI process lifecycle.
@@ -1,4 +1,4 @@
package ai.kilocode.backend
package ai.kilocode.backend.app
import ai.kilocode.jetbrains.api.model.Config
import ai.kilocode.jetbrains.api.model.KiloNotifications200ResponseInner
@@ -1,7 +1,11 @@
package ai.kilocode.backend
package ai.kilocode.backend.app
import ai.kilocode.backend.util.IntellijLog
import ai.kilocode.backend.util.KiloLog
import ai.kilocode.jetbrains.api.client.DefaultApi
import ai.kilocode.jetbrains.api.infrastructure.ClientError
import ai.kilocode.jetbrains.api.infrastructure.ClientException
import ai.kilocode.jetbrains.api.infrastructure.ServerError
import ai.kilocode.jetbrains.api.infrastructure.ServerException
import ai.kilocode.jetbrains.api.model.Config
import ai.kilocode.jetbrains.api.model.KiloNotifications200ResponseInner
@@ -21,6 +25,8 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.util.concurrent.atomic.AtomicReference
/**
@@ -41,16 +47,16 @@ import java.util.concurrent.atomic.AtomicReference
*/
@Service(Service.Level.APP)
class KiloBackendAppService private constructor(
private val cs: CoroutineScope,
private val server: CliServer,
private val log: KiloLog,
private val cs: CoroutineScope,
private val server: CliServer,
private val log: KiloLog,
) : Disposable {
/** IntelliJ service injection entry point. */
constructor(cs: CoroutineScope) : this(
cs,
KiloBackendCliManager(),
IntellijLog(KiloBackendAppService::class.java),
IntellijLog(KiloBackendAppService::class.java),
)
companion object {
@@ -59,9 +65,9 @@ class KiloBackendAppService private constructor(
/** Test factory — no IntelliJ deps needed. */
internal fun create(
cs: CoroutineScope,
server: CliServer,
log: KiloLog,
cs: CoroutineScope,
server: CliServer,
log: KiloLog,
) = KiloBackendAppService(cs, server, log)
}
@@ -280,8 +286,8 @@ class KiloBackendAppService private constructor(
*/
private fun logResponseBody(resource: String, e: Exception) {
val body = when (e) {
is ClientException -> (e.response as? ai.kilocode.jetbrains.api.infrastructure.ClientError<*>)?.body
is ServerException -> (e.response as? ai.kilocode.jetbrains.api.infrastructure.ServerError<*>)?.body
is ClientException -> (e.response as? ClientError<*>)?.body
is ServerException -> (e.response as? ServerError<*>)?.body
else -> null
}
if (body != null) {
@@ -376,8 +382,8 @@ private data class FetchResult<T>(val value: T?, val error: LoadError?) {
when (e) {
is ClientException -> "HTTP ${e.statusCode}: ${e.message}"
is ServerException -> "HTTP ${e.statusCode}: ${e.message}"
is java.net.ConnectException -> "Connection refused: ${e.message}"
is java.net.SocketTimeoutException -> "Timeout: ${e.message}"
is ConnectException -> "Connection refused: ${e.message}"
is SocketTimeoutException -> "Timeout: ${e.message}"
else -> e.message
}
}
@@ -1,5 +1,7 @@
package ai.kilocode.backend
package ai.kilocode.backend.app
import ai.kilocode.backend.util.IntellijLog
import ai.kilocode.backend.util.KiloLog
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.util.SystemInfo
import com.intellij.util.system.CpuArch
@@ -16,7 +18,7 @@ import java.util.concurrent.TimeUnit
* Manages the Kilo CLI binary lifecycle.
*
* Extracts the bundled CLI from JAR resources into IntelliJ's system directory,
* spawns `kilo serve --port 0`, and exposes the result as [CliServer.State].
* spawns `kilo serve --port 0`, and exposes the result as [State].
*
* Concurrency is handled by the owning [KiloBackendAppService] all public
* methods are called under its mutex so no internal synchronization is needed.
@@ -1,5 +1,8 @@
package ai.kilocode.backend
package ai.kilocode.backend.app
import ai.kilocode.backend.util.IntellijLog
import ai.kilocode.backend.KiloBackendHttpClients
import ai.kilocode.backend.util.KiloLog
import ai.kilocode.jetbrains.api.client.DefaultApi
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -50,10 +53,10 @@ data class SseEvent(val type: String, val data: String)
* Not a service owned and instantiated by [KiloBackendAppService].
*/
class KiloConnectionService(
private val cs: CoroutineScope,
private val server: CliServer,
private val onReconnect: () -> Unit,
private val log: KiloLog = IntellijLog(KiloConnectionService::class.java),
private val cs: CoroutineScope,
private val server: CliServer,
private val onReconnect: () -> Unit,
private val log: KiloLog = IntellijLog(KiloConnectionService::class.java),
) {
companion object {
@@ -2,11 +2,11 @@
package ai.kilocode.backend.rpc
import ai.kilocode.backend.KiloAppState
import ai.kilocode.backend.KiloBackendAppService
import ai.kilocode.backend.LoadError
import ai.kilocode.backend.LoadProgress
import ai.kilocode.backend.ProfileResult
import ai.kilocode.backend.app.KiloAppState
import ai.kilocode.backend.app.KiloBackendAppService
import ai.kilocode.backend.app.LoadError
import ai.kilocode.backend.app.LoadProgress
import ai.kilocode.backend.app.ProfileResult
import ai.kilocode.rpc.KiloAppRpcApi
import ai.kilocode.rpc.dto.HealthDto
import ai.kilocode.rpc.dto.KiloAppStateDto
@@ -1,4 +1,4 @@
package ai.kilocode.backend
package ai.kilocode.backend.util
import com.intellij.openapi.diagnostic.Logger
@@ -1,5 +1,10 @@
package ai.kilocode.backend
import ai.kilocode.backend.app.AppData
import ai.kilocode.backend.app.KiloAppState
import ai.kilocode.backend.app.LoadError
import ai.kilocode.backend.app.LoadProgress
import ai.kilocode.backend.app.ProfileResult
import ai.kilocode.jetbrains.api.model.Config
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -42,8 +47,8 @@ class KiloAppStateTest {
@Test
fun `KiloAppState Error with errors list`() {
val errors = listOf(
LoadError("config", status = 500, detail = "server error"),
LoadError("notifications", detail = "timeout"),
LoadError("config", status = 500, detail = "server error"),
LoadError("notifications", detail = "timeout"),
)
val state = KiloAppState.Error("Failed", errors = errors)
assertEquals(2, state.errors.size)
@@ -55,7 +60,8 @@ class KiloAppStateTest {
@Test
fun `AppData construction`() {
val cfg = Config(model = "test")
val data = AppData(profile = null, config = cfg, notifications = emptyList())
val data =
AppData(profile = null, config = cfg, notifications = emptyList())
assertNull(data.profile)
assertEquals(cfg, data.config)
assertTrue(data.notifications.isEmpty())
@@ -63,7 +69,11 @@ class KiloAppStateTest {
@Test
fun `LoadError with all fields`() {
val err = LoadError(resource = "config", status = 503, detail = "Service Unavailable")
val err = LoadError(
resource = "config",
status = 503,
detail = "Service Unavailable"
)
assertEquals("config", err.resource)
assertEquals(503, err.status)
assertEquals("Service Unavailable", err.detail)
@@ -79,7 +89,8 @@ class KiloAppStateTest {
@Test
fun `ProfileResult enum values`() {
assertEquals(3, ProfileResult.entries.size)
assertTrue(ProfileResult.entries.containsAll(
assertTrue(
ProfileResult.entries.containsAll(
listOf(ProfileResult.PENDING, ProfileResult.LOADED, ProfileResult.NOT_LOGGED_IN)
))
}
@@ -1,5 +1,7 @@
package ai.kilocode.backend
import ai.kilocode.backend.app.KiloAppState
import ai.kilocode.backend.app.KiloBackendAppService
import ai.kilocode.backend.testing.FakeCliServer
import ai.kilocode.backend.testing.MockCliServer
import ai.kilocode.backend.testing.TestLog
@@ -1,5 +1,8 @@
package ai.kilocode.backend
import ai.kilocode.backend.app.CliServer
import ai.kilocode.backend.app.ConnectionState
import ai.kilocode.backend.app.KiloConnectionService
import ai.kilocode.backend.testing.FakeCliServer
import ai.kilocode.backend.testing.MockCliServer
import ai.kilocode.backend.testing.TestLog
@@ -35,7 +38,12 @@ class KiloConnectionServiceTest {
@Test
fun `connect transitions to Connected`() = runBlocking {
val reconnects = AtomicInteger(0)
val svc = KiloConnectionService(scope, fake, { reconnects.incrementAndGet() }, log)
val svc = KiloConnectionService(
scope,
fake,
{ reconnects.incrementAndGet() },
log
)
svc.connect()
@@ -1,6 +1,6 @@
package ai.kilocode.backend.testing
import ai.kilocode.backend.CliServer
import ai.kilocode.backend.app.CliServer
/**
* Fake [CliServer] that delegates to a [MockCliServer] instead of
@@ -1,6 +1,6 @@
package ai.kilocode.backend.testing
import ai.kilocode.backend.KiloLog
import ai.kilocode.backend.util.KiloLog
/**
* Test logger that captures messages for assertions and prints to stdout.