@@ -4,6 +4,8 @@ import com.agentclientprotocol.annotations.UnstableApi
44import com.agentclientprotocol.model.ElicitationId
55import com.agentclientprotocol.model.SessionId
66import kotlinx.atomicfu.atomic
7+ import kotlinx.atomicfu.update
8+ import kotlinx.collections.immutable.persistentMapOf
79
810/* *
911 * A mutable, bounded map from [ElicitationId] to [SessionId] with bulk eviction.
@@ -19,34 +21,38 @@ internal class ElicitationSessionStore(
1921 private data class Entry (val sessionId : SessionId , val ordinal : Long )
2022
2123 private val counter = atomic(0L )
22- private val entries: MutableMap <ElicitationId , Entry > = mutableMapOf ( )
24+ private val entries = atomic(persistentMapOf <ElicitationId , Entry >() )
2325
24- operator fun get (elicitationId : ElicitationId ): SessionId ? = entries[elicitationId]?.sessionId
26+ operator fun get (elicitationId : ElicitationId ): SessionId ? = entries.value [elicitationId]?.sessionId
2527
2628 fun put (elicitationId : ElicitationId , sessionId : SessionId ) {
27- entries[elicitationId] = Entry (sessionId, counter.getAndIncrement())
28- if (entries.size > maxCapacity) {
29+ entries.update { it.put(elicitationId, Entry (sessionId, counter.getAndIncrement())) }
30+ if (entries.value. size > maxCapacity) {
2931 evictOldestHalf()
3032 }
3133 }
3234
3335 fun remove (elicitationId : ElicitationId ): SessionId ? {
34- return entries.remove(elicitationId)?.sessionId
36+ val sessionId = entries.value[elicitationId]?.sessionId
37+ entries.update { it.remove(elicitationId) }
38+ return sessionId
3539 }
3640
3741 fun removeBySession (sessionId : SessionId ) {
38- entries.entries.removeAll { it.value.sessionId == sessionId }
42+ val toRemove = entries.value.filter { it.value.sessionId == sessionId }.map { it.key }
43+ entries.update {
44+ toRemove.fold(it) { acc, elicitationId -> acc.remove(elicitationId) }
45+ }
3946 }
4047
4148 private fun evictOldestHalf () {
42- val toRemove = entries.entries
49+ val value = entries.value
50+ val toRemove = value.entries
4351 .sortedBy { it.value.ordinal }
44- .take(entries .size / 2 )
52+ .take(value .size / 2 )
4553 .map { it.key }
46- if (entries.size > maxCapacity) {
47- for (key in toRemove) {
48- entries.remove(key)
49- }
54+ entries.update {
55+ toRemove.fold(it) { acc, elicitationId -> acc.remove(elicitationId) }
5056 }
5157 }
5258
0 commit comments