55 * Uses the shared axios instance which should be configured with auth interceptors
66 * by the app at startup.
77 *
8+ * Migrated from deprecated `/tracing/*` endpoints to canonical `/traces/*` and
9+ * `/spans/*` endpoints (see #4492).
10+ *
811 * @example
912 * ```typescript
1013 * import { fetchAllPreviewTraces, fetchPreviewTrace } from '@agenta/entities/trace'
1114 *
12- * const spans = await fetchAllPreviewTraces({ size: 100, focus: 'span' }, appId)
15+ * const spans = await fetchAllPreviewTraces({ size: 100 }, appId, projectId )
1316 * const trace = await fetchPreviewTrace(traceId, projectId)
1417 * ```
1518 */
@@ -19,18 +22,24 @@ import {axios, getAgentaApiUrl} from "@agenta/shared/api"
1922// See testcase/api/api.ts for rationale — the shared barrel pulls in CSS deps.
2023import { safeParseWithLogging } from "../../shared/utils/zodSchema"
2124import {
25+ sessionIdsResponseSchema ,
2226 spansResponseSchema ,
23- tracesResponseSchema ,
27+ traceIdResponseSchema ,
28+ traceResponseSchema ,
29+ type SessionIdsResponse ,
2430 type SpansResponse ,
25- type TracesResponse ,
31+ type TraceIdResponse ,
32+ type TraceResponse ,
2633} from "../core"
2734
2835/**
29- * Query parameters for fetching traces/spans
36+ * Query parameters for fetching spans.
37+ *
38+ * Note: `focus` is no longer accepted — `POST /spans/query` always returns
39+ * flat spans. For trace-tree views, use `fetchPreviewTrace` instead.
3040 */
3141export interface TraceQueryParams {
3242 size ?: number
33- focus ?: "trace" | "span" | "chat"
3443 format ?: string
3544 filter ?: string | Record < string , unknown >
3645 oldest ?: string
@@ -40,26 +49,27 @@ export interface TraceQueryParams {
4049}
4150
4251/**
43- * Fetch preview traces/spans from the API.
52+ * Fetch spans from the API (flat list).
53+ *
54+ * Calls `POST /spans/query` which always returns a flat `SpansResponse`.
55+ * For trace-tree views, use `fetchPreviewTrace` instead.
4456 *
4557 * @param params - Query parameters for filtering
4658 * @param appId - Application ID (optional)
4759 * @param projectId - Project ID (required)
48- * @returns API response with spans (validated)
60+ * @returns Validated SpansResponse
4961 */
5062export async function fetchAllPreviewTraces (
5163 params : TraceQueryParams = { } ,
5264 appId : string ,
5365 projectId : string ,
54- ) : Promise < SpansResponse | TracesResponse | null > {
66+ ) : Promise < SpansResponse | null > {
5567 const baseUrl = getAgentaApiUrl ( )
5668
57- // Build query parameters
5869 const queryParams = new URLSearchParams ( )
5970 if ( projectId ) queryParams . set ( "project_id" , projectId )
6071 if ( appId ) queryParams . set ( "application_id" , appId )
6172
62- // Build request payload
6373 const payload : Record < string , unknown > = { }
6474 Object . entries ( params ) . forEach ( ( [ key , value ] ) => {
6575 if ( value === undefined || value === null ) return
@@ -71,68 +81,71 @@ export async function fetchAllPreviewTraces(
7181 } catch {
7282 payload . filter = value
7383 }
84+ } else if ( key === "focus" ) {
85+ // `focus` is no longer accepted by POST /spans/query — skip it.
86+ return
7487 } else {
7588 payload [ key ] = value
7689 }
7790 } )
7891
7992 const response = await axios . post (
80- `${ baseUrl } /tracing/ spans/query?${ queryParams . toString ( ) } ` ,
93+ `${ baseUrl } /spans/query?${ queryParams . toString ( ) } ` ,
8194 payload ,
8295 )
8396
84- // Try parsing as SpansResponse first (spans array format)
85- const spansResult = spansResponseSchema . safeParse ( response . data )
86- if ( spansResult . success ) {
87- return spansResult . data
88- }
89-
90- // Fall back to TracesResponse (traces record format)
91- return safeParseWithLogging ( tracesResponseSchema , response . data , "[fetchAllPreviewTraces]" )
97+ return safeParseWithLogging ( spansResponseSchema , response . data , "[fetchAllPreviewTraces]" )
9298}
9399
94100/**
95- * Fetch a single trace by ID.
101+ * Fetch a single trace by ID (with trace-tree structure).
102+ *
103+ * Calls `GET /traces/{id}` which returns a `TraceResponse` with a single
104+ * `trace` object containing `trace_id` and a `spans` record.
96105 *
97106 * @param traceId - Trace ID to fetch
98107 * @param projectId - Project ID
99- * @returns Trace span data (validated)
108+ * @returns Validated TraceResponse
100109 */
101110export async function fetchPreviewTrace (
102111 traceId : string ,
103112 projectId : string ,
104- ) : Promise < TracesResponse | null > {
113+ ) : Promise < TraceResponse | null > {
105114 const baseUrl = getAgentaApiUrl ( )
106115
107116 const queryParams = new URLSearchParams ( )
108117 if ( projectId ) queryParams . set ( "project_id" , projectId )
109118
110119 const response = await axios . get (
111- `${ baseUrl } /tracing/ traces/${ traceId } ?${ queryParams . toString ( ) } ` ,
120+ `${ baseUrl } /traces/${ traceId } ?${ queryParams . toString ( ) } ` ,
112121 )
113122
114- // API returns TracesResponse format with count and traces record
115- return safeParseWithLogging ( tracesResponseSchema , response . data , "[fetchPreviewTrace]" )
123+ return safeParseWithLogging ( traceResponseSchema , response . data , "[fetchPreviewTrace]" )
116124}
117125
118126/**
119127 * Delete a trace by ID.
120128 *
129+ * Calls `DELETE /traces/{id}`.
130+ *
121131 * @param traceId - Trace ID to delete
122132 * @param projectId - Project ID
123- * @returns Delete response
133+ * @returns Validated TraceIdResponse
124134 */
125- export async function deletePreviewTrace ( traceId : string , projectId : string ) : Promise < unknown > {
135+ export async function deletePreviewTrace (
136+ traceId : string ,
137+ projectId : string ,
138+ ) : Promise < TraceIdResponse | null > {
126139 const baseUrl = getAgentaApiUrl ( )
127140
128141 const queryParams = new URLSearchParams ( )
129142 if ( projectId ) queryParams . set ( "project_id" , projectId )
130143
131144 const response = await axios . delete (
132- `${ baseUrl } /tracing/ traces/${ traceId } ?${ queryParams . toString ( ) } ` ,
145+ `${ baseUrl } /traces/${ traceId } ?${ queryParams . toString ( ) } ` ,
133146 )
134147
135- return response . data
148+ return safeParseWithLogging ( traceIdResponseSchema , response . data , "[deletePreviewTrace]" )
136149}
137150
138151/**
@@ -155,14 +168,16 @@ export interface SessionQueryParams {
155168/**
156169 * Fetch sessions with filtering and pagination.
157170 *
171+ * Calls `POST /spans/sessions/query`.
172+ *
158173 * @param params - Session query parameters
159174 * @param projectId - Project ID
160- * @returns Session list response
175+ * @returns Validated SessionIdsResponse
161176 */
162177export async function fetchSessions (
163178 params : SessionQueryParams ,
164179 projectId : string ,
165- ) : Promise < unknown > {
180+ ) : Promise < SessionIdsResponse | null > {
166181 const baseUrl = getAgentaApiUrl ( )
167182
168183 const queryParams = new URLSearchParams ( )
@@ -171,11 +186,8 @@ export async function fetchSessions(
171186
172187 const payload : Record < string , unknown > = { }
173188
174- // Initialize windowing if it doesn't exist but we have a cursor
175189 if ( params . windowing || params . cursor ) {
176190 payload . windowing = { ...( params . windowing || { } ) }
177-
178- // If cursor is provided, it goes into windowing.next
179191 if ( params . cursor ) {
180192 ; ( payload . windowing as Record < string , unknown > ) . next = params . cursor
181193 }
@@ -185,15 +197,14 @@ export async function fetchSessions(
185197 payload . filter = params . filter
186198 }
187199
188- // Add realtime parameter (true = latest/unstable, false/undefined = all/stable)
189200 if ( params . realtime !== undefined ) {
190201 payload . realtime = params . realtime
191202 }
192203
193204 const response = await axios . post (
194- `${ baseUrl } /tracing /sessions/query?${ queryParams . toString ( ) } ` ,
205+ `${ baseUrl } /spans /sessions/query?${ queryParams . toString ( ) } ` ,
195206 payload ,
196207 )
197208
198- return response . data
209+ return safeParseWithLogging ( sessionIdsResponseSchema , response . data , "[fetchSessions]" )
199210}
0 commit comments