fix(jetbrains): register subagent editor kind before VFS open

Call ensureSubagentSessionEditorKind() before opening the sub-agent VFS file so the first click reliably creates the virtual file, matching the diff and attachment open sites. Also cap SubagentTitleCache with an access-order LRU so high-churn child session ids do not accumulate for the IDE lifetime.
This commit is contained in:
kirillk
2026-08-20 12:19:50 -04:00
parent cbd4b1cbf3
commit f6ccea49ba
3 changed files with 17 additions and 1 deletions
@@ -19,6 +19,7 @@ import ai.kilocode.client.session.model.SessionState
import ai.kilocode.client.session.scroll.SessionScroll
import ai.kilocode.client.session.subagent.SubagentSessionEditorKind
import ai.kilocode.client.session.subagent.SubagentTitleCache
import ai.kilocode.client.session.subagent.ensureSubagentSessionEditorKind
import ai.kilocode.client.session.subagent.subagentSessionParams
import ai.kilocode.client.session.ui.ConnectionPanel
import ai.kilocode.client.session.ui.empty.EmptySessionPanel
@@ -891,6 +892,7 @@ class SessionUi(
@RequiresEdt
private fun openSubagent(sessionId: String, title: String) {
service<SubagentTitleCache>().put(sessionId, title)
ensureSubagentSessionEditorKind()
project.service<KiloVfsManager>().open(
SubagentSessionEditorKind.ID,
subagentSessionParams(sessionId, workspace.directory),
@@ -3,9 +3,14 @@ package ai.kilocode.client.session.subagent
import com.intellij.openapi.components.Service
import com.intellij.util.concurrency.annotations.RequiresEdt
private const val CAP = 128
@Service(Service.Level.APP)
class SubagentTitleCache {
private val names = linkedMapOf<String, String>()
// Access-order LRU so high-churn sub-agent session ids evict oldest-used first.
private val names = object : LinkedHashMap<String, String>(16, 0.75f, true) {
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<String, String>) = size > CAP
}
@RequiresEdt
fun put(sessionId: String, title: String) {
@@ -64,6 +64,15 @@ class SubagentSessionEditorKindTest : BasePlatformTestCase() {
assertEquals(KiloBundle.message("session.subagent.title"), SubagentSessionEditorKind.title(subagentSessionParams("ses_child", "/repo")))
}
fun testSubagentTitleCacheEvictsLeastRecentlyUsed() {
val cache = service<SubagentTitleCache>()
repeat(200) { cache.put("ses_$it", "Title $it") }
// Oldest untouched entries are evicted; recent ones survive.
assertNull(cache.title("ses_0"))
assertEquals("Title 199", cache.title("ses_199"))
}
fun testSubagentSessionKindRequiresSessionAndDirectory() {
assertFalse(SubagentSessionEditorKind.isValid(subagentSessionParams("", "/repo")))
assertFalse(SubagentSessionEditorKind.isValid(subagentSessionParams("ses_child", "")))