feat(#1219): support canonical model capability metadata (#1228)

This commit is contained in:
m57 authored and GitHub committed 2026-09-22 18:53:24 +03:00
1 parent 16967c7e91
commit bf53905a93
14 files changed
+451 -43

No files matched your search

@@ -2,6 +2,7 @@ package com.m57.hermescontrol.ui.chat
import com.m57.hermescontrol.data.local.DataScope
import com.m57.hermescontrol.data.model.ModelCapabilities
import com.m57.hermescontrol.data.model.ModelInfoResponse
import com.m57.hermescontrol.data.model.ModelOptionsResponse
import com.m57.hermescontrol.data.model.ModelProvider
import com.m57.hermescontrol.data.model.PinnedModel
@@ -11,6 +12,7 @@ import com.m57.hermescontrol.data.ws.WsMethods
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceUntilIdle
@@ -175,6 +177,41 @@ class ChatModelSwitchDelegateTest {
scopeObserverJob.cancel()
}
@Test
fun modelInfoCapabilities_mergeWithCatalogAndClearOnScopeSwitch() =
testScope.runTest {
val scopeObserverJob = kotlinx.coroutines.Job()
val observerScope = kotlinx.coroutines.CoroutineScope(testDispatcher + scopeObserverJob)
delegate.attachScopeObserver(observerScope)
delegate.preloadModelOptions()
advanceUntilIdle()
uiState.update { it.copy(currentSessionModel = "openai/gpt-4o") }
delegate.applyModelInfo(
ModelInfoResponse(
provider = "openai",
model = "gpt-4o",
capabilities =
ModelCapabilities(
supports_tools = false,
supports_vision = true,
supports_reasoning = true,
),
),
initialDataScope,
)
assertEquals(true, uiState.value.currentModelCapabilities?.fast)
assertEquals(false, uiState.value.currentModelCapabilities?.supports_tools)
assertEquals(true, uiState.value.currentModelCapabilities?.supports_vision)
dataScope.value = initialDataScope.copy(activeProfileId = "work")
runCurrent()
assertNull(uiState.value.currentModelCapabilities)
scopeObserverJob.cancel()
}
@Test
fun closeAndReopenDuringPreload_doesNotDuplicateOrReopenAfterDismiss() =
testScope.runTest {