import { useQuery } from '@tanstack/react-query' import type { UseQueryResult } from '@tanstack/react-query' import { apiFetch } from '../../api/client' import { adaptSession } from '../../api/adapters' import type { Session, SessionDTO } from '../../api/adapters' export interface TurnDTO { turn_id: string seq: number role: 'user' | 'assistant' | 'tool' | 'system' timestamp: number content: string model?: string tokens_in?: number tokens_out?: number cost_usd?: number tool_calls?: unknown metadata?: unknown } export interface Turn { i: number role: 'user' | 'assistant' | 'tool' body: string model?: string tokensIn?: number tokensOut?: number toolName?: string toolKind?: 'call' | 'result' } export interface SessionWithTurnsDTO extends SessionDTO { turns: TurnDTO[] } export interface SessionWithTurns extends Omit { turns: Turn[] } function extractToolCalls( raw: unknown, ): { toolName?: string; toolKind?: 'call' | 'result' } { if (raw == null || typeof raw !== 'object') { return {} } const obj = raw as Record const name = typeof obj['name'] === 'string' ? obj['name'] : undefined const kind = obj['kind'] === 'call' || obj['kind'] === 'result' ? (obj['kind'] as 'call' | 'result') : undefined if (name == null && kind == null) { return {} } return { toolName: name, toolKind: kind } } export function adaptTurn(d: TurnDTO): Turn { const role: 'user' | 'assistant' | 'tool' = d.role === 'system' ? 'assistant' : d.role const { toolName, toolKind } = extractToolCalls(d.tool_calls) return { i: d.seq, role, body: d.content, model: d.model, tokensIn: d.tokens_in, tokensOut: d.tokens_out, toolName, toolKind, } } export function useSession( tool: string, host: string, id: string, ): UseQueryResult { // id is the composite `tool/host/session_id` from Session.id. // Extract only the session_id tail for the API URL. const rawSessionId = id.split('/').slice(2).join('/') return useQuery({ queryKey: ['session', tool, host, id], queryFn: async () => { const dto = await apiFetch( `/api/v1/sessions/${tool}/${host}/${rawSessionId}`, ) const session = adaptSession(dto) return { ...session, turns: dto.turns.map(adaptTurn) } }, }) }