From 5b25563c0a1d17f0b61511ccd18e3a2109650097 Mon Sep 17 00:00:00 2001 From: qixinbo Date: Sun, 15 Mar 2026 18:25:38 +0800 Subject: [PATCH] optimize: session recoginze file --- backend/main.py | 21 ++++++- frontend/src/components/ChatInterface.tsx | 68 ++++++++++++++++++++--- 2 files changed, 80 insertions(+), 9 deletions(-) diff --git a/backend/main.py b/backend/main.py index 82b53c7..208c36c 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1,10 +1,11 @@ -from typing import List, Optional +from typing import Any, Dict, List, Optional from fastapi import FastAPI, HTTPException from fastapi.responses import StreamingResponse from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel import asyncio import json +from datetime import datetime from app.api import upload, llm, skills, users from app.connectors.postgres import postgres_connector @@ -78,6 +79,10 @@ class SessionAliasUpdateRequest(BaseModel): archived: Optional[bool] = None +class SessionFileContextUpdateRequest(BaseModel): + active_data_file: Optional[Dict[str, Any]] = None + + def _build_sql_chart_text(nl2sql_result: NL2SQLResponse) -> str: chart = nl2sql_result.chart can_visualize = bool(chart and chart.can_visualize and chart.chart_spec) @@ -245,6 +250,20 @@ def update_session(session_id: str, payload: SessionAliasUpdateRequest): ) return {"status": "success", **updated} + +@app.put("/nanobot/sessions/{session_id}/context-file") +def update_session_context_file(session_id: str, payload: SessionFileContextUpdateRequest): + if not nanobot_service.agent: + raise HTTPException(status_code=400, detail="Nanobot not running") + session = nanobot_service.agent.sessions.get_or_create(session_id) + if payload.active_data_file is None: + session.metadata.pop("active_data_file", None) + else: + session.metadata["active_data_file"] = payload.active_data_file + session.updated_at = datetime.now() + nanobot_service.agent.sessions.save(session) + return {"status": "success", "metadata": session.metadata} + @app.post("/api/v1/agent/nl2sql", response_model=NL2SQLResponse) async def run_nl2sql(request: NL2SQLRequest): result = await process_nl2sql(request) diff --git a/frontend/src/components/ChatInterface.tsx b/frontend/src/components/ChatInterface.tsx index bffe873..b14f897 100644 --- a/frontend/src/components/ChatInterface.tsx +++ b/frontend/src/components/ChatInterface.tsx @@ -39,8 +39,19 @@ interface ModelConfig { is_active: boolean; } +interface DataFileContext { + filename: string; + url: string; + columns?: string[]; + summary?: string; +} + interface SessionData { key: string; + metadata?: { + active_data_file?: DataFileContext | null; + [key: string]: any; + }; messages: Array<{ role: string; content: string; @@ -67,8 +78,8 @@ export function ChatInterface() { const activeSessionKey = queryParams.get("session") || "api:default"; // File upload state - const [attachedFile, setAttachedFile] = useState<{ filename: string; url: string; columns?: string[]; summary?: string } | null>(null); - const [activeDataFile, setActiveDataFile] = useState<{ filename: string; url: string; columns?: string[]; summary?: string } | null>(null); + const [attachedFile, setAttachedFile] = useState(null); + const [activeDataFile, setActiveDataFile] = useState(null); const [isUploading, setIsUploading] = useState(false); const fileInputRef = useRef(null); @@ -76,6 +87,16 @@ export function ChatInterface() { fetchModels(); }, []); + const syncSessionFileContext = async (file: DataFileContext | null) => { + try { + await api.put(`/nanobot/sessions/${encodeURIComponent(activeSessionKey)}/context-file`, { + active_data_file: file, + }); + } catch (e) { + console.error("Failed to sync session file context", e); + } + }; + useEffect(() => { const fetchSessionData = async () => { setIsLoading(true); @@ -92,9 +113,19 @@ export function ChatInterface() { } else { setMessages([]); } + const restoredFile = data.metadata?.active_data_file || null; + setActiveDataFile(restoredFile); + setAttachedFile(null); + if (restoredFile) { + setSelectedDataSource("upload-main"); + } else if (selectedDataSource.startsWith("upload")) { + setSelectedDataSource("postgres-main"); + } } catch (e) { console.error("Failed to fetch session messages", e); setMessages([]); + setActiveDataFile(null); + setAttachedFile(null); } finally { setIsLoading(false); } @@ -179,6 +210,7 @@ export function ChatInterface() { setAttachedFile(uploadedFile); setActiveDataFile(uploadedFile); setSelectedDataSource("upload-main"); + await syncSessionFileContext(uploadedFile); } catch (error) { console.error("File upload error:", error); // Could show a toast notification here @@ -477,15 +509,25 @@ export function ChatInterface() { {/* Input Area */}
- {attachedFile && ( + {activeDataFile && (
- {attachedFile.filename} + {activeDataFile.filename}
-
@@ -609,13 +651,23 @@ export function ChatInterface() {
- {attachedFile && ( + {activeDataFile && (
- {attachedFile.filename} + {activeDataFile.filename}
-