@@ -215,8 +215,7 @@ class ChatViewModel(
215 fun send(text: String): Boolean {
215 fun send(text: String): Boolean {
216 val conn = connection ?: return false
216 val conn = connection ?: return false
217 val trimmed = text.trim()
217 val trimmed = text.trim()
218− if (trimmed.isEmpty() || _running.value) return false
218+ if (trimmed.isEmpty() || !_running.compareAndSet(false, true)) return false
219− _running.value = true
220 _error.value = null
219 _error.value = null
221 _failedDraft.value = null
220 _failedDraft.value = null
222 // Clear the in-memory draft for the UI immediately, but don't persist the clear
221 // Clear the in-memory draft for the UI immediately, but don't persist the clear
@@ -255,8 +254,7 @@ class ChatViewModel(
255 /** Invoke a slash-command by name via the server's /command endpoint. */
254 /** Invoke a slash-command by name via the server's /command endpoint. */
256 fun runCommand(command: Command) {
255 fun runCommand(command: Command) {
257 val conn = connection ?: return
256 val conn = connection ?: return
258− if (_running.value) return
257+ if (!_running.compareAndSet(false, true)) return
259− _running.value = true
260 _error.value = null
258 _error.value = null
261 viewModelScope.launch {
259 viewModelScope.launch {
262 runCatching {
260 runCatching {