diff --git a/internal/service/static/js/main.js b/internal/service/static/js/main.js index 77d3624..1c859a2 100644 --- a/internal/service/static/js/main.js +++ b/internal/service/static/js/main.js @@ -597,15 +597,6 @@ class Odidere { // Consume the input once the server accepted the request: an // earlier failure keeps it for a retry. let consumed = false; - const consumeInput = () => { - if (consumed) return; - consumed = true; - this.attachments = []; - this.locationData = null; - this.renderAttachments(); - this.ui.setLocationActive(false); - this.updateSendEnabled(); - }; try { const body = { stream: true }; @@ -638,7 +629,14 @@ class Odidere { body, controller.signal, )) { - consumeInput(); + if (!consumed) { + consumed = true; + this.attachments = []; + this.locationData = null; + this.renderAttachments(); + this.ui.setLocationActive(false); + this.updateSendEnabled(); + } if (this.handleEvent(type, data, voice)) break; } } catch (error) { @@ -652,7 +650,11 @@ class Odidere { } else if (error.name !== 'AbortError') { console.error('inference failed:', error); this.ui.renderError(`Inference failed: ${error.message}`); - this.ui.appendComposeText(text); + // Put the text back into the compose field only if the + // request failed before the server accepted it. If the + // stream disconnects later, the server already has the + // message and continues the run in the background. + if (!consumed) this.ui.appendComposeText(text); } // An AbortError ends delivery only; reset deleted the // conversation and will clear the local state.