mirror of
https://github.com/nearai/ironclaw.git
synced 2026-09-02 23:56:24 +08:00
fix web chat refresh active thread (#2330)
This commit is contained in:
@@ -3220,14 +3220,30 @@ function loadThreads() {
|
||||
}
|
||||
}
|
||||
|
||||
// Default to assistant thread on first load if no thread selected
|
||||
if (!currentThreadId && assistantThreadId) {
|
||||
switchToAssistant();
|
||||
// Reopen the server's active thread on first load. This keeps the visible
|
||||
// chat attached to an in-flight agent turn after a browser refresh, even
|
||||
// when the URL does not carry an explicit thread hash.
|
||||
if (!currentThreadId) {
|
||||
const activeThreadId = data.active_thread || null;
|
||||
if (activeThreadId && activeThreadId === assistantThreadId) {
|
||||
switchToAssistant();
|
||||
return;
|
||||
}
|
||||
if (activeThreadId && threads.some(t => t.id === activeThreadId)) {
|
||||
switchThread(activeThreadId);
|
||||
return;
|
||||
}
|
||||
if (assistantThreadId) {
|
||||
switchToAssistant();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable/disable chat input based on channel type
|
||||
if (currentThreadId) {
|
||||
const currentThread = threads.find(t => t.id === currentThreadId);
|
||||
const currentThread = currentThreadId === assistantThreadId
|
||||
? data.assistant_thread
|
||||
: threads.find(t => t.id === currentThreadId);
|
||||
const ch = currentThread ? currentThread.channel : 'gateway';
|
||||
currentThreadIsReadOnly = isReadOnlyChannel(ch);
|
||||
if (currentThreadIsReadOnly) {
|
||||
|
||||
@@ -95,6 +95,37 @@ async def test_sse_reconnect_preserves_chat_history(page):
|
||||
assert user_msgs >= 1, "User message should be preserved after reconnect"
|
||||
|
||||
|
||||
async def test_refresh_without_hash_reopens_active_thread_history(page):
|
||||
"""Refreshing should reopen the server active thread when the URL has no thread hash."""
|
||||
await page.locator("#thread-new-btn").click()
|
||||
await page.wait_for_function(
|
||||
"() => !!currentThreadId && currentThreadId !== assistantThreadId"
|
||||
)
|
||||
thread_id = await page.evaluate("() => currentThreadId")
|
||||
|
||||
result = await send_chat_and_wait_for_terminal_message(
|
||||
page,
|
||||
"Refresh should keep this thread",
|
||||
)
|
||||
assert result["role"] == "assistant"
|
||||
|
||||
await page.evaluate(
|
||||
"() => history.replaceState(null, '', location.pathname + location.search)"
|
||||
)
|
||||
await page.reload()
|
||||
await page.wait_for_selector("#auth-screen", state="hidden", timeout=15000)
|
||||
await _wait_for_connected(page, timeout=15000)
|
||||
await page.wait_for_function(
|
||||
"(threadId) => currentThreadId === threadId",
|
||||
arg=thread_id,
|
||||
timeout=15000,
|
||||
)
|
||||
|
||||
await page.locator(SEL["message_user"]).filter(
|
||||
has_text="Refresh should keep this thread"
|
||||
).wait_for(state="visible", timeout=15000)
|
||||
|
||||
|
||||
async def test_sse_keepalive_comments_arrive(managed_gateway_server):
|
||||
"""Idle SSE connections should receive keepalive comments within 30 seconds."""
|
||||
async with sse_stream(managed_gateway_server.base_url, timeout=50) as response:
|
||||
|
||||
Reference in New Issue
Block a user