diff --git a/web/oss/src/components/SharedDrawers/SessionDrawer/components/SessionDrawerContent.tsx b/web/oss/src/components/SharedDrawers/SessionDrawer/components/SessionDrawerContent.tsx index 2bb7320975..606c3c05b5 100644 --- a/web/oss/src/components/SharedDrawers/SessionDrawer/components/SessionDrawerContent.tsx +++ b/web/oss/src/components/SharedDrawers/SessionDrawer/components/SessionDrawerContent.tsx @@ -23,7 +23,10 @@ interface TraceDrawerContentProps { } const SessionDrawerContent = ({onClose, onToggleWidth, isExpanded}: TraceDrawerContentProps) => { - const [selected, setSelected] = useState("") + // Default-select the "Session" root node so the tree opens with a selection + // instead of nothing highlighted. The root node's key is always "root", and + // selecting it is a no-op in handleSelect (it early-returns for "root"). + const [selected, setSelected] = useState("root") const {isLoading} = useSessionDrawer() if (isLoading) { return ( diff --git a/web/oss/src/components/pages/observability/components/SessionsTable/components/Cells/SessionIdCell.tsx b/web/oss/src/components/pages/observability/components/SessionsTable/components/Cells/SessionIdCell.tsx index 0fcd143913..be8dc956e3 100644 --- a/web/oss/src/components/pages/observability/components/SessionsTable/components/Cells/SessionIdCell.tsx +++ b/web/oss/src/components/pages/observability/components/SessionsTable/components/Cells/SessionIdCell.tsx @@ -4,7 +4,10 @@ import {Tag} from "antd" export const SessionIdCell = ({sessionId}: {sessionId: string}) => { return ( - + # {sessionId} diff --git a/web/oss/src/components/pages/observability/components/SessionsTable/index.tsx b/web/oss/src/components/pages/observability/components/SessionsTable/index.tsx index 0d15650646..188b362b27 100644 --- a/web/oss/src/components/pages/observability/components/SessionsTable/index.tsx +++ b/web/oss/src/components/pages/observability/components/SessionsTable/index.tsx @@ -2,7 +2,7 @@ import {useCallback, useEffect, useMemo, useState} from "react" import {InfiniteVirtualTableFeatureShell} from "@agenta/ui/table" import type {TableFeaturePagination, TableScopeConfig} from "@agenta/ui/table" -import {useAtomValue, useSetAtom} from "jotai" +import {useAtomValue, useSetAtom, useStore} from "jotai" import dynamic from "next/dynamic" import {SessionDrawer} from "@/oss/components/SharedDrawers/SessionDrawer" @@ -49,6 +49,14 @@ const SessionsTable: React.FC = () => { resetSessionPages, } = useSessions() + // The per-session cells (Traces count, First input, metrics, …) read their + // data from page-level atoms keyed by session id (e.g. `sessionsSpansAtom`). + // Without this, the table mounts its rows inside an isolated Jotai store + // (`useIsolatedStore` when no `store` is passed), where those atoms are empty + // — so every cell renders 0/"-" even though the data is loaded in the page + // store. Sharing the page store lets the cells resolve the real data. + const store = useStore() + const isNewUser = useAtomValue(isNewUserAtom) const onboardingStorageUserId = useAtomValue(onboardingStorageUserIdAtom) const openDrawer = useSetAtom(openSessionDrawerWithUrlAtom) @@ -111,7 +119,7 @@ const SessionsTable: React.FC = () => { const isEmptyState = sessionIds.length === 0 && !isLoading return ( -
+
{ ) : ( + store={store} tableScope={tableScope} columns={columns} rowKey="session_id" pagination={pagination} - autoHeight={false} resizableColumns enableExport={false} useSettingsDropdown={false} diff --git a/web/oss/src/state/newObservability/atoms/queries.ts b/web/oss/src/state/newObservability/atoms/queries.ts index 29b74ee98c..c63e3c1d85 100644 --- a/web/oss/src/state/newObservability/atoms/queries.ts +++ b/web/oss/src/state/newObservability/atoms/queries.ts @@ -509,15 +509,18 @@ export const sessionTraceCountAtomFamily = atomFamily((sessionId: string) => }), ) -// Sorted traces are required for time-based metrics (Start/End/Duration) -// We memoize this to avoid re-sorting for every time-related cell +// Sorted traces are required for time-based metrics (Start/End/Duration) and for +// the First input / Last output cells. Sort by `start_time` (falling back to +// `created_at`) to match the Session drawer's tree ordering +// (SessionTree sorts its "Trace N" nodes by start_time). Sorting by a different +// key here made the table's first/last trace diverge from the drawer's. const sessionSortedTracesAtomFamily = atomFamily((sessionId: string) => atom((get) => { const traces = get(sessionTracesAtomFamily(sessionId)) if (!traces.length) return [] - return [...traces].sort( - (a, b) => new Date(a.created_at || 0).getTime() - new Date(b.created_at || 0).getTime(), - ) + const sortKey = (t: (typeof traces)[number]) => + new Date(t.start_time || t.created_at || 0).getTime() + return [...traces].sort((a, b) => sortKey(a) - sortKey(b)) }), )