feat(chat): surface model switch warning messages in chat (#1239)
This commit is contained in:
3 files changed
+107
-1
No files matched your search
@@ -340,6 +340,19 @@ class ChatModelSwitchDelegate(
|
|||||||
it.copy(modelSwitchConfirmMessage = confirmMessage)
|
it.copy(modelSwitchConfirmMessage = confirmMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (pending != null && pending.sequence == modelSwitchSequence) {
|
||||||
|
val warning = (map["warning"] as? String)?.trim()
|
||||||
|
if (!warning.isNullOrBlank()) {
|
||||||
|
val formattedWarning =
|
||||||
|
if (warning.startsWith("⚠") || warning.startsWith("⚠️")) {
|
||||||
|
warning
|
||||||
|
} else {
|
||||||
|
"⚠ $warning"
|
||||||
|
}
|
||||||
|
addAssistantMessage(formattedWarning)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (key == "fast") {
|
} else if (key == "fast") {
|
||||||
val rawVal = map["value"] as? String
|
val rawVal = map["value"] as? String
|
||||||
|
|||||||
@@ -647,4 +647,95 @@ class ChatModelSwitchDelegateTest {
|
|||||||
delegate.dismissModelSwitchConfirm()
|
delegate.dismissModelSwitchConfirm()
|
||||||
assertEquals("anthropic/claude-3", uiState.value.currentSessionModel)
|
assertEquals("anthropic/claude-3", uiState.value.currentSessionModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun handleConfigSetResult_modelWarningWithoutConfirm_addsAssistantMessage() =
|
||||||
|
testScope.runTest {
|
||||||
|
delegate.handleModelSwitch("/model gpt-69-sol --provider openai-codex --session")
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
val warningText =
|
||||||
|
"Note: `gpt-69-sol` was not found in the OpenAI Codex model listing. " +
|
||||||
|
"Similar models: `gpt-5.6-sol`"
|
||||||
|
delegate.handleConfigSetResult(
|
||||||
|
id = "req-1",
|
||||||
|
result =
|
||||||
|
mapOf(
|
||||||
|
"key" to "model",
|
||||||
|
"value" to "gpt-69-sol",
|
||||||
|
"confirm_required" to false,
|
||||||
|
"warning" to warningText,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(1, assistantMessages.size)
|
||||||
|
assertEquals("⚠ $warningText", assistantMessages.first())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun handleConfigSetResult_modelWarningWithExistingWarningEmoji_doesNotDuplicateEmoji() =
|
||||||
|
testScope.runTest {
|
||||||
|
delegate.handleModelSwitch("/model gpt-69-sol --provider openai-codex --session")
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
val warningText = "⚠ Note: Already prefixed"
|
||||||
|
delegate.handleConfigSetResult(
|
||||||
|
id = "req-1",
|
||||||
|
result =
|
||||||
|
mapOf(
|
||||||
|
"key" to "model",
|
||||||
|
"value" to "gpt-69-sol",
|
||||||
|
"confirm_required" to false,
|
||||||
|
"warning" to warningText,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(listOf(warningText), assistantMessages)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun handleConfigSetResult_staleSequenceWarning_isIgnored() =
|
||||||
|
testScope.runTest {
|
||||||
|
// First switch
|
||||||
|
delegate.handleModelSwitch("/model gpt-4o --provider openai --session")
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
// Second switch supersedes first
|
||||||
|
delegate.handleModelSwitch("/model claude-3-5-sonnet --provider anthropic --session")
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
// First switch response arrives with warning
|
||||||
|
delegate.handleConfigSetResult(
|
||||||
|
id = "req-1",
|
||||||
|
result =
|
||||||
|
mapOf(
|
||||||
|
"key" to "model",
|
||||||
|
"value" to "gpt-4o",
|
||||||
|
"confirm_required" to false,
|
||||||
|
"warning" to "Stale warning",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
assertTrue(assistantMessages.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun handleConfigSetResult_blankWarning_doesNotAddAssistantMessage() =
|
||||||
|
testScope.runTest {
|
||||||
|
delegate.handleModelSwitch("/model gpt-4o --provider openai --session")
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
delegate.handleConfigSetResult(
|
||||||
|
id = "req-1",
|
||||||
|
result =
|
||||||
|
mapOf(
|
||||||
|
"key" to "model",
|
||||||
|
"value" to "gpt-4o",
|
||||||
|
"confirm_required" to false,
|
||||||
|
"warning" to " ",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
assertTrue(assistantMessages.isEmpty())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,9 @@ class KanbanScopeTest {
|
|||||||
repository = mockRepository,
|
repository = mockRepository,
|
||||||
preferences = preferences,
|
preferences = preferences,
|
||||||
eventsClientProvider = { mockEventsClient },
|
eventsClientProvider = { mockEventsClient },
|
||||||
)
|
).also {
|
||||||
|
it.ioDispatcher = testDispatcher
|
||||||
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
|
|||||||
Reference in new issue
Block a user