File size: 4,050 Bytes
918426a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks, Request, UploadFile, File, Form, Query
from typing import List, Dict, Any, Optional

from ...core.neo4j_store import Neo4jStore
from ...retrieval.agent import AgentRetrievalSystem
from ...ingestion.pipeline import IngestionPipeline
from ...config import settings
from ...api.models import *
from ...api.auth import get_current_user, User
import redis
from ..dependencies import get_graph_store, get_retrieval_agent, get_ingestion_pipeline, get_redis_client

router = APIRouter()

from ...core.storage import get_storage
storage = get_storage()

@router.get("/api/conversations", response_model=ConversationListResponse, tags=["Memory"])
async def list_conversations(request: Request, current_user: User = Depends(get_current_user)):
    """List all conversation threads for current user"""
    query = """
    MATCH (u:User {username: $username})-[:HAS_CONVERSATION]->(c:Conversation)
    RETURN c.id as id, c.title as title, c.created_at as created_at, c.updated_at as updated_at
    ORDER BY c.updated_at DESC
    """
    results = await request.app.state.graph_store.execute_query(query, {"username": current_user.username})
    
    convs = []
    for r in results:
        convs.append(Conversation(
            id=r["id"],
            title=r["title"],
            created_at=r.get("created_at", datetime.now().isoformat()),
            updated_at=r.get("updated_at", datetime.now().isoformat())
        ))
    return ConversationListResponse(conversations=convs)



@router.get("/api/conversations/{conversation_id}", response_model=Conversation, tags=["Memory"])
async def get_conversation(request: Request, 
    conversation_id: str,
    current_user: User = Depends(get_current_user)
):
    """Get a specific conversation thread and its messages"""
    query = """
    MATCH (u:User {username: $username})-[:HAS_CONVERSATION]->(c:Conversation {id: $conversation_id})
    OPTIONAL MATCH (c)-[:HAS_MESSAGE]->(m:Message)
    RETURN c.id as id, c.title as title, c.created_at as created_at, c.updated_at as updated_at,
           m.id as msg_id, m.role as role, m.content as content, 
           m.reasoning as reasoning_str, m.sources as sources_str, m.created_at as msg_created_at
    ORDER BY m.created_at ASC
    """
    results = await request.app.state.graph_store.execute_query(query, {
        "username": current_user.username,
        "conversation_id": conversation_id
    })
    
    if not results:
        raise HTTPException(status_code=404, detail="Conversation not found")
        
    c_info = results[0]
    messages = []
    import json
    for r in results:
        if r.get("msg_id"):
            reasoning = json.loads(r["reasoning_str"]) if r.get("reasoning_str") else []
            sources = json.loads(r["sources_str"]) if r.get("sources_str") else []
            messages.append(Message(
                id=r["msg_id"],
                role=r["role"],
                content=r["content"],
                reasoning=reasoning,
                sources=sources,
                created_at=r.get("msg_created_at", "")
            ))
            
    return Conversation(
        id=c_info["id"],
        title=c_info["title"],
        created_at=c_info.get("created_at", ""),
        updated_at=c_info.get("updated_at", ""),
        messages=messages
    )



@router.delete("/api/conversations/{conversation_id}", tags=["Memory"])
async def delete_conversation(request: Request, 
    conversation_id: str,
    current_user: User = Depends(get_current_user)
):
    """Delete a conversation thread"""
    query = """
    MATCH (u:User {username: $username})-[:HAS_CONVERSATION]->(c:Conversation {id: $conversation_id})
    OPTIONAL MATCH (c)-[:HAS_MESSAGE]->(m:Message)
    DETACH DELETE c, m
    """
    await request.app.state.graph_store.execute_query(query, {
        "username": current_user.username,
        "conversation_id": conversation_id
    })
    return {"status": "deleted", "conversation_id": conversation_id}


# Query Endpoints