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)
|
||||
}
|
||||
}
|
||||
} 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") {
|
||||
val rawVal = map["value"] as? String
|
||||
|
||||
@@ -647,4 +647,95 @@ class ChatModelSwitchDelegateTest {
|
||||
delegate.dismissModelSwitchConfirm()
|
||||
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,
|
||||
preferences = preferences,
|
||||
eventsClientProvider = { mockEventsClient },
|
||||
)
|
||||
).also {
|
||||
it.ioDispatcher = testDispatcher
|
||||
}
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
|
||||
Reference in new issue
Block a user