diff --git a/acp-model/api/acp-model.api b/acp-model/api/acp-model.api index 1aa53cc..c6ab173 100644 --- a/acp-model/api/acp-model.api +++ b/acp-model/api/acp-model.api @@ -5562,6 +5562,7 @@ public final class com/agentclientprotocol/model/SessionConfigId$Companion { public abstract class com/agentclientprotocol/model/SessionConfigOption : com/agentclientprotocol/model/AcpWithMeta { public static final field Companion Lcom/agentclientprotocol/model/SessionConfigOption$Companion; public synthetic fun (ILkotlinx/serialization/internal/SerializationConstructorMarker;)V + public abstract fun getCategory-hVFCkWA ()Ljava/lang/String; public abstract fun getDescription ()Ljava/lang/String; public abstract fun getId-2Q23AbI ()Ljava/lang/String; public abstract fun getName ()Ljava/lang/String; @@ -5570,16 +5571,18 @@ public abstract class com/agentclientprotocol/model/SessionConfigOption : com/ag public final class com/agentclientprotocol/model/SessionConfigOption$BooleanOption : com/agentclientprotocol/model/SessionConfigOption { public static final field Companion Lcom/agentclientprotocol/model/SessionConfigOption$BooleanOption$Companion; - public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlinx/serialization/json/JsonElement;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlinx/serialization/json/JsonElement;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1-2Q23AbI ()Ljava/lang/String; public final fun component2 ()Ljava/lang/String; public final fun component3 ()Ljava/lang/String; - public final fun component4 ()Z - public final fun component5 ()Lkotlinx/serialization/json/JsonElement; - public final fun copy-AHie1Zw (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionConfigOption$BooleanOption; - public static synthetic fun copy-AHie1Zw$default (Lcom/agentclientprotocol/model/SessionConfigOption$BooleanOption;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigOption$BooleanOption; + public final fun component4-hVFCkWA ()Ljava/lang/String; + public final fun component5 ()Z + public final fun component6 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy-pwdxzbE (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionConfigOption$BooleanOption; + public static synthetic fun copy-pwdxzbE$default (Lcom/agentclientprotocol/model/SessionConfigOption$BooleanOption;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigOption$BooleanOption; public fun equals (Ljava/lang/Object;)Z + public fun getCategory-hVFCkWA ()Ljava/lang/String; public final fun getCurrentValue ()Z public fun getDescription ()Ljava/lang/String; public fun getId-2Q23AbI ()Ljava/lang/String; @@ -5605,26 +5608,28 @@ public final class com/agentclientprotocol/model/SessionConfigOption$BooleanOpti } public final class com/agentclientprotocol/model/SessionConfigOption$Companion { - public final fun boolean (Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;)Lcom/agentclientprotocol/model/SessionConfigOption$BooleanOption; - public static synthetic fun boolean$default (Lcom/agentclientprotocol/model/SessionConfigOption$Companion;Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigOption$BooleanOption; - public final fun select (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Ljava/lang/String;)Lcom/agentclientprotocol/model/SessionConfigOption$Select; - public static synthetic fun select$default (Lcom/agentclientprotocol/model/SessionConfigOption$Companion;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Ljava/lang/String;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigOption$Select; + public final fun boolean-Zk-hV-o (Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;)Lcom/agentclientprotocol/model/SessionConfigOption$BooleanOption; + public static synthetic fun boolean-Zk-hV-o$default (Lcom/agentclientprotocol/model/SessionConfigOption$Companion;Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigOption$BooleanOption; + public final fun select-tW3b3dA (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Ljava/lang/String;Ljava/lang/String;)Lcom/agentclientprotocol/model/SessionConfigOption$Select; + public static synthetic fun select-tW3b3dA$default (Lcom/agentclientprotocol/model/SessionConfigOption$Companion;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigOption$Select; public final fun serializer ()Lkotlinx/serialization/KSerializer; } public final class com/agentclientprotocol/model/SessionConfigOption$Select : com/agentclientprotocol/model/SessionConfigOption { public static final field Companion Lcom/agentclientprotocol/model/SessionConfigOption$Select$Companion; - public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Lkotlinx/serialization/json/JsonElement;Lkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Lkotlinx/serialization/json/JsonElement;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Lkotlinx/serialization/json/JsonElement;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1-2Q23AbI ()Ljava/lang/String; public final fun component2 ()Ljava/lang/String; public final fun component3 ()Ljava/lang/String; - public final fun component4-cDIbsdA ()Ljava/lang/String; - public final fun component5 ()Lcom/agentclientprotocol/model/SessionConfigSelectOptions; - public final fun component6 ()Lkotlinx/serialization/json/JsonElement; - public final fun copy-ajXSYlw (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionConfigOption$Select; - public static synthetic fun copy-ajXSYlw$default (Lcom/agentclientprotocol/model/SessionConfigOption$Select;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigOption$Select; + public final fun component4-hVFCkWA ()Ljava/lang/String; + public final fun component5-cDIbsdA ()Ljava/lang/String; + public final fun component6 ()Lcom/agentclientprotocol/model/SessionConfigSelectOptions; + public final fun component7 ()Lkotlinx/serialization/json/JsonElement; + public final fun copy-xDZ6wdk (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Lkotlinx/serialization/json/JsonElement;)Lcom/agentclientprotocol/model/SessionConfigOption$Select; + public static synthetic fun copy-xDZ6wdk$default (Lcom/agentclientprotocol/model/SessionConfigOption$Select;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/agentclientprotocol/model/SessionConfigSelectOptions;Lkotlinx/serialization/json/JsonElement;ILjava/lang/Object;)Lcom/agentclientprotocol/model/SessionConfigOption$Select; public fun equals (Ljava/lang/Object;)Z + public fun getCategory-hVFCkWA ()Ljava/lang/String; public final fun getCurrentValue-cDIbsdA ()Ljava/lang/String; public fun getDescription ()Ljava/lang/String; public fun getId-2Q23AbI ()Ljava/lang/String; @@ -5650,6 +5655,39 @@ public final class com/agentclientprotocol/model/SessionConfigOption$Select$Comp public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class com/agentclientprotocol/model/SessionConfigOptionCategory { + public static final field Companion Lcom/agentclientprotocol/model/SessionConfigOptionCategory$Companion; + public static final synthetic fun box-impl (Ljava/lang/String;)Lcom/agentclientprotocol/model/SessionConfigOptionCategory; + public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; + public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z + public final fun getValue ()Ljava/lang/String; + public fun hashCode ()I + public static fun hashCode-impl (Ljava/lang/String;)I + public fun toString ()Ljava/lang/String; + public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Ljava/lang/String; +} + +public final synthetic class com/agentclientprotocol/model/SessionConfigOptionCategory$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lcom/agentclientprotocol/model/SessionConfigOptionCategory$$serializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public final fun deserialize-NTdcRRE (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/String; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public final fun serialize-5T3uW0w (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/String;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class com/agentclientprotocol/model/SessionConfigOptionCategory$Companion { + public final fun getMODE-3ipu9Lg ()Ljava/lang/String; + public final fun getMODEL-3ipu9Lg ()Ljava/lang/String; + public final fun getTHOUGHT_LEVEL-3ipu9Lg ()Ljava/lang/String; + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public abstract class com/agentclientprotocol/model/SessionConfigOptionValue { public static final field Companion Lcom/agentclientprotocol/model/SessionConfigOptionValue$Companion; } diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpCreatedSessionResponse.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpCreatedSessionResponse.kt index a706c12..0aabe9d 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpCreatedSessionResponse.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/AcpCreatedSessionResponse.kt @@ -6,6 +6,5 @@ public interface AcpCreatedSessionResponse : AcpWithMeta { public val modes: SessionModeState? @UnstableApi public val models: SessionModelState? - @UnstableApi public val configOptions: List? } \ No newline at end of file diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Requests.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Requests.kt index 69ceb16..bd2a012 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Requests.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Requests.kt @@ -682,7 +682,6 @@ public data class NewSessionResponse( override val modes: SessionModeState? = null, @property:UnstableApi override val models: SessionModelState? = null, - @property:UnstableApi override val configOptions: List? = null, override val _meta: JsonElement? = null ) : AcpCreatedSessionResponse, AcpResponse, AcpWithSessionId @@ -710,7 +709,6 @@ public data class LoadSessionResponse( override val modes: SessionModeState? = null, @property:UnstableApi override val models: SessionModelState? = null, - @property:UnstableApi override val configOptions: List? = null, override val _meta: JsonElement? = null ) : AcpCreatedSessionResponse, AcpResponse @@ -980,7 +978,6 @@ public data class ResumeSessionResponse( override val modes: SessionModeState? = null, @property:UnstableApi override val models: SessionModelState? = null, - @property:UnstableApi override val configOptions: List? = null, override val _meta: JsonElement? = null ) : AcpCreatedSessionResponse, AcpResponse @@ -1002,13 +999,8 @@ public data class SetSessionConfigOptionRequest( ) : AcpRequest, AcpWithSessionId /** - * **UNSTABLE** - * - * This capability is not part of the spec yet, and may be removed or changed at any point. - * * Response from setting a configuration option. */ -@UnstableApi @Serializable public data class SetSessionConfigOptionResponse( val configOptions: List, diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionConfig.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionConfig.kt index 4285b17..aacc929 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionConfig.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionConfig.kt @@ -28,15 +28,29 @@ import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.buildJsonObject import kotlinx.serialization.json.jsonObject import kotlinx.serialization.json.put +import kotlin.jvm.JvmInline /** - * **UNSTABLE** - * - * This capability is not part of the spec yet, and may be removed or changed at any point. + * Category for a session configuration option. * + * Well-known categories are provided as constants. Custom categories are supported + * via the constructor, matching the protocol's open string-based design. + */ +@JvmInline +@Serializable +public value class SessionConfigOptionCategory(public val value: String) { + override fun toString(): String = value + + public companion object { + public val MODE: SessionConfigOptionCategory = SessionConfigOptionCategory("mode") + public val MODEL: SessionConfigOptionCategory = SessionConfigOptionCategory("model") + public val THOUGHT_LEVEL: SessionConfigOptionCategory = SessionConfigOptionCategory("thought_level") + } +} + +/** * A single option for a session configuration select. */ -@UnstableApi @Serializable public data class SessionConfigSelectOption( val value: SessionConfigValueId, @@ -46,13 +60,8 @@ public data class SessionConfigSelectOption( ) : AcpWithMeta /** - * **UNSTABLE** - * - * This capability is not part of the spec yet, and may be removed or changed at any point. - * * A group of options for a session configuration select. */ -@UnstableApi @Serializable public data class SessionConfigSelectGroup( val group: SessionConfigGroupId, @@ -62,13 +71,8 @@ public data class SessionConfigSelectGroup( ) : AcpWithMeta /** - * **UNSTABLE** - * - * This capability is not part of the spec yet, and may be removed or changed at any point. - * * Options for a session configuration select, either as a flat list or grouped. */ -@UnstableApi @Serializable(with = SessionConfigSelectOptionsSerializer::class) public sealed class SessionConfigSelectOptions { /** @@ -89,13 +93,8 @@ public sealed class SessionConfigSelectOptions { } /** - * **UNSTABLE** - * - * This capability is not part of the spec yet, and may be removed or changed at any point. - * * Polymorphic serializer for [SessionConfigSelectOptions]. */ -@OptIn(UnstableApi::class) internal object SessionConfigSelectOptionsSerializer : KSerializer { @@ -139,19 +138,15 @@ internal object SessionConfigSelectOptionsSerializer : } /** - * **UNSTABLE** - * - * This capability is not part of the spec yet, and may be removed or changed at any point. - * * Configuration option types for sessions. */ -@UnstableApi @Serializable @JsonClassDiscriminator("type") public sealed class SessionConfigOption : AcpWithMeta { public abstract val id: SessionConfigId public abstract val name: String public abstract val description: String? + public abstract val category: SessionConfigOptionCategory? /** * A select-type configuration option. @@ -162,20 +157,25 @@ public sealed class SessionConfigOption : AcpWithMeta { override val id: SessionConfigId, override val name: String, override val description: String? = null, + override val category: SessionConfigOptionCategory? = null, val currentValue: SessionConfigValueId, val options: SessionConfigSelectOptions, override val _meta: JsonElement? = null ) : SessionConfigOption() /** - * A boolean-type configuration option. + * **UNSTABLE** + * + * Boolean-type configuration option. Not part of the protocol spec yet. */ + @UnstableApi @Serializable @SerialName("boolean") public data class BooleanOption( override val id: SessionConfigId, override val name: String, override val description: String? = null, + override val category: SessionConfigOptionCategory? = null, val currentValue: Boolean, override val _meta: JsonElement? = null ) : SessionConfigOption() @@ -190,10 +190,12 @@ public sealed class SessionConfigOption : AcpWithMeta { currentValue: String, options: SessionConfigSelectOptions, description: String? = null, + category: SessionConfigOptionCategory? = null, ): Select = Select( id = SessionConfigId(id), name = name, description = description, + category = category, currentValue = SessionConfigValueId(currentValue), options = options, ) @@ -206,10 +208,12 @@ public sealed class SessionConfigOption : AcpWithMeta { name: String, currentValue: Boolean, description: String? = null, + category: SessionConfigOptionCategory? = null, ): BooleanOption = BooleanOption( id = SessionConfigId(id), name = name, description = description, + category = category, currentValue = currentValue, ) } diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionUpdate.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionUpdate.kt index cd8cbbe..c3b28a5 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionUpdate.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/SessionUpdate.kt @@ -187,13 +187,8 @@ public sealed class SessionUpdate { ) : SessionUpdate() /** - * **UNSTABLE** - * - * This capability is not part of the spec yet, and may be removed or changed at any point. - * * Configuration options have been updated. */ - @UnstableApi @Serializable @SerialName("config_option_update") public data class ConfigOptionUpdate( diff --git a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Types.kt b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Types.kt index 13da4cc..77faf4e 100644 --- a/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Types.kt +++ b/acp-model/src/commonMain/kotlin/com/agentclientprotocol/model/Types.kt @@ -89,13 +89,8 @@ public value class ModelId(public val value: String) { } /** - * **UNSTABLE** - * - * This capability is not part of the spec yet, and may be removed or changed at any point. - * * Unique identifier for a session configuration option. */ -@UnstableApi @JvmInline @Serializable public value class SessionConfigId(public val value: String) { @@ -103,13 +98,8 @@ public value class SessionConfigId(public val value: String) { } /** - * **UNSTABLE** - * - * This capability is not part of the spec yet, and may be removed or changed at any point. - * * Unique identifier for a session configuration value. */ -@UnstableApi @JvmInline @Serializable public value class SessionConfigValueId(public val value: String) { @@ -117,13 +107,8 @@ public value class SessionConfigValueId(public val value: String) { } /** - * **UNSTABLE** - * - * This capability is not part of the spec yet, and may be removed or changed at any point. - * * Unique identifier for a session configuration group. */ -@UnstableApi @JvmInline @Serializable public value class SessionConfigGroupId(public val value: String) { diff --git a/acp-model/src/commonTest/kotlin/com/agentclientprotocol/model/SessionConfigSelectOptionsSerializerTest.kt b/acp-model/src/commonTest/kotlin/com/agentclientprotocol/model/SessionConfigSelectOptionsSerializerTest.kt index 4380ee9..30344f9 100644 --- a/acp-model/src/commonTest/kotlin/com/agentclientprotocol/model/SessionConfigSelectOptionsSerializerTest.kt +++ b/acp-model/src/commonTest/kotlin/com/agentclientprotocol/model/SessionConfigSelectOptionsSerializerTest.kt @@ -13,6 +13,7 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertIs import kotlin.test.assertNotNull +import kotlin.test.assertNull class SessionConfigSelectOptionsSerializerTest { @@ -106,6 +107,7 @@ class SessionConfigSelectOptionsSerializerTest { val options = assertIs(select.options) assertEquals(SessionConfigValueId("auto"), select.currentValue) assertEquals(3, options.options.size) + assertEquals(SessionConfigOptionCategory.MODE, select.category) } @Test @@ -217,6 +219,9 @@ class SessionConfigSelectOptionsSerializerTest { val firstOptions = assertIs(first.options) assertEquals(SessionConfigValueId("ask"), first.currentValue) assertEquals(2, firstOptions.options.size) + assertEquals(SessionConfigOptionCategory.MODE, first.category) + val second = assertIs(configOptions[1]) + assertEquals(SessionConfigOptionCategory.MODEL, second.category) } @Test @@ -652,6 +657,177 @@ class SessionConfigSelectOptionsSerializerTest { assertEquals(false, boolValue.value) } + // --- SessionConfigOptionCategory tests --- + + @Test + fun `decode select config option with category mode`() { + val json = """ + { + "id": "mode", + "name": "Session Mode", + "category": "mode", + "type": "select", + "currentValue": "ask", + "options": [{"value": "ask", "name": "Ask"}] + } + """.trimIndent() + val option = ACPJson.decodeFromString(SessionConfigOption.serializer(), json) + val select = assertIs(option) + assertEquals(SessionConfigOptionCategory.MODE, select.category) + } + + @Test + fun `decode select config option with category model`() { + val json = """ + { + "id": "models", + "name": "Model", + "category": "model", + "type": "select", + "currentValue": "m1", + "options": [{"value": "m1", "name": "Model 1"}] + } + """.trimIndent() + val option = ACPJson.decodeFromString(SessionConfigOption.serializer(), json) + val select = assertIs(option) + assertEquals(SessionConfigOptionCategory.MODEL, select.category) + } + + @Test + fun `decode select config option with category thought_level`() { + val json = """ + { + "id": "thinking", + "name": "Thinking", + "category": "thought_level", + "type": "select", + "currentValue": "high", + "options": [{"value": "high", "name": "High"}] + } + """.trimIndent() + val option = ACPJson.decodeFromString(SessionConfigOption.serializer(), json) + val select = assertIs(option) + assertEquals(SessionConfigOptionCategory.THOUGHT_LEVEL, select.category) + } + + @Test + fun `decode select config option with custom category`() { + val json = """ + { + "id": "custom", + "name": "Custom", + "category": "_custom_foo", + "type": "select", + "currentValue": "a", + "options": [{"value": "a", "name": "A"}] + } + """.trimIndent() + val option = ACPJson.decodeFromString(SessionConfigOption.serializer(), json) + val select = assertIs(option) + assertEquals(SessionConfigOptionCategory("_custom_foo"), select.category) + } + + @Test + fun `decode select config option without category`() { + val json = """ + { + "id": "mode", + "name": "Mode", + "type": "select", + "currentValue": "a", + "options": [{"value": "a", "name": "A"}] + } + """.trimIndent() + val option = ACPJson.decodeFromString(SessionConfigOption.serializer(), json) + val select = assertIs(option) + assertNull(select.category) + } + + @Test + fun `decode boolean config option with category`() { + val json = """ + { + "id": "auto_approve", + "name": "Auto Approve", + "category": "mode", + "type": "boolean", + "currentValue": true + } + """.trimIndent() + val option = ACPJson.decodeFromString(SessionConfigOption.serializer(), json) + val boolOption = assertIs(option) + assertEquals(SessionConfigOptionCategory.MODE, boolOption.category) + } + + @Test + fun `decode boolean config option without category`() { + val json = """ + { + "id": "verbose", + "name": "Verbose", + "type": "boolean", + "currentValue": false + } + """.trimIndent() + val option = ACPJson.decodeFromString(SessionConfigOption.serializer(), json) + val boolOption = assertIs(option) + assertNull(boolOption.category) + } + + @Test + fun `encode select config option with category roundtrip`() { + val original = SessionConfigOption.Select( + id = SessionConfigId("mode"), + name = "Session Mode", + category = SessionConfigOptionCategory.MODE, + currentValue = SessionConfigValueId("ask"), + options = SessionConfigSelectOptions.Flat(listOf( + SessionConfigSelectOption(SessionConfigValueId("ask"), "Ask") + )) + ) + val encoded = ACPJson.encodeToString(SessionConfigOption.serializer(), original) + val decoded = ACPJson.decodeFromString(SessionConfigOption.serializer(), encoded) + val select = assertIs(decoded) + assertEquals(SessionConfigOptionCategory.MODE, select.category) + } + + @Test + fun `encode boolean config option with category roundtrip`() { + val original = SessionConfigOption.BooleanOption( + id = SessionConfigId("auto_approve"), + name = "Auto Approve", + category = SessionConfigOptionCategory.MODEL, + currentValue = true + ) + val encoded = ACPJson.encodeToString(SessionConfigOption.serializer(), original) + val decoded = ACPJson.decodeFromString(SessionConfigOption.serializer(), encoded) + val boolOption = assertIs(decoded) + assertEquals(SessionConfigOptionCategory.MODEL, boolOption.category) + } + + @Test + fun `factory method select with category`() { + val options = SessionConfigSelectOptions.Flat(listOf( + SessionConfigSelectOption(SessionConfigValueId("a"), "Option A") + )) + val option = SessionConfigOption.select( + "mode", "Mode", "a", options, + description = "Pick a mode", + category = SessionConfigOptionCategory.MODE + ) + assertEquals(SessionConfigOptionCategory.MODE, option.category) + } + + @Test + fun `factory method boolean with category`() { + val option = SessionConfigOption.boolean( + "verbose", "Verbose", true, + description = "Enable verbose logging", + category = SessionConfigOptionCategory.THOUGHT_LEVEL + ) + assertEquals(SessionConfigOptionCategory.THOUGHT_LEVEL, option.category) + } + @Test fun `unknown type roundtrip preserves type and value`() { val json = """{"sessionId":"s","configId":"c","type":"multi_select","value":["a","b"]}"""