diff --git a/src/agentkit/chat/sqlite_conversation_store.py b/src/agentkit/chat/sqlite_conversation_store.py index 3b9ee65..6c4b0b0 100644 --- a/src/agentkit/chat/sqlite_conversation_store.py +++ b/src/agentkit/chat/sqlite_conversation_store.py @@ -276,13 +276,25 @@ class SqliteConversationStore: if conv_id in self._cache: result.append(self._cache[conv_id]) else: - result.append( - Conversation( - id=conv_id, - created_at=self._str_to_dt(row["created_at"]), - updated_at=self._str_to_dt(row["updated_at"]), - ) + conv = Conversation( + id=conv_id, + created_at=self._str_to_dt(row["created_at"]), + updated_at=self._str_to_dt(row["updated_at"]), ) + # Load first user message from SQLite for title derivation + try: + title_cursor = await db.execute( + "SELECT content FROM messages " + "WHERE conversation_id = ? AND role = 'user' " + "ORDER BY timestamp ASC LIMIT 1", + (conv_id,), + ) + title_row = await title_cursor.fetchone() + if title_row: + conv.messages.append(ChatMessage(role="user", content=title_row["content"])) + except Exception: + pass + result.append(conv) return result async def restore_from_store( diff --git a/src/agentkit/core/event_queue.py b/src/agentkit/core/event_queue.py index 38d536f..ad5b34f 100644 --- a/src/agentkit/core/event_queue.py +++ b/src/agentkit/core/event_queue.py @@ -210,7 +210,9 @@ class EventQueue: 保证不会遗漏或重复事件。 """ if self._closed: + # Must yield to make this an async generator, not a coroutine return + yield # noqa: unreachable — makes this an async generator # P1 #13 fix: enforce subscriber cap to prevent resource exhaustion # from malicious resume floods or runaway client loops. diff --git a/src/agentkit/server/routes/portal.py b/src/agentkit/server/routes/portal.py index e17abf5..570d42c 100644 --- a/src/agentkit/server/routes/portal.py +++ b/src/agentkit/server/routes/portal.py @@ -1141,9 +1141,13 @@ async def portal_websocket(websocket: WebSocket): if not message_text: continue - # Create conversation on first message (not on connect) - if conv is None: - conv_id = msg.get("conversation_id") + # Create or switch conversation based on conversation_id from frontend + conv_id = msg.get("conversation_id") + if conv_id: + if conv is None or conv.id != conv_id: + conv = await _conversation_store.get_or_create(conv_id) + await websocket.send_json({"type": "connected", "conversation_id": conv.id}) + elif conv is None: conv = await _conversation_store.get_or_create(conv_id) await websocket.send_json({"type": "connected", "conversation_id": conv.id})