mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-08-09 15:08:44 -04:00
* Fix: restore session URL hash writes (removed in cf4e240a)
Restores history.replaceState() calls in selectSession() and
materializePendingSession() that were dropped during the July 23 merge.
Without these, chat URLs never update the address bar hash, making
sessions unshareable and causing bare-URL reloads to land on the
welcome screen instead of restoring the last active chat.
Root cause: selectSession() had its hash-write deliberately removed;
materializePendingSession() lost its during a larger refactor that
added the stale-response and incognito guards.
Fixes #5870 (upstream)
* 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.
---------
Co-authored-by: samy <samy@users.noreply.github.com>
This commit is contained in:
+2
-2
@@ -10,14 +10,14 @@ import modelsModule from './js/models.js?v=20260715startupcalm2';
|
||||
import ragModule from './js/rag.js';
|
||||
import presetsModule from './js/presets.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 documentModule from './js/document.js?v=20260722emailfastindex1';
|
||||
import searchChatModule from './js/search-chat.js';
|
||||
import { makeWindowDraggable } from './js/windowDrag.js';
|
||||
import markdownModule from './js/markdown.js';
|
||||
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 voiceRecorderModule from './js/voiceRecorder.js';
|
||||
import censorModule from './js/censor.js';
|
||||
|
||||
+4
-4
@@ -250,9 +250,9 @@
|
||||
</script>
|
||||
<link rel="stylesheet" href="/static/style.css?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/sessions.js?v=20260722ctxheader4">
|
||||
<link rel="modulepreload" href="/static/js/sessions.js">
|
||||
<link rel="modulepreload" href="/static/js/markdown.js">
|
||||
</head>
|
||||
<body>
|
||||
@@ -2504,7 +2504,7 @@
|
||||
<script type="module" src="/static/js/ui.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/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/skills.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/codeRunner.js"></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 src="/static/js/cookbookSchedule.js"></script>
|
||||
<script type="module" src="/static/js/search-chat.js"></script>
|
||||
|
||||
+7
-2
@@ -349,6 +349,9 @@ import { wireArrowUpRecall, getUserMessagesFromChatHistory } from './composerArr
|
||||
|
||||
async function _adoptOpenedSessionBeforeAutoCreate() {
|
||||
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 hashId = _hashSessionCandidate();
|
||||
const lastSelectedId = String(window.__odysseusLastSelectedSessionId || '').trim();
|
||||
@@ -1403,6 +1406,8 @@ import { wireArrowUpRecall, getUserMessagesFromChatHistory } from './composerArr
|
||||
currentAccumulated = '';
|
||||
currentHolder = null;
|
||||
|
||||
let abortCtrl = null;
|
||||
let streamingTTS = false;
|
||||
try {
|
||||
// Re-enable auto-scroll when user sends a message
|
||||
uiModule.setAutoScroll(true);
|
||||
@@ -1716,7 +1721,7 @@ import { wireArrowUpRecall, getUserMessagesFromChatHistory } from './composerArr
|
||||
}
|
||||
|
||||
|
||||
const abortCtrl = new AbortController();
|
||||
abortCtrl = new AbortController();
|
||||
abortCtrl._reason = '';
|
||||
currentAbort = abortCtrl;
|
||||
|
||||
@@ -1897,7 +1902,7 @@ import { wireArrowUpRecall, getUserMessagesFromChatHistory } from './composerArr
|
||||
let isThinking = false;
|
||||
let thinkingStartTime = null;
|
||||
// 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();
|
||||
// Multi-bubble agent tracking
|
||||
let roundHolder = holder; // Current AI text bubble (changes per round)
|
||||
|
||||
@@ -1847,6 +1847,10 @@ export async function selectSession(id, { keepSidebar = false, showLoading = tru
|
||||
const _isTransientChat = !!_meta && (_meta.folder === 'Assistant' || _meta.folder === 'Tasks');
|
||||
if (!_isTransientChat) {
|
||||
Storage.set('lastSessionId', id);
|
||||
// Update URL hash without triggering hashchange handler
|
||||
if (window.location.hash !== '#' + id) {
|
||||
history.replaceState(null, '', '#' + id);
|
||||
}
|
||||
}
|
||||
// Restore character preset for persistent chats
|
||||
try {
|
||||
@@ -2313,6 +2317,7 @@ export async function materializePendingSession() {
|
||||
currentSessionId = payload.id;
|
||||
if (!isIncognito) {
|
||||
Storage.set('lastSessionId', payload.id);
|
||||
history.replaceState(null, '', '#' + payload.id);
|
||||
}
|
||||
|
||||
// Reload the sidebar in the background. Awaiting this used to block the first
|
||||
|
||||
Reference in New Issue
Block a user