diff --git a/turnstone/core/session.py b/turnstone/core/session.py index 9c74a54c..c0636bcc 100644 --- a/turnstone/core/session.py +++ b/turnstone/core/session.py @@ -628,10 +628,14 @@ class ChatSession: user_msg = "" asst_msg = "" for m in self.messages: + content = m.get("content") or "" + # Handle multi-part content (vision messages) + if isinstance(content, list): + content = " ".join(p.get("text", "") for p in content if isinstance(p, dict)) if m["role"] == "user" and not user_msg: - user_msg = (m.get("content") or "")[:300] + user_msg = content[:300] elif m["role"] == "assistant" and not asst_msg: - asst_msg = (m.get("content") or "")[:200] + asst_msg = content[:200] if user_msg and asst_msg: break if not user_msg: @@ -667,8 +671,9 @@ class ChatSession: title = raw.split("\n")[0].strip().strip('"').strip("'") if title: update_workstream_title(self._ws_id, title[:80]) + self.ui.on_rename(title[:80]) except Exception: - pass # Title generation is non-critical + log.debug("Title generation failed for ws=%s", self._ws_id, exc_info=True) def resume(self, ws_id: str) -> bool: """Load messages from a previous workstream and resume it. diff --git a/turnstone/ui/static/app.js b/turnstone/ui/static/app.js index 5fb79eaf..adb5bcb0 100644 --- a/turnstone/ui/static/app.js +++ b/turnstone/ui/static/app.js @@ -592,10 +592,31 @@ function connectContentSSE(wsId) { showLogin(); return; } - setTimeout(function () { - connectContentSSE(currentWsId); - }, contentRetryDelay); - contentRetryDelay = Math.min(contentRetryDelay * 2, 30000); + return r.json().then(function (data) { + // Replace workstream list — IDs may have changed after restart + var freshIds = {}; + workstreams = {}; + (data.workstreams || []).forEach(function (ws) { + workstreams[ws.id] = { name: ws.name, state: ws.state }; + freshIds[ws.id] = true; + }); + // Always re-render tabs since workstreams map was replaced + renderTabBar(); + // If current ws_id is stale, switch to first available + if (currentWsId && !freshIds[currentWsId]) { + var ids = Object.keys(freshIds); + if (ids.length) { + switchTab(ids[0]); + } else { + showDashboard(); + } + return; // switchTab/showDashboard handles SSE connection + } + setTimeout(function () { + connectContentSSE(currentWsId); + }, contentRetryDelay); + contentRetryDelay = Math.min(contentRetryDelay * 2, 30000); + }); }) .catch(function () { setTimeout(function () {