feat: reset bot session context while retaining monitoring history

This commit is contained in:
Hyu
2026-10-10 22:35:27 +08:00
parent b8a7649ac2
commit 1c70218383
20 changed files with 408 additions and 5 deletions
@@ -1,3 +1,6 @@
import { useCurrentWorkspace } from '@/app/infra/http';
import { Button } from '@/components/ui/button';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog';
import LoadErrorState from '@/components/LoadErrorState';
import React, {
useState,
@@ -13,6 +16,7 @@ import { httpClient } from '@/app/infra/http/HttpClient';
import { ScrollArea } from '@/components/ui/scroll-area';
import { cn } from '@/lib/utils';
import {
RotateCcw,
Ban,
Bot,
Copy,
@@ -143,6 +147,23 @@ const BotSessionMonitor = forwardRef<
BotSessionMonitorProps
>(function BotSessionMonitor({ botId }, ref) {
const { t } = useTranslation();
const workspace = useCurrentWorkspace();
const canReset = workspace?.permissions.includes('resource.manage') ?? false;
const [resetTarget, setResetTarget] = useState<string | null>(null);
const [resetting, setResetting] = useState(false);
const resetContext = async () => {
if (!resetTarget || resetting) return;
setResetting(true);
try {
await httpClient.resetSessionContext(botId, resetTarget);
toast.success(t('bots.sessionMonitor.resetSuccess'));
setResetTarget(null);
} catch {
toast.error(t('bots.sessionMonitor.resetError'));
} finally {
setResetting(false);
}
};
const [sessions, setSessions] = useState<SessionInfo[]>([]);
const [sessionTotal, setSessionTotal] = useState(0);
const [sessionPage, setSessionPage] = useState(0);
@@ -686,7 +707,7 @@ const BotSessionMonitor = forwardRef<
{/* Left Panel: Session List */}
<div className="max-h-48 md:max-h-none md:w-60 flex-shrink-0 border-b md:border-b-0 md:border-r flex flex-col min-h-0">
{/* Admin header */}
<div className="px-2 py-1.5 border-b shrink-0 flex items-center justify-between">
<div className="px-2 py-1.5 border-b shrink-0 flex items-center justify-between gap-4">
<button
type="button"
className="inline-flex items-center gap-1.5 text-sm font-medium hover:text-foreground transition-colors"
@@ -860,7 +881,7 @@ const BotSessionMonitor = forwardRef<
selectedSession?.user_id ||
selectedSessionId.slice(0, 20)}
</div>
<div className="flex items-center gap-1.5 text-xs text-muted-foreground mt-0.5">
<div className="flex flex-wrap items-center gap-1.5 text-xs text-muted-foreground mt-0.5">
{parseSessionType(selectedSessionId) && (
<span>{parseSessionType(selectedSessionId)}</span>
)}
@@ -923,6 +944,13 @@ const BotSessionMonitor = forwardRef<
)}
</div>
</div>
{canReset && (
<Button variant="outline" size="sm" className="h-7 shrink-0 gap-1.5"
disabled={resetting} onClick={() => setResetTarget(selectedSessionId)}>
<RotateCcw className="size-3.5" />
{t('bots.sessionMonitor.resetContext')}
</Button>
)}
</div>
{/* Messages Area */}
@@ -1194,6 +1222,21 @@ const BotSessionMonitor = forwardRef<
</div>
</div>
<Dialog open={resetTarget !== null} onOpenChange={(open) => { if (!open && !resetting) setResetTarget(null); }}>
<DialogContent>
<DialogHeader>
<DialogTitle>{t('bots.sessionMonitor.resetContext')}</DialogTitle>
<DialogDescription>{t('bots.sessionMonitor.resetDescription')}</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline" disabled={resetting} onClick={() => setResetTarget(null)}>{t('common.cancel')}</Button>
<Button disabled={resetting} onClick={resetContext}>
<RotateCcw className={cn('size-4', resetting && 'animate-spin motion-reduce:animate-none')} />
{t('bots.sessionMonitor.resetContext')}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<BotAdminsDialog
botId={botId}
open={adminsDialogOpen}
+6
View File
@@ -822,6 +822,12 @@ export class BackendClient extends BaseHttpClient {
return this.get(`/api/v1/monitoring/sessions?${queryParams.toString()}`);
}
public resetSessionContext(botId: string, sessionId: string): Promise<{ reset: boolean }> {
return this.post('/api/v1/monitoring/sessions/reset-context', {
bot_id: botId, session_id: sessionId,
});
}
public getSessionAnalysis<T>(
sessionId: string,
botId: string,
+5
View File
@@ -1172,6 +1172,11 @@ const enUS = {
imagesAttached: 'image(s) attached',
noLogs: 'No logs yet',
sessionMonitor: {
resetContext: "Reset context",
resetDescription: "New messages will start with an empty context. Monitoring history is kept; files and long-term memory are unchanged. Wait for active tasks to finish before resetting.",
resetSuccess: "Context reset. New messages will start a fresh conversation.",
resetError: "Could not reset context. Wait for active tasks to finish and try again.",
title: 'Sessions',
sessions: 'Sessions',
noSessions: 'No sessions found',
+5
View File
@@ -1194,6 +1194,11 @@ const esES = {
imagesAttached: 'imagen(es) adjunta(s)',
noLogs: 'Aún no hay registros',
sessionMonitor: {
resetContext: "Restablecer contexto",
resetDescription: "Los mensajes nuevos comenzarán sin contexto previo. Se conservan el historial de monitoreo, los archivos y la memoria a largo plazo. Espere a que terminen las tareas activas.",
resetSuccess: "Contexto restablecido.",
resetError: "No se pudo restablecer. Espere a que terminen las tareas activas y vuelva a intentarlo.",
title: 'Sesiones',
sessions: 'Sesiones',
noSessions: 'No se encontraron sesiones',
+5
View File
@@ -1182,6 +1182,11 @@ const jaJP = {
imagesAttached: '枚の画像が添付されています',
noLogs: 'ログはまだありません',
sessionMonitor: {
resetContext: "コンテキストをリセット",
resetDescription: "新しいメッセージは空のコンテキストから開始します。監視履歴、ファイル、長期記憶は保持されます。実行中のタスクが完了してからリセットしてください。",
resetSuccess: "コンテキストをリセットしました。",
resetError: "リセットできませんでした。実行中のタスクが完了してから再試行してください。",
title: 'セッション監視',
sessions: 'セッション一覧',
noSessions: 'セッションが見つかりません',
+5
View File
@@ -1192,6 +1192,11 @@ const ruRU = {
imagesAttached: 'изображений прикреплено',
noLogs: 'Журналов пока нет',
sessionMonitor: {
resetContext: "Сбросить контекст",
resetDescription: "Новые сообщения начнутся с пустого контекста. История мониторинга, файлы и долговременная память сохранятся. Дождитесь завершения активных задач.",
resetSuccess: "Контекст сброшен.",
resetError: "Не удалось сбросить контекст. Дождитесь завершения активных задач и повторите попытку.",
title: 'Сессии',
sessions: 'Сессии',
noSessions: 'Сессии не найдены',
+5
View File
@@ -1152,6 +1152,11 @@ const thTH = {
imagesAttached: 'รูปภาพที่แนบ',
noLogs: 'ยังไม่มีบันทึก',
sessionMonitor: {
resetContext: "รีเซ็ตบริบท",
resetDescription: "ข้อความใหม่จะเริ่มด้วยบริบทว่าง ประวัติการตรวจสอบ ไฟล์ และความจำระยะยาวจะยังคงอยู่ โปรดรอให้งานที่กำลังทำอยู่เสร็จก่อน",
resetSuccess: "รีเซ็ตบริบทแล้ว",
resetError: "รีเซ็ตไม่สำเร็จ โปรดรอให้งานที่กำลังทำอยู่เสร็จแล้วลองอีกครั้ง",
title: 'เซสชัน',
sessions: 'เซสชัน',
noSessions: 'ไม่พบเซสชัน',
+5
View File
@@ -1170,6 +1170,11 @@ const viVN = {
imagesAttached: 'hình ảnh đính kèm',
noLogs: 'Chưa có nhật ký',
sessionMonitor: {
resetContext: "Đặt lại ngữ cảnh",
resetDescription: "Tin nhắn mới sẽ bắt đầu với ngữ cảnh trống. Lịch sử giám sát, tệp và bộ nhớ dài hạn được giữ lại. Hãy đợi các tác vụ đang chạy hoàn tất.",
resetSuccess: "Đã đặt lại ngữ cảnh.",
resetError: "Không thể đặt lại. Hãy đợi các tác vụ đang chạy hoàn tất rồi thử lại.",
title: 'Phiên',
sessions: 'Phiên',
noSessions: 'Không tìm thấy phiên nào',
+5
View File
@@ -1108,6 +1108,11 @@ const zhHans = {
imagesAttached: '张图片',
noLogs: '暂无日志',
sessionMonitor: {
resetContext: "重置上下文",
resetDescription: "重置后,新消息将从空上下文开始。监控历史会保留,文件和长期记忆不受影响。请等待当前任务结束后再重置。",
resetSuccess: "上下文已重置,新消息将开启新的对话。",
resetError: "重置失败,请等待当前任务结束后重试。",
title: '会话监控',
sessions: '会话列表',
noSessions: '暂无会话',
+5
View File
@@ -1107,6 +1107,11 @@ const zhHant = {
imagesAttached: '張圖片已附加',
noLogs: '暫無日誌',
sessionMonitor: {
resetContext: "重設上下文",
resetDescription: "重設後,新訊息將從空上下文開始。監控歷史會保留,檔案和長期記憶不受影響。請等待目前任務結束後再重設。",
resetSuccess: "上下文已重設,新訊息將開始新的對話。",
resetError: "重設失敗,請等待目前任務結束後重試。",
title: '會話監控',
sessions: '會話列表',
noSessions: '暫無會話',