AI Agent commited on
Commit ·
bfd4772
1
Parent(s): 9357073
Fix: Handle mobile UI disconnects during LLM query via SSE keep-alives and UI alerts
Browse files- app.py +6 -1
- static/app.js +10 -3
app.py
CHANGED
|
@@ -870,7 +870,12 @@ def query():
|
|
| 870 |
_llm_query_queue.put((_run, ()))
|
| 871 |
|
| 872 |
while True:
|
| 873 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 874 |
if "error" in event:
|
| 875 |
yield f"data: {json.dumps({'error': event['error']})}\n\n"
|
| 876 |
break
|
|
|
|
| 870 |
_llm_query_queue.put((_run, ()))
|
| 871 |
|
| 872 |
while True:
|
| 873 |
+
try:
|
| 874 |
+
event = q_events.get(timeout=10)
|
| 875 |
+
except queue.Empty:
|
| 876 |
+
yield ": keep-alive\n\n"
|
| 877 |
+
continue
|
| 878 |
+
|
| 879 |
if "error" in event:
|
| 880 |
yield f"data: {json.dumps({'error': event['error']})}\n\n"
|
| 881 |
break
|
static/app.js
CHANGED
|
@@ -1005,15 +1005,22 @@ async function submitQuery() {
|
|
| 1005 |
} catch(err) {
|
| 1006 |
diag.error('Query error:', err);
|
| 1007 |
stopTimer();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1008 |
if (currentMsId) {
|
| 1009 |
const el = $(currentMsId);
|
| 1010 |
if (el) el.querySelector('.milestone-dot').className = 'milestone-dot failed';
|
| 1011 |
}
|
| 1012 |
-
addChatMsg(`❌ ${escHtml(
|
| 1013 |
outputContainer.innerHTML = `<div class="output-placeholder" style="color:var(--red)">
|
| 1014 |
-
<div class="ph-icon">⚠️</div><div>${escHtml(
|
| 1015 |
</div>`;
|
| 1016 |
-
notify(
|
| 1017 |
} finally {
|
| 1018 |
state.isQuerying = false;
|
| 1019 |
sendBtn.disabled = false;
|
|
|
|
| 1005 |
} catch(err) {
|
| 1006 |
diag.error('Query error:', err);
|
| 1007 |
stopTimer();
|
| 1008 |
+
|
| 1009 |
+
// Check if the browser recently suspended the tab (common on mobile)
|
| 1010 |
+
let errorMsg = err.message;
|
| 1011 |
+
if (document.hidden || document.visibilityState === 'hidden') {
|
| 1012 |
+
errorMsg = "Connection lost because the app was moved to the background. Please keep the app open during analysis to prevent the network from dropping.";
|
| 1013 |
+
}
|
| 1014 |
+
|
| 1015 |
if (currentMsId) {
|
| 1016 |
const el = $(currentMsId);
|
| 1017 |
if (el) el.querySelector('.milestone-dot').className = 'milestone-dot failed';
|
| 1018 |
}
|
| 1019 |
+
addChatMsg(`❌ ${escHtml(errorMsg)}`, 'assistant');
|
| 1020 |
outputContainer.innerHTML = `<div class="output-placeholder" style="color:var(--red)">
|
| 1021 |
+
<div class="ph-icon">⚠️</div><div>${escHtml(errorMsg)}</div>
|
| 1022 |
</div>`;
|
| 1023 |
+
notify(errorMsg, 'error', 8000);
|
| 1024 |
} finally {
|
| 1025 |
state.isQuerying = false;
|
| 1026 |
sendBtn.disabled = false;
|