mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-03-26 17:51:54 +01:00
Session id: int -> UUID (#2814)
* session id: int -> UUID * nit * validated * validated downgrade + upgrade + all functionality * nit * minor nit * fix test case
This commit is contained in:
parent
f3fb7c572e
commit
db0779dd02
@ -0,0 +1,153 @@
|
||||
"""
|
||||
Revision ID: 6756efa39ada
|
||||
Revises: 5d12a446f5c0
|
||||
Create Date: 2024-10-15 17:47:44.108537
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = "6756efa39ada"
|
||||
down_revision = "5d12a446f5c0"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
"""
|
||||
Migrate chat_session and chat_message tables to use UUID primary keys.
|
||||
|
||||
This script:
|
||||
1. Adds UUID columns to chat_session and chat_message
|
||||
2. Populates new columns with UUIDs
|
||||
3. Updates foreign key relationships
|
||||
4. Removes old integer ID columns
|
||||
|
||||
Note: Downgrade will assign new integer IDs, not restore original ones.
|
||||
"""
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.execute("CREATE EXTENSION IF NOT EXISTS pgcrypto;")
|
||||
|
||||
op.add_column(
|
||||
"chat_session",
|
||||
sa.Column(
|
||||
"new_id",
|
||||
sa.UUID(as_uuid=True),
|
||||
server_default=sa.text("gen_random_uuid()"),
|
||||
nullable=False,
|
||||
),
|
||||
)
|
||||
|
||||
op.execute("UPDATE chat_session SET new_id = gen_random_uuid();")
|
||||
|
||||
op.add_column(
|
||||
"chat_message",
|
||||
sa.Column("new_chat_session_id", sa.UUID(as_uuid=True), nullable=True),
|
||||
)
|
||||
|
||||
op.execute(
|
||||
"""
|
||||
UPDATE chat_message
|
||||
SET new_chat_session_id = cs.new_id
|
||||
FROM chat_session cs
|
||||
WHERE chat_message.chat_session_id = cs.id;
|
||||
"""
|
||||
)
|
||||
|
||||
op.drop_constraint(
|
||||
"chat_message_chat_session_id_fkey", "chat_message", type_="foreignkey"
|
||||
)
|
||||
|
||||
op.drop_column("chat_message", "chat_session_id")
|
||||
op.alter_column(
|
||||
"chat_message", "new_chat_session_id", new_column_name="chat_session_id"
|
||||
)
|
||||
|
||||
op.drop_constraint("chat_session_pkey", "chat_session", type_="primary")
|
||||
op.drop_column("chat_session", "id")
|
||||
op.alter_column("chat_session", "new_id", new_column_name="id")
|
||||
|
||||
op.create_primary_key("chat_session_pkey", "chat_session", ["id"])
|
||||
|
||||
op.create_foreign_key(
|
||||
"chat_message_chat_session_id_fkey",
|
||||
"chat_message",
|
||||
"chat_session",
|
||||
["chat_session_id"],
|
||||
["id"],
|
||||
ondelete="CASCADE",
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_constraint(
|
||||
"chat_message_chat_session_id_fkey", "chat_message", type_="foreignkey"
|
||||
)
|
||||
|
||||
op.add_column(
|
||||
"chat_session",
|
||||
sa.Column("old_id", sa.Integer, autoincrement=True, nullable=True),
|
||||
)
|
||||
|
||||
op.execute("CREATE SEQUENCE chat_session_old_id_seq OWNED BY chat_session.old_id;")
|
||||
op.execute(
|
||||
"ALTER TABLE chat_session ALTER COLUMN old_id SET DEFAULT nextval('chat_session_old_id_seq');"
|
||||
)
|
||||
|
||||
op.execute(
|
||||
"UPDATE chat_session SET old_id = nextval('chat_session_old_id_seq') WHERE old_id IS NULL;"
|
||||
)
|
||||
|
||||
op.alter_column("chat_session", "old_id", nullable=False)
|
||||
|
||||
op.drop_constraint("chat_session_pkey", "chat_session", type_="primary")
|
||||
op.create_primary_key("chat_session_pkey", "chat_session", ["old_id"])
|
||||
|
||||
op.add_column(
|
||||
"chat_message",
|
||||
sa.Column("old_chat_session_id", sa.Integer, nullable=True),
|
||||
)
|
||||
|
||||
op.execute(
|
||||
"""
|
||||
UPDATE chat_message
|
||||
SET old_chat_session_id = cs.old_id
|
||||
FROM chat_session cs
|
||||
WHERE chat_message.chat_session_id = cs.id;
|
||||
"""
|
||||
)
|
||||
|
||||
op.drop_column("chat_message", "chat_session_id")
|
||||
op.alter_column(
|
||||
"chat_message", "old_chat_session_id", new_column_name="chat_session_id"
|
||||
)
|
||||
|
||||
op.create_foreign_key(
|
||||
"chat_message_chat_session_id_fkey",
|
||||
"chat_message",
|
||||
"chat_session",
|
||||
["chat_session_id"],
|
||||
["old_id"],
|
||||
ondelete="CASCADE",
|
||||
)
|
||||
|
||||
op.drop_column("chat_session", "id")
|
||||
op.alter_column("chat_session", "old_id", new_column_name="id")
|
||||
|
||||
op.alter_column(
|
||||
"chat_session",
|
||||
"id",
|
||||
type_=sa.Integer(),
|
||||
existing_type=sa.Integer(),
|
||||
existing_nullable=False,
|
||||
existing_server_default=False,
|
||||
)
|
||||
|
||||
# Rename the sequence
|
||||
op.execute("ALTER SEQUENCE chat_session_old_id_seq RENAME TO chat_session_id_seq;")
|
||||
|
||||
# Update the default value to use the renamed sequence
|
||||
op.alter_column(
|
||||
"chat_session",
|
||||
"id",
|
||||
server_default=sa.text("nextval('chat_session_id_seq'::regclass)"),
|
||||
)
|
@ -1,5 +1,6 @@
|
||||
import re
|
||||
from typing import cast
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi.datastructures import Headers
|
||||
from sqlalchemy.orm import Session
|
||||
@ -34,7 +35,7 @@ def llm_doc_from_inference_section(inference_section: InferenceSection) -> LlmDo
|
||||
|
||||
|
||||
def create_chat_chain(
|
||||
chat_session_id: int,
|
||||
chat_session_id: UUID,
|
||||
db_session: Session,
|
||||
prefetch_tool_calls: bool = True,
|
||||
# Optional id at which we finish processing
|
||||
|
@ -43,7 +43,7 @@ logger = setup_logger()
|
||||
|
||||
|
||||
def get_chat_session_by_id(
|
||||
chat_session_id: int,
|
||||
chat_session_id: UUID,
|
||||
user_id: UUID | None,
|
||||
db_session: Session,
|
||||
include_deleted: bool = False,
|
||||
@ -87,9 +87,9 @@ def get_chat_sessions_by_slack_thread_id(
|
||||
|
||||
|
||||
def get_valid_messages_from_query_sessions(
|
||||
chat_session_ids: list[int],
|
||||
chat_session_ids: list[UUID],
|
||||
db_session: Session,
|
||||
) -> dict[int, str]:
|
||||
) -> dict[UUID, str]:
|
||||
user_message_subquery = (
|
||||
select(
|
||||
ChatMessage.chat_session_id, func.min(ChatMessage.id).label("user_msg_id")
|
||||
@ -196,7 +196,7 @@ def delete_orphaned_search_docs(db_session: Session) -> None:
|
||||
|
||||
|
||||
def delete_messages_and_files_from_chat_session(
|
||||
chat_session_id: int, db_session: Session
|
||||
chat_session_id: UUID, db_session: Session
|
||||
) -> None:
|
||||
# Select messages older than cutoff_time with files
|
||||
messages_with_files = db_session.execute(
|
||||
@ -253,7 +253,7 @@ def create_chat_session(
|
||||
def update_chat_session(
|
||||
db_session: Session,
|
||||
user_id: UUID | None,
|
||||
chat_session_id: int,
|
||||
chat_session_id: UUID,
|
||||
description: str | None = None,
|
||||
sharing_status: ChatSessionSharedStatus | None = None,
|
||||
) -> ChatSession:
|
||||
@ -276,7 +276,7 @@ def update_chat_session(
|
||||
|
||||
def delete_chat_session(
|
||||
user_id: UUID | None,
|
||||
chat_session_id: int,
|
||||
chat_session_id: UUID,
|
||||
db_session: Session,
|
||||
hard_delete: bool = HARD_DELETE_CHATS,
|
||||
) -> None:
|
||||
@ -337,7 +337,7 @@ def get_chat_message(
|
||||
|
||||
|
||||
def get_chat_messages_by_sessions(
|
||||
chat_session_ids: list[int],
|
||||
chat_session_ids: list[UUID],
|
||||
user_id: UUID | None,
|
||||
db_session: Session,
|
||||
skip_permission_check: bool = False,
|
||||
@ -370,7 +370,7 @@ def get_search_docs_for_chat_message(
|
||||
|
||||
|
||||
def get_chat_messages_by_session(
|
||||
chat_session_id: int,
|
||||
chat_session_id: UUID,
|
||||
user_id: UUID | None,
|
||||
db_session: Session,
|
||||
skip_permission_check: bool = False,
|
||||
@ -397,7 +397,7 @@ def get_chat_messages_by_session(
|
||||
|
||||
|
||||
def get_or_create_root_message(
|
||||
chat_session_id: int,
|
||||
chat_session_id: UUID,
|
||||
db_session: Session,
|
||||
) -> ChatMessage:
|
||||
try:
|
||||
@ -433,7 +433,7 @@ def get_or_create_root_message(
|
||||
|
||||
def reserve_message_id(
|
||||
db_session: Session,
|
||||
chat_session_id: int,
|
||||
chat_session_id: UUID,
|
||||
parent_message: int,
|
||||
message_type: MessageType,
|
||||
) -> int:
|
||||
@ -460,7 +460,7 @@ def reserve_message_id(
|
||||
|
||||
|
||||
def create_new_chat_message(
|
||||
chat_session_id: int,
|
||||
chat_session_id: UUID,
|
||||
parent_message: ChatMessage,
|
||||
message: str,
|
||||
prompt_id: int | None,
|
||||
|
@ -5,9 +5,12 @@ from typing import Any
|
||||
from typing import Literal
|
||||
from typing import NotRequired
|
||||
from typing import Optional
|
||||
from uuid import uuid4
|
||||
from typing_extensions import TypedDict # noreorder
|
||||
from uuid import UUID
|
||||
|
||||
from sqlalchemy.dialects.postgresql import UUID as PGUUID
|
||||
|
||||
from fastapi_users_db_sqlalchemy import SQLAlchemyBaseOAuthAccountTableUUID
|
||||
from fastapi_users_db_sqlalchemy import SQLAlchemyBaseUserTableUUID
|
||||
from fastapi_users_db_sqlalchemy.access_token import SQLAlchemyBaseAccessTokenTableUUID
|
||||
@ -920,7 +923,9 @@ class ToolCall(Base):
|
||||
class ChatSession(Base):
|
||||
__tablename__ = "chat_session"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
id: Mapped[UUID] = mapped_column(
|
||||
PGUUID(as_uuid=True), primary_key=True, default=uuid4
|
||||
)
|
||||
user_id: Mapped[UUID | None] = mapped_column(
|
||||
ForeignKey("user.id", ondelete="CASCADE"), nullable=True
|
||||
)
|
||||
@ -990,7 +995,9 @@ class ChatMessage(Base):
|
||||
__tablename__ = "chat_message"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
chat_session_id: Mapped[int] = mapped_column(ForeignKey("chat_session.id"))
|
||||
chat_session_id: Mapped[UUID] = mapped_column(
|
||||
PGUUID(as_uuid=True), ForeignKey("chat_session.id")
|
||||
)
|
||||
|
||||
alternate_assistant_id = mapped_column(
|
||||
Integer, ForeignKey("persona.id"), nullable=True
|
||||
|
@ -1,3 +1,5 @@
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from danswer.server.query_and_chat.models import ChatSessionDetails
|
||||
@ -23,7 +25,7 @@ class FolderUpdateRequest(BaseModel):
|
||||
|
||||
|
||||
class FolderChatSessionRequest(BaseModel):
|
||||
chat_session_id: int
|
||||
chat_session_id: UUID
|
||||
|
||||
|
||||
class DeleteFolderOptions(BaseModel):
|
||||
|
@ -4,6 +4,7 @@ import uuid
|
||||
from collections.abc import Callable
|
||||
from collections.abc import Generator
|
||||
from typing import Tuple
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import APIRouter
|
||||
from fastapi import Depends
|
||||
@ -131,7 +132,7 @@ def update_chat_session_model(
|
||||
|
||||
@router.get("/get-chat-session/{session_id}")
|
||||
def get_chat_session(
|
||||
session_id: int,
|
||||
session_id: UUID,
|
||||
is_shared: bool = False,
|
||||
user: User | None = Depends(current_user),
|
||||
db_session: Session = Depends(get_session),
|
||||
@ -254,7 +255,7 @@ def rename_chat_session(
|
||||
|
||||
@router.patch("/chat-session/{session_id}")
|
||||
def patch_chat_session(
|
||||
session_id: int,
|
||||
session_id: UUID,
|
||||
chat_session_update_req: ChatSessionUpdateRequest,
|
||||
user: User | None = Depends(current_user),
|
||||
db_session: Session = Depends(get_session),
|
||||
@ -271,7 +272,7 @@ def patch_chat_session(
|
||||
|
||||
@router.delete("/delete-chat-session/{session_id}")
|
||||
def delete_chat_session_by_id(
|
||||
session_id: int,
|
||||
session_id: UUID,
|
||||
user: User | None = Depends(current_user),
|
||||
db_session: Session = Depends(get_session),
|
||||
) -> None:
|
||||
|
@ -1,5 +1,6 @@
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel
|
||||
from pydantic import model_validator
|
||||
@ -34,7 +35,7 @@ class SimpleQueryRequest(BaseModel):
|
||||
|
||||
class UpdateChatSessionThreadRequest(BaseModel):
|
||||
# If not specified, use Danswer default persona
|
||||
chat_session_id: int
|
||||
chat_session_id: UUID
|
||||
new_alternate_model: str
|
||||
|
||||
|
||||
@ -45,7 +46,7 @@ class ChatSessionCreationRequest(BaseModel):
|
||||
|
||||
|
||||
class CreateChatSessionID(BaseModel):
|
||||
chat_session_id: int
|
||||
chat_session_id: UUID
|
||||
|
||||
|
||||
class ChatFeedbackRequest(BaseModel):
|
||||
@ -75,7 +76,7 @@ Currently the different branches are generated by changing the search query
|
||||
class CreateChatMessageRequest(ChunkContext):
|
||||
"""Before creating messages, be sure to create a chat_session and get an id"""
|
||||
|
||||
chat_session_id: int
|
||||
chat_session_id: UUID
|
||||
# This is the primary-key (unique identifier) for the previous message of the tree
|
||||
parent_message_id: int | None
|
||||
# New message contents
|
||||
@ -115,13 +116,18 @@ class CreateChatMessageRequest(ChunkContext):
|
||||
)
|
||||
return self
|
||||
|
||||
def model_dump(self, *args: Any, **kwargs: Any) -> dict[str, Any]:
|
||||
data = super().model_dump(*args, **kwargs)
|
||||
data["chat_session_id"] = str(data["chat_session_id"])
|
||||
return data
|
||||
|
||||
|
||||
class ChatMessageIdentifier(BaseModel):
|
||||
message_id: int
|
||||
|
||||
|
||||
class ChatRenameRequest(BaseModel):
|
||||
chat_session_id: int
|
||||
chat_session_id: UUID
|
||||
name: str | None = None
|
||||
|
||||
|
||||
@ -134,7 +140,7 @@ class RenameChatSessionResponse(BaseModel):
|
||||
|
||||
|
||||
class ChatSessionDetails(BaseModel):
|
||||
id: int
|
||||
id: UUID
|
||||
name: str
|
||||
persona_id: int | None = None
|
||||
time_created: str
|
||||
@ -175,7 +181,7 @@ class ChatMessageDetail(BaseModel):
|
||||
overridden_model: str | None
|
||||
alternate_assistant_id: int | None = None
|
||||
# Dict mapping citation number to db_doc_id
|
||||
chat_session_id: int | None = None
|
||||
chat_session_id: UUID | None = None
|
||||
citations: dict[int, int] | None = None
|
||||
files: list[FileDescriptor]
|
||||
tool_calls: list[ToolCallFinalResult]
|
||||
@ -187,14 +193,14 @@ class ChatMessageDetail(BaseModel):
|
||||
|
||||
|
||||
class SearchSessionDetailResponse(BaseModel):
|
||||
search_session_id: int
|
||||
search_session_id: UUID
|
||||
description: str
|
||||
documents: list[SearchDoc]
|
||||
messages: list[ChatMessageDetail]
|
||||
|
||||
|
||||
class ChatSessionDetailResponse(BaseModel):
|
||||
chat_session_id: int
|
||||
chat_session_id: UUID
|
||||
description: str
|
||||
persona_id: int | None = None
|
||||
persona_name: str | None
|
||||
|
@ -1,3 +1,5 @@
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import APIRouter
|
||||
from fastapi import Depends
|
||||
from fastapi import HTTPException
|
||||
@ -186,7 +188,7 @@ def get_user_search_sessions(
|
||||
|
||||
@basic_router.get("/search-session/{session_id}")
|
||||
def get_search_session(
|
||||
session_id: int,
|
||||
session_id: UUID,
|
||||
is_shared: bool = False,
|
||||
user: User | None = Depends(current_user),
|
||||
db_session: Session = Depends(get_session),
|
||||
|
@ -1,4 +1,5 @@
|
||||
from typing import Any
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel
|
||||
from pydantic import model_validator
|
||||
@ -40,7 +41,7 @@ class ToolCallFinalResult(ToolCallKickoff):
|
||||
|
||||
|
||||
class DynamicSchemaInfo(BaseModel):
|
||||
chat_session_id: int | None
|
||||
chat_session_id: UUID | None
|
||||
message_id: int | None
|
||||
|
||||
|
||||
|
@ -42,7 +42,7 @@ def get_empty_chat_messages_entries__paginated(
|
||||
|
||||
message_skeletons.append(
|
||||
ChatMessageSkeleton(
|
||||
message_id=chat_session.id,
|
||||
message_id=message.id,
|
||||
chat_session_id=chat_session.id,
|
||||
user_id=str(chat_session.user_id) if chat_session.user_id else None,
|
||||
flow_type=flow_type,
|
||||
|
@ -1,3 +1,5 @@
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel
|
||||
from pydantic import Field
|
||||
|
||||
@ -36,7 +38,7 @@ class BasicCreateChatMessageRequest(ChunkContext):
|
||||
Note, for simplicity this option only allows for a single linear chain of messages
|
||||
"""
|
||||
|
||||
chat_session_id: int
|
||||
chat_session_id: UUID
|
||||
# New message contents
|
||||
message: str
|
||||
# Defaults to using retrieval with no additional filters
|
||||
|
@ -4,6 +4,7 @@ from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from datetime import timezone
|
||||
from typing import Literal
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import APIRouter
|
||||
from fastapi import Depends
|
||||
@ -83,7 +84,7 @@ class MessageSnapshot(BaseModel):
|
||||
|
||||
|
||||
class ChatSessionMinimal(BaseModel):
|
||||
id: int
|
||||
id: UUID
|
||||
user_email: str
|
||||
name: str | None
|
||||
first_user_message: str
|
||||
@ -95,7 +96,7 @@ class ChatSessionMinimal(BaseModel):
|
||||
|
||||
|
||||
class ChatSessionSnapshot(BaseModel):
|
||||
id: int
|
||||
id: UUID
|
||||
user_email: str
|
||||
name: str | None
|
||||
messages: list[MessageSnapshot]
|
||||
@ -105,7 +106,7 @@ class ChatSessionSnapshot(BaseModel):
|
||||
|
||||
|
||||
class QuestionAnswerPairSnapshot(BaseModel):
|
||||
chat_session_id: int
|
||||
chat_session_id: UUID
|
||||
# 1-indexed message number in the chat_session
|
||||
# e.g. the first message pair in the chat_session is 1, the second is 2, etc.
|
||||
message_pair_num: int
|
||||
@ -350,7 +351,7 @@ def get_chat_session_history(
|
||||
|
||||
@router.get("/admin/chat-session-history/{chat_session_id}")
|
||||
def get_chat_session_admin(
|
||||
chat_session_id: int,
|
||||
chat_session_id: UUID,
|
||||
_: User | None = Depends(current_admin_user),
|
||||
db_session: Session = Depends(get_session),
|
||||
) -> ChatSessionSnapshot:
|
||||
|
@ -1,5 +1,6 @@
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
@ -14,7 +15,7 @@ class FlowType(str, Enum):
|
||||
|
||||
class ChatMessageSkeleton(BaseModel):
|
||||
message_id: int
|
||||
chat_session_id: int
|
||||
chat_session_id: UUID
|
||||
user_id: str | None
|
||||
flow_type: FlowType
|
||||
time_sent: datetime
|
||||
|
@ -1,4 +1,5 @@
|
||||
import json
|
||||
from uuid import UUID
|
||||
|
||||
import requests
|
||||
from requests.models import Response
|
||||
@ -44,7 +45,7 @@ class ChatSessionManager:
|
||||
|
||||
@staticmethod
|
||||
def send_message(
|
||||
chat_session_id: int,
|
||||
chat_session_id: UUID,
|
||||
message: str,
|
||||
parent_message_id: int | None = None,
|
||||
user_performing_action: DATestUser | None = None,
|
||||
|
@ -123,14 +123,14 @@ class DATestPersona(BaseModel):
|
||||
|
||||
#
|
||||
class DATestChatSession(BaseModel):
|
||||
id: int
|
||||
id: UUID
|
||||
persona_id: int
|
||||
description: str
|
||||
|
||||
|
||||
class DATestChatMessage(BaseModel):
|
||||
id: str | None = None
|
||||
chat_session_id: int
|
||||
chat_session_id: UUID
|
||||
parent_message_id: str | None
|
||||
message: str
|
||||
response: str
|
||||
|
@ -1,4 +1,5 @@
|
||||
import unittest
|
||||
import uuid
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
|
||||
@ -73,7 +74,7 @@ class TestCustomTool(unittest.TestCase):
|
||||
}
|
||||
validate_openapi_schema(self.openapi_schema)
|
||||
self.dynamic_schema_info: DynamicSchemaInfo = DynamicSchemaInfo(
|
||||
chat_session_id=10, message_id=20
|
||||
chat_session_id=uuid.uuid4(), message_id=20
|
||||
)
|
||||
|
||||
@patch("danswer.tools.custom.custom_tool.requests.request")
|
||||
|
@ -145,19 +145,17 @@ export function ChatPage({
|
||||
const existingChatIdRaw = searchParams.get("chatId");
|
||||
const currentPersonaId = searchParams.get(SEARCH_PARAM_NAMES.PERSONA_ID);
|
||||
|
||||
const existingChatSessionId = existingChatIdRaw
|
||||
? parseInt(existingChatIdRaw)
|
||||
: null;
|
||||
const existingChatSessionId = existingChatIdRaw ? existingChatIdRaw : null;
|
||||
|
||||
const selectedChatSession = chatSessions.find(
|
||||
(chatSession) => chatSession.id === existingChatSessionId
|
||||
);
|
||||
|
||||
const chatSessionIdRef = useRef<number | null>(existingChatSessionId);
|
||||
const chatSessionIdRef = useRef<string | null>(existingChatSessionId);
|
||||
|
||||
// Only updates on session load (ie. rename / switching chat session)
|
||||
// Useful for determining which session has been loaded (i.e. still on `new, empty session` or `previous session`)
|
||||
const loadedIdSessionRef = useRef<number | null>(existingChatSessionId);
|
||||
const loadedIdSessionRef = useRef<string | null>(existingChatSessionId);
|
||||
|
||||
// Assistants in order
|
||||
const { finalAssistants } = useMemo(() => {
|
||||
@ -448,11 +446,11 @@ export function ChatPage({
|
||||
);
|
||||
|
||||
const [completeMessageDetail, setCompleteMessageDetail] = useState<
|
||||
Map<number | null, Map<number, Message>>
|
||||
Map<string | null, Map<number, Message>>
|
||||
>(new Map());
|
||||
|
||||
const updateCompleteMessageDetail = (
|
||||
sessionId: number | null,
|
||||
sessionId: string | null,
|
||||
messageMap: Map<number, Message>
|
||||
) => {
|
||||
setCompleteMessageDetail((prevState) => {
|
||||
@ -463,13 +461,13 @@ export function ChatPage({
|
||||
};
|
||||
|
||||
const currentMessageMap = (
|
||||
messageDetail: Map<number | null, Map<number, Message>>
|
||||
messageDetail: Map<string | null, Map<number, Message>>
|
||||
) => {
|
||||
return (
|
||||
messageDetail.get(chatSessionIdRef.current) || new Map<number, Message>()
|
||||
);
|
||||
};
|
||||
const currentSessionId = (): number => {
|
||||
const currentSessionId = (): string => {
|
||||
return chatSessionIdRef.current!;
|
||||
};
|
||||
|
||||
@ -484,7 +482,7 @@ export function ChatPage({
|
||||
// if calling this function repeatedly with short delay, stay may not update in time
|
||||
// and result in weird behavipr
|
||||
completeMessageMapOverride?: Map<number, Message> | null;
|
||||
chatSessionId?: number;
|
||||
chatSessionId?: string;
|
||||
replacementsMap?: Map<number, number> | null;
|
||||
makeLatestChildMessage?: boolean;
|
||||
}) => {
|
||||
@ -559,23 +557,23 @@ export function ChatPage({
|
||||
|
||||
const [submittedMessage, setSubmittedMessage] = useState("");
|
||||
|
||||
const [chatState, setChatState] = useState<Map<number | null, ChatState>>(
|
||||
const [chatState, setChatState] = useState<Map<string | null, ChatState>>(
|
||||
new Map([[chatSessionIdRef.current, "input"]])
|
||||
);
|
||||
|
||||
const [regenerationState, setRegenerationState] = useState<
|
||||
Map<number | null, RegenerationState | null>
|
||||
Map<string | null, RegenerationState | null>
|
||||
>(new Map([[null, null]]));
|
||||
|
||||
const [abortControllers, setAbortControllers] = useState<
|
||||
Map<number | null, AbortController>
|
||||
Map<string | null, AbortController>
|
||||
>(new Map());
|
||||
|
||||
// Updates "null" session values to new session id for
|
||||
// regeneration, chat, and abort controller state, messagehistory
|
||||
const updateStatesWithNewSessionId = (newSessionId: number) => {
|
||||
const updateStatesWithNewSessionId = (newSessionId: string) => {
|
||||
const updateState = (
|
||||
setState: Dispatch<SetStateAction<Map<number | null, any>>>,
|
||||
setState: Dispatch<SetStateAction<Map<string | null, any>>>,
|
||||
defaultValue?: any
|
||||
) => {
|
||||
setState((prevState) => {
|
||||
@ -610,7 +608,7 @@ export function ChatPage({
|
||||
chatSessionIdRef.current = newSessionId;
|
||||
};
|
||||
|
||||
const updateChatState = (newState: ChatState, sessionId?: number | null) => {
|
||||
const updateChatState = (newState: ChatState, sessionId?: string | null) => {
|
||||
setChatState((prevState) => {
|
||||
const newChatState = new Map(prevState);
|
||||
newChatState.set(
|
||||
@ -635,7 +633,7 @@ export function ChatPage({
|
||||
|
||||
const updateRegenerationState = (
|
||||
newState: RegenerationState | null,
|
||||
sessionId?: number | null
|
||||
sessionId?: string | null
|
||||
) => {
|
||||
setRegenerationState((prevState) => {
|
||||
const newRegenerationState = new Map(prevState);
|
||||
@ -647,18 +645,18 @@ export function ChatPage({
|
||||
});
|
||||
};
|
||||
|
||||
const resetRegenerationState = (sessionId?: number | null) => {
|
||||
const resetRegenerationState = (sessionId?: string | null) => {
|
||||
updateRegenerationState(null, sessionId);
|
||||
};
|
||||
|
||||
const currentRegenerationState = (): RegenerationState | null => {
|
||||
return regenerationState.get(currentSessionId()) || null;
|
||||
};
|
||||
const [canContinue, setCanContinue] = useState<Map<number | null, boolean>>(
|
||||
const [canContinue, setCanContinue] = useState<Map<string | null, boolean>>(
|
||||
new Map([[null, false]])
|
||||
);
|
||||
|
||||
const updateCanContinue = (newState: boolean, sessionId?: number | null) => {
|
||||
const updateCanContinue = (newState: boolean, sessionId?: string | null) => {
|
||||
setCanContinue((prevState) => {
|
||||
const newCanContinueState = new Map(prevState);
|
||||
newCanContinueState.set(
|
||||
@ -1003,7 +1001,7 @@ export function ChatPage({
|
||||
|
||||
setAlternativeGeneratingAssistant(alternativeAssistantOverride);
|
||||
clientScrollToBottom();
|
||||
let currChatSessionId: number;
|
||||
let currChatSessionId: string;
|
||||
const isNewSession = chatSessionIdRef.current === null;
|
||||
const searchParamBasedChatSessionName =
|
||||
searchParams.get(SEARCH_PARAM_NAMES.TITLE) || null;
|
||||
@ -1014,7 +1012,7 @@ export function ChatPage({
|
||||
searchParamBasedChatSessionName
|
||||
);
|
||||
} else {
|
||||
currChatSessionId = chatSessionIdRef.current as number;
|
||||
currChatSessionId = chatSessionIdRef.current as string;
|
||||
}
|
||||
frozenSessionId = currChatSessionId;
|
||||
|
||||
@ -1598,7 +1596,7 @@ export function ChatPage({
|
||||
}
|
||||
|
||||
const [visibleRange, setVisibleRange] = useState<
|
||||
Map<number | null, VisibleRange>
|
||||
Map<string | null, VisibleRange>
|
||||
>(() => {
|
||||
const initialRange: VisibleRange = {
|
||||
start: 0,
|
||||
|
@ -30,7 +30,7 @@ const FolderItem = ({
|
||||
initiallySelected,
|
||||
}: {
|
||||
folder: Folder;
|
||||
currentChatId?: number;
|
||||
currentChatId?: string;
|
||||
isInitiallyExpanded: boolean;
|
||||
initiallySelected: boolean;
|
||||
}) => {
|
||||
@ -145,10 +145,7 @@ const FolderItem = ({
|
||||
const handleDrop = async (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
setIsDragOver(false);
|
||||
const chatSessionId = parseInt(
|
||||
event.dataTransfer.getData(CHAT_SESSION_ID_KEY),
|
||||
10
|
||||
);
|
||||
const chatSessionId = event.dataTransfer.getData(CHAT_SESSION_ID_KEY);
|
||||
try {
|
||||
await addChatToFolder(folder.folder_id, chatSessionId);
|
||||
router.refresh(); // Refresh to show the updated folder contents
|
||||
@ -302,7 +299,7 @@ export const FolderList = ({
|
||||
newFolderId,
|
||||
}: {
|
||||
folders: Folder[];
|
||||
currentChatId?: number;
|
||||
currentChatId?: string;
|
||||
openedFolders?: { [key: number]: boolean };
|
||||
newFolderId: number | null;
|
||||
}) => {
|
||||
|
@ -17,7 +17,7 @@ export async function createFolder(folderName: string): Promise<number> {
|
||||
// Function to add a chat session to a folder
|
||||
export async function addChatToFolder(
|
||||
folderId: number,
|
||||
chatSessionId: number
|
||||
chatSessionId: string
|
||||
): Promise<void> {
|
||||
const response = await fetch(`/api/folder/${folderId}/add-chat-session`, {
|
||||
method: "POST",
|
||||
@ -34,7 +34,7 @@ export async function addChatToFolder(
|
||||
// Function to remove a chat session from a folder
|
||||
export async function removeChatFromFolder(
|
||||
folderId: number,
|
||||
chatSessionId: number
|
||||
chatSessionId: string
|
||||
): Promise<void> {
|
||||
const response = await fetch(`/api/folder/${folderId}/remove-chat-session`, {
|
||||
method: "POST",
|
||||
|
@ -86,7 +86,7 @@ export function ChatInputBar({
|
||||
setFiles: (files: FileDescriptor[]) => void;
|
||||
handleFileUpload: (files: File[]) => void;
|
||||
textAreaRef: React.RefObject<HTMLTextAreaElement>;
|
||||
chatSessionId?: number;
|
||||
chatSessionId?: string;
|
||||
refreshUser: () => void;
|
||||
}) {
|
||||
useEffect(() => {
|
||||
|
@ -60,7 +60,7 @@ export interface ToolCallFinalResult {
|
||||
}
|
||||
|
||||
export interface ChatSession {
|
||||
id: number;
|
||||
id: string;
|
||||
name: string;
|
||||
persona_id: number;
|
||||
time_created: string;
|
||||
@ -70,7 +70,7 @@ export interface ChatSession {
|
||||
}
|
||||
|
||||
export interface SearchSession {
|
||||
search_session_id: number;
|
||||
search_session_id: string;
|
||||
documents: SearchDanswerDocument[];
|
||||
messages: BackendMessage[];
|
||||
description: string;
|
||||
@ -97,7 +97,7 @@ export interface Message {
|
||||
}
|
||||
|
||||
export interface BackendChatSession {
|
||||
chat_session_id: number;
|
||||
chat_session_id: string;
|
||||
description: string;
|
||||
persona_id: number;
|
||||
persona_name: string;
|
||||
@ -110,7 +110,7 @@ export interface BackendChatSession {
|
||||
export interface BackendMessage {
|
||||
message_id: number;
|
||||
comments: any;
|
||||
chat_session_id: number;
|
||||
chat_session_id: string;
|
||||
parent_message: number | null;
|
||||
latest_child_message: number | null;
|
||||
message: string;
|
||||
|
@ -55,7 +55,7 @@ export function getChatRetentionInfo(
|
||||
}
|
||||
|
||||
export async function updateModelOverrideForChatSession(
|
||||
chatSessionId: number,
|
||||
chatSessionId: string,
|
||||
newAlternateModel: string
|
||||
) {
|
||||
const response = await fetch("/api/chat/update-chat-session-model", {
|
||||
@ -74,7 +74,7 @@ export async function updateModelOverrideForChatSession(
|
||||
export async function createChatSession(
|
||||
personaId: number,
|
||||
description: string | null
|
||||
): Promise<number> {
|
||||
): Promise<string> {
|
||||
const createChatSessionResponse = await fetch(
|
||||
"/api/chat/create-chat-session",
|
||||
{
|
||||
@ -131,7 +131,7 @@ export async function* sendMessage({
|
||||
message: string;
|
||||
fileDescriptors: FileDescriptor[];
|
||||
parentMessageId: number | null;
|
||||
chatSessionId: number;
|
||||
chatSessionId: string;
|
||||
promptId: number | null | undefined;
|
||||
filters: Filters | null;
|
||||
selectedDocumentIds: number[] | null;
|
||||
@ -203,7 +203,7 @@ export async function* sendMessage({
|
||||
yield* handleSSEStream<PacketType>(response);
|
||||
}
|
||||
|
||||
export async function nameChatSession(chatSessionId: number, message: string) {
|
||||
export async function nameChatSession(chatSessionId: string, message: string) {
|
||||
const response = await fetch("/api/chat/rename-chat-session", {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
@ -252,7 +252,7 @@ export async function handleChatFeedback(
|
||||
return response;
|
||||
}
|
||||
export async function renameChatSession(
|
||||
chatSessionId: number,
|
||||
chatSessionId: string,
|
||||
newName: string
|
||||
) {
|
||||
const response = await fetch(`/api/chat/rename-chat-session`, {
|
||||
@ -269,7 +269,7 @@ export async function renameChatSession(
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function deleteChatSession(chatSessionId: number) {
|
||||
export async function deleteChatSession(chatSessionId: string) {
|
||||
const response = await fetch(
|
||||
`/api/chat/delete-chat-session/${chatSessionId}`,
|
||||
{
|
||||
@ -348,6 +348,7 @@ export function getCitedDocumentsFromMessage(message: Message) {
|
||||
}
|
||||
|
||||
export function groupSessionsByDateRange(chatSessions: ChatSession[]) {
|
||||
console.log(chatSessions);
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0); // Set to start of today for accurate comparison
|
||||
|
||||
@ -584,7 +585,7 @@ const PARAMS_TO_SKIP = [
|
||||
|
||||
export function buildChatUrl(
|
||||
existingSearchParams: ReadonlyURLSearchParams,
|
||||
chatSessionId: number | null,
|
||||
chatSessionId: string | null,
|
||||
personaId: number | null,
|
||||
search?: boolean
|
||||
) {
|
||||
|
@ -6,12 +6,12 @@ import { ChatSessionSharedStatus } from "../interfaces";
|
||||
import { FiCopy } from "react-icons/fi";
|
||||
import { CopyButton } from "@/components/CopyButton";
|
||||
|
||||
function buildShareLink(chatSessionId: number) {
|
||||
function buildShareLink(chatSessionId: string) {
|
||||
const baseUrl = `${window.location.protocol}//${window.location.host}`;
|
||||
return `${baseUrl}/chat/shared/${chatSessionId}`;
|
||||
}
|
||||
|
||||
async function generateShareLink(chatSessionId: number) {
|
||||
async function generateShareLink(chatSessionId: string) {
|
||||
const response = await fetch(`/api/chat/chat-session/${chatSessionId}`, {
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
@ -26,7 +26,7 @@ async function generateShareLink(chatSessionId: number) {
|
||||
return null;
|
||||
}
|
||||
|
||||
async function deleteShareLink(chatSessionId: number) {
|
||||
async function deleteShareLink(chatSessionId: string) {
|
||||
const response = await fetch(`/api/chat/chat-session/${chatSessionId}`, {
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
@ -44,7 +44,7 @@ export function ShareChatSessionModal({
|
||||
onShare,
|
||||
onClose,
|
||||
}: {
|
||||
chatSessionId: number;
|
||||
chatSessionId: string;
|
||||
existingSharedStatus: ChatSessionSharedStatus;
|
||||
onShare?: (shared: boolean) => void;
|
||||
onClose: () => void;
|
||||
|
@ -14,7 +14,7 @@ interface LlmTabProps {
|
||||
llmOverrideManager: LlmOverrideManager;
|
||||
currentLlm: string;
|
||||
openModelSettings: () => void;
|
||||
chatSessionId?: number;
|
||||
chatSessionId?: string;
|
||||
close: () => void;
|
||||
currentAssistant: Persona;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ export function PagesTab({
|
||||
}: {
|
||||
page: pageType;
|
||||
existingChats?: ChatSession[];
|
||||
currentChatId?: number;
|
||||
currentChatId?: string;
|
||||
folders?: Folder[];
|
||||
openedFolders?: { [key: number]: boolean };
|
||||
closeSidebar?: () => void;
|
||||
@ -44,10 +44,7 @@ export function PagesTab({
|
||||
) => {
|
||||
event.preventDefault();
|
||||
setIsDragOver(false); // Reset drag over state on drop
|
||||
const chatSessionId = parseInt(
|
||||
event.dataTransfer.getData(CHAT_SESSION_ID_KEY),
|
||||
10
|
||||
);
|
||||
const chatSessionId = event.dataTransfer.getData(CHAT_SESSION_ID_KEY);
|
||||
const folderId = event.dataTransfer.getData(FOLDER_ID_KEY);
|
||||
|
||||
if (folderId) {
|
||||
|
@ -48,7 +48,7 @@ export default async function Page({ params }: { params: { chatId: string } }) {
|
||||
const user = results[1] as User | null;
|
||||
const chatSession = results[2] as BackendChatSession | null;
|
||||
const assistantsResponse = results[3] as FetchAssistantsResponse | null;
|
||||
const [availableAssistants, _] = assistantsResponse ?? [[], null];
|
||||
const [availableAssistants, error] = assistantsResponse ?? [[], null];
|
||||
|
||||
const authDisabled = authTypeMetadata?.authType === "disabled";
|
||||
if (!authDisabled && !user) {
|
||||
@ -58,7 +58,6 @@ export default async function Page({ params }: { params: { chatId: string } }) {
|
||||
if (user && !user.is_verified && authTypeMetadata?.requiresVerification) {
|
||||
return redirect("/auth/waiting-on-verification");
|
||||
}
|
||||
|
||||
const persona: Persona =
|
||||
chatSession?.persona_id && availableAssistants?.length
|
||||
? (availableAssistants.find((p) => p.id === chatSession.persona_id) ??
|
||||
@ -72,7 +71,7 @@ export default async function Page({ params }: { params: { chatId: string } }) {
|
||||
</div>
|
||||
|
||||
<div className="flex relative bg-background text-default overflow-hidden pt-16 h-screen">
|
||||
<SharedChatDisplay chatSession={chatSession} persona={persona!} />
|
||||
<SharedChatDisplay chatSession={chatSession} persona={persona} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -168,13 +168,10 @@ export const SearchSection = ({
|
||||
});
|
||||
|
||||
const searchParams = useSearchParams();
|
||||
const existingSearchIdRaw = searchParams.get("searchId");
|
||||
const existingSearchessionId = existingSearchIdRaw
|
||||
? parseInt(existingSearchIdRaw)
|
||||
: null;
|
||||
const existingSearchessionId = searchParams.get("searchId");
|
||||
|
||||
useEffect(() => {
|
||||
if (existingSearchIdRaw == null) {
|
||||
if (existingSearchessionId == null) {
|
||||
return;
|
||||
}
|
||||
function extractFirstMessageByType(
|
||||
@ -207,7 +204,7 @@ export const SearchSection = ({
|
||||
quotes: null,
|
||||
selectedDocIndices: null,
|
||||
error: null,
|
||||
messageId: existingSearchIdRaw ? parseInt(existingSearchIdRaw) : null,
|
||||
messageId: searchSession.messages[0].message_id,
|
||||
suggestedFlowType: null,
|
||||
additional_relevance: undefined,
|
||||
};
|
||||
@ -219,7 +216,7 @@ export const SearchSection = ({
|
||||
}
|
||||
}
|
||||
initialSessionFetch();
|
||||
}, [existingSearchessionId, existingSearchIdRaw]);
|
||||
}, [existingSearchessionId]);
|
||||
|
||||
// Overrides for default behavior that only last a single query
|
||||
const [defaultOverrides, setDefaultOverrides] =
|
||||
@ -328,7 +325,7 @@ export const SearchSection = ({
|
||||
};
|
||||
const updateMessageAndThreadId = (
|
||||
messageId: number,
|
||||
chat_session_id: number
|
||||
chat_session_id: string
|
||||
) => {
|
||||
setSearchResponse((prevState) => ({
|
||||
...(prevState || initialSearchResponse),
|
||||
|
@ -136,8 +136,10 @@ export async function fetchChatData(searchParams: {
|
||||
);
|
||||
}
|
||||
|
||||
// Larger ID -> created later
|
||||
chatSessions.sort((a, b) => (a.id > b.id ? -1 : 1));
|
||||
chatSessions.sort(
|
||||
(a, b) =>
|
||||
new Date(b.time_created).getTime() - new Date(a.time_created).getTime()
|
||||
);
|
||||
|
||||
let documentSets: DocumentSet[] = [];
|
||||
if (documentSetsResponse?.ok) {
|
||||
|
@ -152,7 +152,7 @@ export interface SearchRequestArgs {
|
||||
updateError: (error: string) => void;
|
||||
updateMessageAndThreadId: (
|
||||
messageId: number,
|
||||
chat_session_id: number
|
||||
chat_session_id: string
|
||||
) => void;
|
||||
finishedSearching: () => void;
|
||||
updateComments: (comments: any) => void;
|
||||
|
Loading…
x
Reference in New Issue
Block a user