Session Management
Build conversation history UI with session listing and loading.
Manage conversation history, allowing users to view their past conversations and continue where they left off.
Overview
Lens OS automatically saves conversations. You can use the Sessions API to let users:
- View a list of past conversations
- Load and continue previous conversations
- Start new conversations
History Sidebar State
State management
interface Session {
id: string;
title: string;
messageCount: number;
created_at: string;
}
const [sessions, setSessions] = useState<Session[]>([]);
const [showHistory, setShowHistory] = useState(false);
const [loadingHistory, setLoadingHistory] = useState(false);Fetch Sessions
Load session list
const loadSessions = async () => {
setLoadingHistory(true);
try {
const res = await fetch("/api/lens/agent/sessions");
if (res.ok) {
const data = await res.json();
if (data.success) {
setSessions(data.sessions);
}
}
} finally {
setLoadingHistory(false);
}
};
// Load when opening sidebar
const toggleHistory = () => {
const opening = !showHistory;
setShowHistory(opening);
if (opening) loadSessions();
};Load Session
Load and restore conversation
const { loadSession, sessionId } = useLensAgent({...});
const handleLoadSession = async (targetId: string) => {
const res = await fetch(`/api/lens/agent/sessions/${targetId}`);
if (!res.ok) return;
const data = await res.json();
if (data.success) {
// Messages may need to be reversed
loadSession(targetId, data.messages.reverse());
setShowHistory(false);
}
};Format Date
Date formatting helper
const formatDate = (dateStr: string, id?: string) => {
let date = new Date(dateStr);
// Fallback: extract timestamp from session ID
if (isNaN(date.getTime()) && id) {
const match = id.match(/^session-(\d+)-/);
if (match) date = new Date(Number(match[1]));
}
if (isNaN(date.getTime())) return "";
const now = new Date();
const diffDays = Math.floor(
(now.getTime() - date.getTime()) / (1000 * 60 * 60 * 24)
);
if (diffDays === 0) return "Today";
if (diffDays === 1) return "Yesterday";
if (diffDays < 7) return `${diffDays} days ago`;
return date.toLocaleDateString("en-US", {
month: "short",
day: "numeric",
});
};UI Implementation
History sidebar
{/* History Button */}
<button onClick={toggleHistory}>
<svg /* icon */ />
History
</button>
{/* Sidebar Backdrop */}
{showHistory && (
<div
className="fixed inset-0 bg-black/20 z-40"
onClick={() => setShowHistory(false)}
/>
)}
{/* Sidebar */}
<div className={`
fixed top-0 left-0 h-full w-72 bg-white shadow-lg z-50
transform transition-transform
${showHistory ? "translate-x-0" : "-translate-x-full"}
`}>
{/* Header */}
<div className="flex items-center justify-between p-4 border-b">
<span className="font-semibold">Conversation History</span>
<button onClick={() => setShowHistory(false)}>✕</button>
</div>
{/* List */}
<div className="overflow-auto h-[calc(100%-60px)]">
{loadingHistory ? (
<div className="p-4 text-center text-gray-400">Loading...</div>
) : sessions.length === 0 ? (
<div className="p-4 text-center text-gray-400">No conversation history</div>
) : (
sessions.map((s) => (
<div
key={s.id}
className={`
p-4 border-b cursor-pointer hover:bg-gray-50
${s.id === sessionId ? "bg-blue-50" : ""}
`}
onClick={() => handleLoadSession(s.id)}
>
<div className="font-medium truncate">
{s.title || "New Conversation"}
</div>
<div className="text-xs text-gray-400 mt-1 flex justify-between">
<span>{formatDate(s.created_at, s.id)}</span>
<span>{s.messageCount} messages</span>
</div>
</div>
))
)}
</div>
</div>New Session
Start new conversation
const { newSession } = useLensAgent({...});
const handleNewSession = () => {
newSession();
// Clear tool cards and other state
setToolCards([]);
};Full Example
Complete implementation
export function LensChat({ userId }: { userId: string }) {
const [showHistory, setShowHistory] = useState(false);
const [sessions, setSessions] = useState<Session[]>([]);
const [loadingHistory, setLoadingHistory] = useState(false);
const {
messages,
sessionId,
loadSession,
newSession,
// ...
} = useLensAgent({ endpoint: "/api/lens/agent/chat", userId });
const loadSessions = async () => {
setLoadingHistory(true);
const res = await fetch("/api/lens/agent/sessions");
const data = await res.json();
if (data.success) setSessions(data.sessions);
setLoadingHistory(false);
};
const toggleHistory = () => {
setShowHistory(!showHistory);
if (!showHistory) loadSessions();
};
const handleLoadSession = async (targetId: string) => {
const res = await fetch(`/api/lens/agent/sessions/${targetId}`);
const data = await res.json();
if (data.success) {
loadSession(targetId, data.messages.reverse());
setShowHistory(false);
}
};
return (
<div className="relative">
{/* Main Chat UI */}
{/* ... */}
{/* History Sidebar */}
{/* ... */}
</div>
);
}Note
Sessions are automatically managed by Lens OS. You don't need to handle session creation or storage manually.