mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-08-05 02:45:28 +00:00
fix: session URL hash lost when sending message mid-stream
Two independent bugs caused the session hash to disappear from the URL:
Bug 1 — ReferenceError in catch block silently killed error recovery
In handleChatSubmit, two const variables (streamingTTS at line 1922 and
abortCtrl at line 1741) were declared inside the try block but referenced
in the catch block. Since const is block-scoped in JavaScript, they were
undefined in catch, causing a ReferenceError that silently aborted the
error handler. This prevented materializePendingSession() from ever being
called, so no hash was written to the URL.
Fix: Hoisted both as let declarations before the try { block.
Bug 2 — Dual sessions.js ES module instances with mismatched state
app.js imported sessions.js with a version query string
(?v=20260722ctxheader4) while every other module imported ./sessions.js
without one. The browser treated them as different URLs, creating two
separate module instances with independent _pendingChat and
currentSessionId state. createDirectChat() set pending on one instance
while handleChatSubmit() checked hasPendingChat() on the other — so the
pending session never materialized.
Fix: Removed the version query string from the sessions.js import in
app.js and from the modulepreload + script tags in index.html. All
modules now share a single sessions.js instance.
Bonus guard: _adoptOpenedSessionBeforeAutoCreate() now checks
hasPendingChat() before adopting a stale DOM-active session, preventing
the send path from landing in the wrong session when a New Chat is pending.
This commit is contained in:
parent
1de596efb4
commit
6058be7088
3 changed files with 13 additions and 8 deletions
|
|
@ -10,14 +10,14 @@ import modelsModule from './js/models.js?v=20260715startupcalm2';
|
||||||
import ragModule from './js/rag.js';
|
import ragModule from './js/rag.js';
|
||||||
import presetsModule from './js/presets.js';
|
import presetsModule from './js/presets.js';
|
||||||
import searchModule from './js/search.js';
|
import searchModule from './js/search.js';
|
||||||
import chatModule from './js/chat.js?v=20260722ctxheader4';
|
import chatModule from './js/chat.js?v=20260801fix1';
|
||||||
import compareModule from './js/compare/index.js?v=20260723compareicon2';
|
import compareModule from './js/compare/index.js?v=20260723compareicon2';
|
||||||
import documentModule from './js/document.js?v=20260722emailfastindex1';
|
import documentModule from './js/document.js?v=20260722emailfastindex1';
|
||||||
import searchChatModule from './js/search-chat.js';
|
import searchChatModule from './js/search-chat.js';
|
||||||
import { makeWindowDraggable } from './js/windowDrag.js';
|
import { makeWindowDraggable } from './js/windowDrag.js';
|
||||||
import markdownModule from './js/markdown.js';
|
import markdownModule from './js/markdown.js';
|
||||||
import chatRenderer from './js/chatRenderer.js?v=20260722emailfastindex1';
|
import chatRenderer from './js/chatRenderer.js?v=20260722emailfastindex1';
|
||||||
import sessionModule from './js/sessions.js?v=20260722ctxheader4';
|
import sessionModule from './js/sessions.js';
|
||||||
import memoryModule from './js/memory.js?v=20260722memoryloading1';
|
import memoryModule from './js/memory.js?v=20260722memoryloading1';
|
||||||
import voiceRecorderModule from './js/voiceRecorder.js';
|
import voiceRecorderModule from './js/voiceRecorder.js';
|
||||||
import censorModule from './js/censor.js';
|
import censorModule from './js/censor.js';
|
||||||
|
|
|
||||||
|
|
@ -250,9 +250,9 @@
|
||||||
</script>
|
</script>
|
||||||
<link rel="stylesheet" href="/static/style.css?v=20260723tasksbulkfeedback1">
|
<link rel="stylesheet" href="/static/style.css?v=20260723tasksbulkfeedback1">
|
||||||
<link rel="modulepreload" href="/static/app.js?v=20260723tasksbulkfeedback1">
|
<link rel="modulepreload" href="/static/app.js?v=20260723tasksbulkfeedback1">
|
||||||
<link rel="modulepreload" href="/static/js/chat.js?v=20260722ctxheader4">
|
<link rel="modulepreload" href="/static/js/chat.js?v=20260801fix1">
|
||||||
<link rel="modulepreload" href="/static/js/ui.js">
|
<link rel="modulepreload" href="/static/js/ui.js">
|
||||||
<link rel="modulepreload" href="/static/js/sessions.js?v=20260722ctxheader4">
|
<link rel="modulepreload" href="/static/js/sessions.js">
|
||||||
<link rel="modulepreload" href="/static/js/markdown.js">
|
<link rel="modulepreload" href="/static/js/markdown.js">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -2504,7 +2504,7 @@
|
||||||
<script type="module" src="/static/js/ui.js"></script>
|
<script type="module" src="/static/js/ui.js"></script>
|
||||||
<script type="module" src="/static/js/markdown.js"></script>
|
<script type="module" src="/static/js/markdown.js"></script>
|
||||||
<script type="module" src="/static/js/dragSort.js"></script>
|
<script type="module" src="/static/js/dragSort.js"></script>
|
||||||
<script type="module" src="/static/js/sessions.js?v=20260722ctxheader4"></script>
|
<script type="module" src="/static/js/sessions.js"></script>
|
||||||
<script type="module" src="/static/js/memory.js?v=20260722memoryloading1"></script>
|
<script type="module" src="/static/js/memory.js?v=20260722memoryloading1"></script>
|
||||||
<script type="module" src="/static/js/skills.js"></script>
|
<script type="module" src="/static/js/skills.js"></script>
|
||||||
<script type="module" src="/static/js/tourHints.js"></script>
|
<script type="module" src="/static/js/tourHints.js"></script>
|
||||||
|
|
@ -2522,7 +2522,7 @@
|
||||||
<script type="module" src="/static/js/chatRenderer.js?v=20260722emailfastindex1"></script>
|
<script type="module" src="/static/js/chatRenderer.js?v=20260722emailfastindex1"></script>
|
||||||
<script type="module" src="/static/js/codeRunner.js"></script>
|
<script type="module" src="/static/js/codeRunner.js"></script>
|
||||||
<script type="module" src="/static/js/chatStream.js?v=20260722emailfastindex1"></script>
|
<script type="module" src="/static/js/chatStream.js?v=20260722emailfastindex1"></script>
|
||||||
<script type="module" src="/static/js/chat.js?v=20260722ctxheader4"></script>
|
<script type="module" src="/static/js/chat.js?v=20260801fix1"></script>
|
||||||
<script type="module" src="/static/js/cookbook.js"></script>
|
<script type="module" src="/static/js/cookbook.js"></script>
|
||||||
<script src="/static/js/cookbookSchedule.js"></script>
|
<script src="/static/js/cookbookSchedule.js"></script>
|
||||||
<script type="module" src="/static/js/search-chat.js"></script>
|
<script type="module" src="/static/js/search-chat.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -349,6 +349,9 @@ import { wireArrowUpRecall, getUserMessagesFromChatHistory } from './composerArr
|
||||||
|
|
||||||
async function _adoptOpenedSessionBeforeAutoCreate() {
|
async function _adoptOpenedSessionBeforeAutoCreate() {
|
||||||
if (!sessionModule || !sessionModule.getCurrentSessionId || sessionModule.getCurrentSessionId()) return true;
|
if (!sessionModule || !sessionModule.getCurrentSessionId || sessionModule.getCurrentSessionId()) return true;
|
||||||
|
// Don't adopt a stale session when the user explicitly started a New Chat
|
||||||
|
// (pending state set) — the send path must materialize the pending session.
|
||||||
|
if (sessionModule.hasPendingChat && sessionModule.hasPendingChat()) return false;
|
||||||
const activeRowId = document.querySelector('.list-item.active-session[data-session-id], .session-item.active[data-session-id]')?.dataset?.sessionId || '';
|
const activeRowId = document.querySelector('.list-item.active-session[data-session-id], .session-item.active[data-session-id]')?.dataset?.sessionId || '';
|
||||||
const hashId = _hashSessionCandidate();
|
const hashId = _hashSessionCandidate();
|
||||||
const lastSelectedId = String(window.__odysseusLastSelectedSessionId || '').trim();
|
const lastSelectedId = String(window.__odysseusLastSelectedSessionId || '').trim();
|
||||||
|
|
@ -1403,6 +1406,8 @@ import { wireArrowUpRecall, getUserMessagesFromChatHistory } from './composerArr
|
||||||
currentAccumulated = '';
|
currentAccumulated = '';
|
||||||
currentHolder = null;
|
currentHolder = null;
|
||||||
|
|
||||||
|
let abortCtrl = null;
|
||||||
|
let streamingTTS = false;
|
||||||
try {
|
try {
|
||||||
// Re-enable auto-scroll when user sends a message
|
// Re-enable auto-scroll when user sends a message
|
||||||
uiModule.setAutoScroll(true);
|
uiModule.setAutoScroll(true);
|
||||||
|
|
@ -1716,7 +1721,7 @@ import { wireArrowUpRecall, getUserMessagesFromChatHistory } from './composerArr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const abortCtrl = new AbortController();
|
abortCtrl = new AbortController();
|
||||||
abortCtrl._reason = '';
|
abortCtrl._reason = '';
|
||||||
currentAbort = abortCtrl;
|
currentAbort = abortCtrl;
|
||||||
|
|
||||||
|
|
@ -1897,7 +1902,7 @@ import { wireArrowUpRecall, getUserMessagesFromChatHistory } from './composerArr
|
||||||
let isThinking = false;
|
let isThinking = false;
|
||||||
let thinkingStartTime = null;
|
let thinkingStartTime = null;
|
||||||
// Streaming TTS: synthesize sentence-by-sentence during streaming
|
// Streaming TTS: synthesize sentence-by-sentence during streaming
|
||||||
const streamingTTS = !!(window.aiTTSManager && window.aiTTSManager.autoPlay && window.aiTTSManager.available);
|
streamingTTS = !!(window.aiTTSManager && window.aiTTSManager.autoPlay && window.aiTTSManager.available);
|
||||||
if (streamingTTS) window.aiTTSManager.streamingStart();
|
if (streamingTTS) window.aiTTSManager.streamingStart();
|
||||||
// Multi-bubble agent tracking
|
// Multi-bubble agent tracking
|
||||||
let roundHolder = holder; // Current AI text bubble (changes per round)
|
let roundHolder = holder; // Current AI text bubble (changes per round)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue