@mastra/react 1.10.0-alpha.1 → 1.10.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/combine-by-ids-CcaZKGT9.js +24 -0
- package/dist/combine-by-ids-CcaZKGT9.js.map +1 -0
- package/dist/combine-by-ids-D_lp6Dvq.cjs +29 -0
- package/dist/combine-by-ids-D_lp6Dvq.cjs.map +1 -0
- package/dist/hooks/datasets/index.cjs +4 -21
- package/dist/hooks/datasets/index.cjs.map +1 -1
- package/dist/hooks/datasets/index.js +2 -19
- package/dist/hooks/datasets/index.js.map +1 -1
- package/dist/hooks/datasets/use-dataset-experiments.d.ts +2 -9
- package/dist/hooks/datasets/use-dataset-experiments.d.ts.map +1 -1
- package/dist/hooks/experiments/index.cjs +73 -0
- package/dist/hooks/experiments/index.cjs.map +1 -1
- package/dist/hooks/experiments/index.d.ts +1 -0
- package/dist/hooks/experiments/index.d.ts.map +1 -1
- package/dist/hooks/experiments/index.js +74 -2
- package/dist/hooks/experiments/index.js.map +1 -1
- package/dist/hooks/experiments/use-experiment-item-usage.d.ts +27 -0
- package/dist/hooks/experiments/use-experiment-item-usage.d.ts.map +1 -0
- package/dist/hooks/shared/combine-by-ids.d.ts +15 -0
- package/dist/hooks/shared/combine-by-ids.d.ts.map +1 -0
- package/dist/hooks/traces/index.cjs +1 -1
- package/dist/hooks/traces/index.js +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
//#region src/hooks/shared/combine-by-ids.ts
|
|
3
|
+
/**
|
|
4
|
+
* Stable `combine` for `useQueries`: keyed on the ids' contents (callers pass a fresh array every
|
|
5
|
+
* render), so TanStack only recombines when a query result actually changes.
|
|
6
|
+
*/
|
|
7
|
+
const useCombineByIds = (ids) => {
|
|
8
|
+
const idsKey = JSON.stringify(ids);
|
|
9
|
+
return useCallback((results) => {
|
|
10
|
+
const data = {};
|
|
11
|
+
JSON.parse(idsKey).forEach((id, index) => {
|
|
12
|
+
data[id] = results[index]?.data;
|
|
13
|
+
});
|
|
14
|
+
return {
|
|
15
|
+
data,
|
|
16
|
+
isLoading: results.some((result) => result.isLoading),
|
|
17
|
+
error: results.find((result) => result.error)?.error ?? null
|
|
18
|
+
};
|
|
19
|
+
}, [idsKey]);
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { useCombineByIds as t };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=combine-by-ids-CcaZKGT9.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combine-by-ids-CcaZKGT9.js","names":[],"sources":["../src/hooks/shared/combine-by-ids.ts"],"sourcesContent":["import type { UseQueryResult } from '@tanstack/react-query';\nimport { useCallback } from 'react';\n\n/** One entry per requested experiment id, in the order the ids were given. */\nexport interface ExperimentQueriesResult<T> {\n data: Record<string, T | undefined>;\n /** True while any experiment has not loaded yet. */\n isLoading: boolean;\n /** First error among the experiments, if any. */\n error: Error | null;\n}\n\n/**\n * Stable `combine` for `useQueries`: keyed on the ids' contents (callers pass a fresh array every\n * render), so TanStack only recombines when a query result actually changes.\n */\nexport const useCombineByIds = <T>(ids: string[]) => {\n const idsKey = JSON.stringify(ids);\n return useCallback(\n (results: Array<UseQueryResult<T, Error>>): ExperimentQueriesResult<T> => {\n const data: Record<string, T | undefined> = {};\n (JSON.parse(idsKey) as string[]).forEach((id, index) => {\n data[id] = results[index]?.data;\n });\n return {\n data,\n isLoading: results.some(result => result.isLoading),\n error: results.find(result => result.error)?.error ?? null,\n };\n },\n [idsKey],\n );\n};\n"],"mappings":";;;;;;AAgBA,MAAa,mBAAsB,QAAkB;CACnD,MAAM,SAAS,KAAK,UAAU,GAAG;CACjC,OAAO,aACJ,YAAyE;EACxE,MAAM,OAAsC,CAAC;EAC7C,KAAM,MAAM,MAAM,CAAC,CAAc,SAAS,IAAI,UAAU;GACtD,KAAK,MAAM,QAAQ,MAAM,EAAE;EAC7B,CAAC;EACD,OAAO;GACL;GACA,WAAW,QAAQ,MAAK,WAAU,OAAO,SAAS;GAClD,OAAO,QAAQ,MAAK,WAAU,OAAO,KAAK,CAAC,EAAE,SAAS;EACxD;CACF,GACA,CAAC,MAAM,CACT;AACF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
let react = require("react");
|
|
2
|
+
//#region src/hooks/shared/combine-by-ids.ts
|
|
3
|
+
/**
|
|
4
|
+
* Stable `combine` for `useQueries`: keyed on the ids' contents (callers pass a fresh array every
|
|
5
|
+
* render), so TanStack only recombines when a query result actually changes.
|
|
6
|
+
*/
|
|
7
|
+
const useCombineByIds = (ids) => {
|
|
8
|
+
const idsKey = JSON.stringify(ids);
|
|
9
|
+
return (0, react.useCallback)((results) => {
|
|
10
|
+
const data = {};
|
|
11
|
+
JSON.parse(idsKey).forEach((id, index) => {
|
|
12
|
+
data[id] = results[index]?.data;
|
|
13
|
+
});
|
|
14
|
+
return {
|
|
15
|
+
data,
|
|
16
|
+
isLoading: results.some((result) => result.isLoading),
|
|
17
|
+
error: results.find((result) => result.error)?.error ?? null
|
|
18
|
+
};
|
|
19
|
+
}, [idsKey]);
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
Object.defineProperty(exports, "useCombineByIds", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get: function() {
|
|
25
|
+
return useCombineByIds;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=combine-by-ids-D_lp6Dvq.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combine-by-ids-D_lp6Dvq.cjs","names":[],"sources":["../src/hooks/shared/combine-by-ids.ts"],"sourcesContent":["import type { UseQueryResult } from '@tanstack/react-query';\nimport { useCallback } from 'react';\n\n/** One entry per requested experiment id, in the order the ids were given. */\nexport interface ExperimentQueriesResult<T> {\n data: Record<string, T | undefined>;\n /** True while any experiment has not loaded yet. */\n isLoading: boolean;\n /** First error among the experiments, if any. */\n error: Error | null;\n}\n\n/**\n * Stable `combine` for `useQueries`: keyed on the ids' contents (callers pass a fresh array every\n * render), so TanStack only recombines when a query result actually changes.\n */\nexport const useCombineByIds = <T>(ids: string[]) => {\n const idsKey = JSON.stringify(ids);\n return useCallback(\n (results: Array<UseQueryResult<T, Error>>): ExperimentQueriesResult<T> => {\n const data: Record<string, T | undefined> = {};\n (JSON.parse(idsKey) as string[]).forEach((id, index) => {\n data[id] = results[index]?.data;\n });\n return {\n data,\n isLoading: results.some(result => result.isLoading),\n error: results.find(result => result.error)?.error ?? null,\n };\n },\n [idsKey],\n );\n};\n"],"mappings":";;;;;;AAgBA,MAAa,mBAAsB,QAAkB;CACnD,MAAM,SAAS,KAAK,UAAU,GAAG;CACjC,QAAA,GAAA,MAAA,YAAA,EACG,YAAyE;EACxE,MAAM,OAAsC,CAAC;EAC7C,KAAM,MAAM,MAAM,CAAC,CAAc,SAAS,IAAI,UAAU;GACtD,KAAK,MAAM,QAAQ,MAAM,EAAE;EAC7B,CAAC;EACD,OAAO;GACL;GACA,WAAW,QAAQ,MAAK,WAAU,OAAO,SAAS;GAClD,OAAO,QAAQ,MAAK,WAAU,OAAO,KAAK,CAAC,EAAE,SAAS;EACxD;CACF,GACA,CAAC,MAAM,CACT;AACF"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_mastra_client_context = require("../../mastra-client-context-DzX3f0RF.cjs");
|
|
3
3
|
const require_use_in_view = require("../../use-in-view-B6eJO9Zi.cjs");
|
|
4
|
+
const require_combine_by_ids = require("../../combine-by-ids-D_lp6Dvq.cjs");
|
|
4
5
|
let react = require("react");
|
|
5
6
|
let _tanstack_react_query = require("@tanstack/react-query");
|
|
6
7
|
//#region src/hooks/datasets/use-dataset-items.ts
|
|
@@ -424,24 +425,6 @@ const allDatasetExperimentResultsQueryOptions = (client, datasetId, experimentId
|
|
|
424
425
|
refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false
|
|
425
426
|
});
|
|
426
427
|
/**
|
|
427
|
-
* Stable `combine` for `useQueries`: keyed on the ids' contents (callers pass a fresh array every
|
|
428
|
-
* render), so TanStack only recombines when a query result actually changes.
|
|
429
|
-
*/
|
|
430
|
-
const useCombineByIds = (ids) => {
|
|
431
|
-
const idsKey = JSON.stringify(ids);
|
|
432
|
-
return (0, react.useCallback)((results) => {
|
|
433
|
-
const data = {};
|
|
434
|
-
JSON.parse(idsKey).forEach((id, index) => {
|
|
435
|
-
data[id] = results[index]?.data;
|
|
436
|
-
});
|
|
437
|
-
return {
|
|
438
|
-
data,
|
|
439
|
-
isLoading: results.some((result) => result.isLoading),
|
|
440
|
-
error: results.find((result) => result.error)?.error ?? null
|
|
441
|
-
};
|
|
442
|
-
}, [idsKey]);
|
|
443
|
-
};
|
|
444
|
-
/**
|
|
445
428
|
* Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.
|
|
446
429
|
*/
|
|
447
430
|
const useDatasetExperiment = ({ datasetId, experimentId, queryOptions }) => {
|
|
@@ -462,7 +445,7 @@ const useDatasetExperiment = ({ datasetId, experimentId, queryOptions }) => {
|
|
|
462
445
|
*/
|
|
463
446
|
const useDatasetExperimentsQueries = ({ datasetId, experimentIds }) => {
|
|
464
447
|
const client = require_mastra_client_context.useMastraClient();
|
|
465
|
-
const combine = useCombineByIds(experimentIds);
|
|
448
|
+
const combine = require_combine_by_ids.useCombineByIds(experimentIds);
|
|
466
449
|
return (0, _tanstack_react_query.useQueries)({
|
|
467
450
|
queries: experimentIds.map((id) => datasetExperimentQueryOptions(client, datasetId, id)),
|
|
468
451
|
combine
|
|
@@ -518,7 +501,7 @@ const useDatasetExperimentResults = ({ datasetId, experimentId, experimentStatus
|
|
|
518
501
|
*/
|
|
519
502
|
const useAllDatasetExperimentResultsQueries = ({ datasetId, experiments }) => {
|
|
520
503
|
const client = require_mastra_client_context.useMastraClient();
|
|
521
|
-
const combine = useCombineByIds(experiments.map((experiment) => experiment.id));
|
|
504
|
+
const combine = require_combine_by_ids.useCombineByIds(experiments.map((experiment) => experiment.id));
|
|
522
505
|
return (0, _tanstack_react_query.useQueries)({
|
|
523
506
|
queries: experiments.map((experiment) => allDatasetExperimentResultsQueryOptions(client, datasetId, experiment.id, experiment.status)),
|
|
524
507
|
combine
|
|
@@ -546,7 +529,7 @@ const useScoresByExperimentId = ({ experimentId, experimentStatus, queryOptions
|
|
|
546
529
|
*/
|
|
547
530
|
const useScoresByExperimentIdsQueries = ({ experiments }) => {
|
|
548
531
|
const client = require_mastra_client_context.useMastraClient();
|
|
549
|
-
const combine = useCombineByIds(experiments.map((experiment) => experiment.id));
|
|
532
|
+
const combine = require_combine_by_ids.useCombineByIds(experiments.map((experiment) => experiment.id));
|
|
550
533
|
return (0, _tanstack_react_query.useQueries)({
|
|
551
534
|
queries: experiments.map((experiment) => experimentScoresQueryOptions(client, experiment.id, experiment.status)),
|
|
552
535
|
combine
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["useMastraClient","PER_PAGE","useInView","useMastraClient","useMastraClient","useInView","useMastraClient","useMastraClient","useInView","useMastraClient","useMastraClient","useMastraClient","useMastraClient"],"sources":["../../../src/hooks/datasets/use-dataset-items.ts","../../../src/hooks/datasets/use-dataset-mutations.ts","../../../src/hooks/datasets/use-datasets.ts","../../../src/hooks/datasets/use-compare-experiments.ts","../../../src/hooks/datasets/use-dataset-experiments.ts","../../../src/hooks/datasets/use-dataset-item-versions.ts","../../../src/hooks/datasets/use-dataset-versions.ts","../../../src/hooks/datasets/use-experiments.ts","../../../src/hooks/datasets/use-workflow-schema.ts"],"sourcesContent":["import type { MastraClient } from '@mastra/client-js';\nimport { useQuery, useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult, UseQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\n\n/**\n * Hook to fetch a single dataset item by ID\n */\ntype DatasetItemResponse = Awaited<ReturnType<MastraClient['getDatasetItem']>>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItem = <TData = DatasetItemResponse>({\n datasetId,\n itemId,\n queryOptions,\n}: {\n datasetId: string;\n itemId: string;\n queryOptions?: MastraQueryOptions<DatasetItemResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['dataset-item', datasetId, itemId],\n queryFn: () => client.getDatasetItem(datasetId, itemId),\n retry: false, // Don't retry 404s for deleted items\n ...queryOptions,\n });\n};\n\nconst PER_PAGE = 10;\n\ntype ListDatasetItemsResponse = Awaited<ReturnType<MastraClient['listDatasetItems']>>;\n\nexport type UseDatasetItemsResult = Omit<\n UseInfiniteQueryResult<InfiniteData<ListDatasetItemsResponse>, Error>,\n 'data'\n> & {\n data: ListDatasetItemsResponse['items'];\n total: number | undefined;\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n};\n\n/**\n * Hook to list items in a dataset with infinite scroll pagination and optional search\n * @param version - Optional version timestamp to view historical snapshot\n */\nexport type DatasetItemsOrderBy = NonNullable<NonNullable<Parameters<MastraClient['listDatasetItems']>[1]>['orderBy']>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItems = ({\n datasetId,\n search,\n version,\n orderBy,\n queryOptions,\n}: {\n datasetId: string;\n search?: string;\n version?: number | null;\n orderBy?: DatasetItemsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<\n ListDatasetItemsResponse,\n InfiniteData<ListDatasetItemsResponse, number>,\n QueryKey,\n number\n >;\n}): UseDatasetItemsResult => {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n\n const query = useInfiniteQuery({\n queryKey: ['dataset-items', datasetId, search, version, orderBy],\n queryFn: async ({ pageParam }) => {\n const res = await client.listDatasetItems(datasetId, {\n page: pageParam,\n perPage: PER_PAGE,\n search: search || undefined,\n version: version || undefined,\n orderBy,\n });\n return res;\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.items?.length) {\n return undefined;\n }\n const totalFetched = (lastPageParam + 1) * PER_PAGE;\n const total = lastPage?.pagination?.total ?? 0;\n if (totalFetched >= total) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n retry: false,\n ...queryOptions,\n });\n\n const items = query.data?.pages.flatMap(page => page?.items ?? []) ?? [];\n const total = query.data?.pages[0]?.pagination?.total;\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, data: items, total, setEndOfListElement };\n};\n","import type {\n CreateDatasetParams,\n UpdateDatasetParams,\n AddDatasetItemParams,\n UpdateDatasetItemParams,\n TriggerDatasetExperimentParams,\n UpdateDatasetExperimentParams,\n UpdateExperimentResultParams,\n BatchInsertDatasetItemsParams,\n BatchDeleteDatasetItemsParams,\n MastraClient,\n} from '@mastra/client-js';\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraMutationOptions } from '../shared/query-options';\n\ntype DatasetItemMutationVariables = {\n datasetId: string;\n itemId: string;\n};\n\ntype ClientResult<K extends keyof MastraClient> = MastraClient[K] extends (...args: any[]) => Promise<infer R>\n ? R\n : never;\n\nexport interface DatasetMutationsQueryOptions {\n createDataset?: MastraMutationOptions<ClientResult<'createDataset'>, CreateDatasetParams>;\n updateDataset?: MastraMutationOptions<ClientResult<'updateDataset'>, UpdateDatasetParams>;\n deleteDataset?: MastraMutationOptions<ClientResult<'deleteDataset'>, string>;\n addItem?: MastraMutationOptions<ClientResult<'addDatasetItem'>, AddDatasetItemParams>;\n updateItem?: MastraMutationOptions<ClientResult<'updateDatasetItem'>, UpdateDatasetItemParams>;\n deleteItem?: MastraMutationOptions<ClientResult<'deleteDatasetItem'>, DatasetItemMutationVariables>;\n purgeItem?: MastraMutationOptions<ClientResult<'purgeDatasetItem'>, DatasetItemMutationVariables>;\n deleteItems?: MastraMutationOptions<\n ClientResult<'batchDeleteDatasetItems'>,\n { datasetId: string; itemIds: string[] }\n >;\n batchInsertItems?: MastraMutationOptions<ClientResult<'batchInsertDatasetItems'>, BatchInsertDatasetItemsParams>;\n batchDeleteItems?: MastraMutationOptions<ClientResult<'batchDeleteDatasetItems'>, BatchDeleteDatasetItemsParams>;\n triggerExperiment?: MastraMutationOptions<ClientResult<'triggerDatasetExperiment'>, TriggerDatasetExperimentParams>;\n deleteExperiment?: MastraMutationOptions<ClientResult<'deleteExperiment'>, string>;\n updateExperiment?: MastraMutationOptions<ClientResult<'updateDatasetExperiment'>, UpdateDatasetExperimentParams>;\n updateExperimentResult?: MastraMutationOptions<\n ClientResult<'updateDatasetExperimentResult'>,\n UpdateExperimentResultParams\n >;\n}\n\n/**\n * Hook providing mutation functions for datasets, items, and runs\n * All mutations invalidate relevant query caches on success.\n * `queryOptions` is keyed by returned mutation name and spread last; a user `onSuccess` replaces the internal invalidation.\n */\nexport const useDatasetMutations = ({ queryOptions }: { queryOptions?: DatasetMutationsQueryOptions } = {}) => {\n const client = useMastraClient();\n const queryClient = useQueryClient();\n\n const createDataset = useMutation({\n mutationFn: (params: CreateDatasetParams) => client.createDataset(params),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['datasets'] });\n },\n ...queryOptions?.createDataset,\n });\n\n const updateDataset = useMutation({\n mutationFn: (params: UpdateDatasetParams) => client.updateDataset(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['datasets'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n },\n ...queryOptions?.updateDataset,\n });\n\n const deleteDataset = useMutation({\n mutationFn: (datasetId: string) => client.deleteDataset(datasetId),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['datasets'] });\n },\n ...queryOptions?.deleteDataset,\n });\n\n const addItem = useMutation({\n mutationFn: (params: AddDatasetItemParams) => client.addDatasetItem(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.addItem,\n });\n\n const updateItem = useMutation({\n mutationFn: (params: UpdateDatasetItemParams) => client.updateDatasetItem(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-item', variables.datasetId, variables.itemId] });\n void queryClient.invalidateQueries({\n queryKey: ['dataset-item-versions', variables.datasetId, variables.itemId],\n });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.updateItem,\n });\n\n const deleteItem = useMutation({\n mutationFn: ({ datasetId, itemId }: DatasetItemMutationVariables) => client.deleteDatasetItem(datasetId, itemId),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.deleteItem,\n });\n\n const purgeItem = useMutation({\n mutationFn: ({ datasetId, itemId }: DatasetItemMutationVariables) => client.purgeDatasetItem(datasetId, itemId),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-item', variables.datasetId, variables.itemId] });\n void queryClient.invalidateQueries({\n queryKey: ['dataset-item-versions', variables.datasetId, variables.itemId],\n });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-completed-items'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-review-summary'] });\n },\n ...queryOptions?.purgeItem,\n });\n\n // Batch insert items using the batch endpoint\n const batchInsertItems = useMutation({\n mutationFn: (params: BatchInsertDatasetItemsParams) => client.batchInsertDatasetItems(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.batchInsertItems,\n });\n\n // Batch delete items using the batch endpoint\n const batchDeleteItems = useMutation({\n mutationFn: (params: BatchDeleteDatasetItemsParams) => client.batchDeleteDatasetItems(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.batchDeleteItems,\n });\n\n // @deprecated - use batchDeleteItems mutation instead\n const deleteItems = useMutation({\n mutationFn: async ({ datasetId, itemIds }: { datasetId: string; itemIds: string[] }) => {\n return client.batchDeleteDatasetItems({ datasetId, itemIds });\n },\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.deleteItems,\n });\n\n const triggerExperiment = useMutation({\n mutationFn: (params: TriggerDatasetExperimentParams) => client.triggerDatasetExperiment(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiments', variables.datasetId] });\n },\n ...queryOptions?.triggerExperiment,\n });\n\n const deleteExperiment = useMutation({\n mutationFn: (experimentId: string) => client.deleteExperiment(experimentId),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['experiments'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiments'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['completed-items'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-review-summary'] });\n },\n ...queryOptions?.deleteExperiment,\n });\n\n const updateExperiment = useMutation({\n mutationFn: (params: UpdateDatasetExperimentParams) => client.updateDatasetExperiment(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['experiments'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment', variables.experimentId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiments', variables.datasetId] });\n void queryClient.invalidateQueries({\n queryKey: ['dataset-experiment', variables.datasetId, variables.experimentId],\n });\n },\n ...queryOptions?.updateExperiment,\n });\n\n const updateExperimentResult = useMutation({\n mutationFn: (params: UpdateExperimentResultParams) => client.updateDatasetExperimentResult(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['experiment-results', variables.experimentId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-completed-items'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-review-summary'] });\n },\n ...queryOptions?.updateExperimentResult,\n });\n\n return {\n createDataset,\n updateDataset,\n deleteDataset,\n addItem,\n updateItem,\n deleteItem,\n purgeItem,\n deleteItems,\n batchInsertItems,\n batchDeleteItems,\n triggerExperiment,\n deleteExperiment,\n updateExperiment,\n updateExperimentResult,\n };\n};\n","import type { ExperimentTargetType, ListDatasetsParams, MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery, useQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult, UseQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\n\ntype ListDatasetsResponse = Awaited<ReturnType<MastraClient['listDatasets']>>;\ntype DatasetResponse = Awaited<ReturnType<MastraClient['getDataset']>>;\n\n/**\n * Hook to list all datasets with optional pagination\n */\nexport const useDatasets = <TData = ListDatasetsResponse>({\n pagination,\n queryOptions,\n}: {\n pagination?: { page?: number; perPage?: number };\n queryOptions?: MastraQueryOptions<ListDatasetsResponse, TData>;\n} = {}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['datasets', pagination],\n queryFn: () => client.listDatasets(pagination),\n placeholderData: previousData => previousData,\n ...queryOptions,\n });\n};\n\nconst DATASETS_PER_PAGE = 20;\n\nexport interface DatasetTargetFilter {\n targetType?: ExperimentTargetType | '';\n targetId?: string;\n}\n\nexport type DatasetsOrderBy = NonNullable<ListDatasetsParams['orderBy']>;\n\ntype DatasetRecord = ListDatasetsResponse['datasets'][number];\n\nexport type UseInfiniteDatasetsResult<TData = DatasetRecord[]> = UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n};\n\n/**\n * Hook to list datasets with infinite scroll pagination, optionally scoped server-side to a target.\n * `data` defaults to the flattened dataset list; a user `select` replaces that flattening.\n */\nexport const useInfiniteDatasets = <TData = DatasetRecord[]>({\n filter,\n orderBy,\n queryOptions,\n}: {\n filter?: DatasetTargetFilter;\n orderBy?: DatasetsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ListDatasetsResponse, TData, QueryKey, number>;\n} = {}): UseInfiniteDatasetsResult<TData> => {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n const targetType = filter?.targetType || undefined;\n const targetIds = filter?.targetId ? [filter.targetId] : undefined;\n\n const query = useInfiniteQuery({\n queryKey: ['datasets', 'infinite', { targetType, targetIds, orderBy }],\n queryFn: ({ pageParam }) =>\n client.listDatasets({ page: pageParam, perPage: DATASETS_PER_PAGE, targetType, targetIds, orderBy }),\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.datasets?.length || !lastPage.pagination?.hasMore) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n select: (data: InfiniteData<ListDatasetsResponse, number>) =>\n data.pages.flatMap(page => page?.datasets ?? []) as TData,\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n};\n\n/**\n * Hook to fetch a single dataset by ID\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDataset = <TData = DatasetResponse>({\n datasetId,\n queryOptions,\n}: {\n datasetId: string;\n queryOptions?: MastraQueryOptions<DatasetResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['dataset', datasetId],\n queryFn: () => client.getDataset(datasetId),\n ...queryOptions,\n });\n};\n","import type { CompareExperimentsResponse } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\n/**\n * Hook to compare two to ten dataset experiments item by item against a baseline.\n * @param datasetId - ID of the dataset\n * @param experimentIds - IDs of the experiments to compare\n * @param baselineId - ID of the baseline experiment; must be one of `experimentIds` (defaults to the first)\n * @param queryOptions - TanStack Query options, spread last to override defaults\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useCompareExperiments = <TData = CompareExperimentsResponse>({\n datasetId,\n experimentIds,\n baselineId,\n queryOptions,\n}: {\n datasetId: string;\n experimentIds: string[];\n baselineId?: string;\n queryOptions?: MastraQueryOptions<CompareExperimentsResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['compare-experiments', datasetId, experimentIds, baselineId],\n queryFn: () => client.compareExperiments({ datasetId, experimentIds, baselineId }),\n ...queryOptions,\n });\n};\n","import type { ClientScoreRowData, DatasetExperimentResult, MastraClient } from '@mastra/client-js';\nimport type { ExperimentStatus } from '@mastra/core/storage';\nimport { queryOptions as tanstackQueryOptions, useInfiniteQuery, useQueries, useQuery } from '@tanstack/react-query';\nimport type {\n InfiniteData,\n QueryKey,\n UseInfiniteQueryResult,\n UseQueryOptions,\n UseQueryResult,\n} from '@tanstack/react-query';\nimport { useCallback, useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\n\ntype DatasetExperimentResponse = Awaited<ReturnType<MastraClient['getDatasetExperiment']>>;\ntype ExperimentResultsPage = Awaited<ReturnType<MastraClient['listDatasetExperimentResults']>>;\ntype ExperimentScoresByEntity = Record<string, ClientScoreRowData[]>;\ntype DatasetExperimentQueryKey = string[];\ntype ExperimentStatusQueryKey = (string | undefined)[];\n\nconst POLL_INTERVAL_MS = 2000;\nconst RESULTS_PER_PAGE = 100;\nconst SCORES_PER_PAGE = 100;\n\nconst isInProgress = (status: string | undefined) => status === 'running' || status === 'pending';\n\n/**\n * Key, fetcher and polling policy of the `dataset-experiment` query, shared by the single and\n * multi-experiment hooks so they hit the same cache entry.\n * Polls every 2 seconds while the experiment is 'running' or 'pending'.\n */\nexport const datasetExperimentQueryOptions = (\n client: MastraClient,\n datasetId: string,\n experimentId: string,\n): UseQueryOptions<DatasetExperimentResponse, Error, DatasetExperimentResponse, DatasetExperimentQueryKey> =>\n tanstackQueryOptions({\n queryKey: ['dataset-experiment', datasetId, experimentId],\n queryFn: () => client.getDatasetExperiment(datasetId, experimentId),\n gcTime: 0,\n staleTime: 0,\n refetchInterval: query => (isInProgress(query.state.data?.status) ? POLL_INTERVAL_MS : false),\n });\n\n/**\n * Key and fetcher of the `dataset-experiment-scores` query: every score of an experiment, across all\n * pages, grouped by dataset item id. Polls every 2 seconds while `experimentStatus` is in progress.\n */\nexport const experimentScoresQueryOptions = (\n client: MastraClient,\n experimentId: string,\n experimentStatus: ExperimentStatus | undefined,\n): UseQueryOptions<ExperimentScoresByEntity, Error, ExperimentScoresByEntity, ExperimentStatusQueryKey> =>\n tanstackQueryOptions({\n queryKey: ['dataset-experiment-scores', experimentId, experimentStatus],\n queryFn: async (): Promise<ExperimentScoresByEntity> => {\n const allScores: ClientScoreRowData[] = [];\n let page = 0;\n\n while (true) {\n const response = await client.listScoresByRunId({ runId: experimentId, page, perPage: SCORES_PER_PAGE });\n allScores.push(...response.scores);\n if (!response.pagination.hasMore) break;\n page++;\n }\n\n const grouped: ExperimentScoresByEntity = {};\n for (const row of allScores) {\n (grouped[row.entityId] ??= []).push(row);\n }\n return grouped;\n },\n refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false,\n });\n\n/**\n * Key and fetcher of the `dataset-experiment-results-all` query: every result of an experiment, across\n * all pages. Polls every 2 seconds while `experimentStatus` is in progress.\n */\nexport const allDatasetExperimentResultsQueryOptions = (\n client: MastraClient,\n datasetId: string,\n experimentId: string,\n experimentStatus: ExperimentStatus | undefined,\n): UseQueryOptions<DatasetExperimentResult[], Error, DatasetExperimentResult[], ExperimentStatusQueryKey> =>\n tanstackQueryOptions({\n queryKey: ['dataset-experiment-results-all', datasetId, experimentId, experimentStatus],\n queryFn: async (): Promise<DatasetExperimentResult[]> => {\n const allResults: DatasetExperimentResult[] = [];\n let page = 0;\n\n while (true) {\n const response = await client.listDatasetExperimentResults(datasetId, experimentId, {\n page,\n perPage: RESULTS_PER_PAGE,\n });\n allResults.push(...response.results);\n if (!response.pagination.hasMore || response.results.length === 0) break;\n page++;\n }\n\n return allResults;\n },\n refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false,\n });\n\n/** One entry per requested experiment id, in the order the ids were given. */\nexport interface ExperimentQueriesResult<T> {\n data: Record<string, T | undefined>;\n /** True while any experiment has not loaded yet. */\n isLoading: boolean;\n /** First error among the experiments, if any. */\n error: Error | null;\n}\n\n/**\n * Stable `combine` for `useQueries`: keyed on the ids' contents (callers pass a fresh array every\n * render), so TanStack only recombines when a query result actually changes.\n */\nconst useCombineByIds = <T>(ids: string[]) => {\n const idsKey = JSON.stringify(ids);\n return useCallback(\n (results: Array<UseQueryResult<T, Error>>): ExperimentQueriesResult<T> => {\n const data: Record<string, T | undefined> = {};\n (JSON.parse(idsKey) as string[]).forEach((id, index) => {\n data[id] = results[index]?.data;\n });\n return {\n data,\n isLoading: results.some(result => result.isLoading),\n error: results.find(result => result.error)?.error ?? null,\n };\n },\n [idsKey],\n );\n};\n\n/** An experiment id plus its status, which drives polling of its dependent queries. */\nexport interface ExperimentRef {\n id: string;\n status?: ExperimentStatus;\n}\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetExperiment = <TData = DatasetExperimentResponse>({\n datasetId,\n experimentId,\n queryOptions,\n}: {\n datasetId: string;\n experimentId: string;\n queryOptions?: MastraQueryOptions<DatasetExperimentResponse, TData, DatasetExperimentQueryKey>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n const { queryKey, queryFn, gcTime, staleTime, refetchInterval } = datasetExperimentQueryOptions(\n client,\n datasetId,\n experimentId,\n );\n return useQuery<DatasetExperimentResponse, Error, TData, DatasetExperimentQueryKey>({\n queryKey,\n queryFn,\n gcTime,\n staleTime,\n refetchInterval,\n ...queryOptions,\n });\n};\n\n/**\n * Fetches several experiments of one dataset in parallel, each polled while it runs.\n * The server 404s an experiment that does not belong to `datasetId`, which surfaces as `error`.\n */\nexport const useDatasetExperimentsQueries = ({\n datasetId,\n experimentIds,\n}: {\n datasetId: string;\n experimentIds: string[];\n}): ExperimentQueriesResult<DatasetExperimentResponse> => {\n const client = useMastraClient();\n const combine = useCombineByIds<DatasetExperimentResponse>(experimentIds);\n return useQueries({\n queries: experimentIds.map(id => datasetExperimentQueryOptions(client, datasetId, id)),\n combine,\n });\n};\n\nexport type ExperimentResultsOrderBy = NonNullable<\n NonNullable<Parameters<MastraClient['listDatasetExperimentResults']>[2]>['orderBy']\n>;\n\ninterface UseDatasetExperimentResultsParams<TData = DatasetExperimentResult[]> {\n datasetId: string;\n experimentId: string;\n experimentStatus?: ExperimentStatus;\n orderBy?: ExperimentResultsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ExperimentResultsPage, TData, QueryKey, number>;\n}\n\n/**\n * Hook to list results for a dataset experiment with infinite scroll pagination.\n * Polls every 2 seconds while experiment status is 'pending' or 'running'.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetExperimentResults = <TData = DatasetExperimentResult[]>({\n datasetId,\n experimentId,\n experimentStatus,\n orderBy,\n queryOptions,\n}: UseDatasetExperimentResultsParams<TData>): UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n} => {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n\n const query = useInfiniteQuery({\n queryKey: ['dataset-experiment-results', datasetId, experimentId, experimentStatus, orderBy],\n queryFn: async ({ pageParam }) => {\n return client.listDatasetExperimentResults(datasetId, experimentId, {\n page: pageParam,\n perPage: RESULTS_PER_PAGE,\n orderBy,\n });\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.results?.length) {\n return undefined;\n }\n const totalFetched = (lastPageParam + 1) * RESULTS_PER_PAGE;\n const total = lastPage?.pagination?.total ?? 0;\n if (totalFetched >= total) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false,\n select: (data: InfiniteData<ExperimentResultsPage, number>) => {\n return data.pages.flatMap(page => page?.results ?? []) as TData;\n },\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n};\n\n/**\n * Fetches every result (all pages) of several experiments of one dataset in parallel.\n * Each experiment is polled while its `status` is in progress.\n */\nexport const useAllDatasetExperimentResultsQueries = ({\n datasetId,\n experiments,\n}: {\n datasetId: string;\n experiments: ExperimentRef[];\n}): ExperimentQueriesResult<DatasetExperimentResult[]> => {\n const client = useMastraClient();\n const combine = useCombineByIds<DatasetExperimentResult[]>(experiments.map(experiment => experiment.id));\n return useQueries({\n queries: experiments.map(experiment =>\n allDatasetExperimentResultsQueryOptions(client, datasetId, experiment.id, experiment.status),\n ),\n combine,\n });\n};\n\n/**\n * Hook to fetch all scores for an experiment, transformed to Record<entityId, ClientScoreRowData[]>\n * Paginates through all pages to ensure no scores are silently dropped.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useScoresByExperimentId = <TData = ExperimentScoresByEntity>({\n experimentId,\n experimentStatus,\n queryOptions,\n}: {\n experimentId: string;\n experimentStatus?: ExperimentStatus;\n queryOptions?: MastraQueryOptions<ExperimentScoresByEntity, TData, ExperimentStatusQueryKey>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n const { queryKey, queryFn, refetchInterval } = experimentScoresQueryOptions(client, experimentId, experimentStatus);\n return useQuery<ExperimentScoresByEntity, Error, TData, ExperimentStatusQueryKey>({\n queryKey,\n queryFn,\n refetchInterval,\n ...queryOptions,\n });\n};\n\n/**\n * Fetches every score of several experiments in parallel, each grouped by dataset item id.\n * Each experiment is polled while its `status` is in progress.\n */\nexport const useScoresByExperimentIdsQueries = ({\n experiments,\n}: {\n experiments: ExperimentRef[];\n}): ExperimentQueriesResult<ExperimentScoresByEntity> => {\n const client = useMastraClient();\n const combine = useCombineByIds<ExperimentScoresByEntity>(experiments.map(experiment => experiment.id));\n return useQueries({\n queries: experiments.map(experiment => experimentScoresQueryOptions(client, experiment.id, experiment.status)),\n combine,\n });\n};\n","import type { DatasetItemVersionResponse } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\nexport type DatasetItemVersion = DatasetItemVersionResponse & {\n validTo: number | null;\n isDeleted: boolean;\n isLatest: boolean;\n};\n\n/**\n * Hook to fetch full item history (SCD-2 rows).\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItemVersions = <TData = DatasetItemVersion[]>({\n datasetId,\n itemId,\n queryOptions,\n}: {\n datasetId: string;\n itemId: string;\n queryOptions?: MastraQueryOptions<DatasetItemVersion[], TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['dataset-item-versions', datasetId, itemId],\n queryFn: async (): Promise<DatasetItemVersion[]> => {\n const res = await client.getItemHistory(datasetId, itemId);\n\n return (res?.history ?? []).map(\n (version, index): DatasetItemVersion => ({\n id: version.id,\n datasetId: version.datasetId,\n datasetVersion: version.datasetVersion,\n input: version.input,\n groundTruth: version.groundTruth,\n expectedTrajectory: version.expectedTrajectory,\n toolMocks: version.toolMocks ?? undefined,\n scorerIds: version.scorerIds ?? undefined,\n requestContext: version.requestContext ?? undefined,\n metadata: version.metadata ?? undefined,\n validTo: version.validTo,\n isDeleted: version.isDeleted,\n createdAt: version.createdAt,\n updatedAt: version.updatedAt,\n isLatest: index === 0,\n }),\n );\n },\n ...queryOptions,\n });\n};\n\n/**\n * Hook to fetch a specific version of a dataset item.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItemVersion = <TData = DatasetItemVersion>({\n datasetId,\n itemId,\n datasetVersion,\n latestVersion,\n queryOptions,\n}: {\n datasetId: string;\n itemId: string;\n datasetVersion: number;\n latestVersion?: number;\n queryOptions?: MastraQueryOptions<DatasetItemVersion, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['dataset-item-version', datasetId, itemId, datasetVersion],\n queryFn: async (): Promise<DatasetItemVersion> => {\n const v = await client.getDatasetItemVersion(datasetId, itemId, datasetVersion);\n\n return {\n id: v.id,\n datasetId: v.datasetId,\n datasetVersion: v.datasetVersion,\n input: v.input,\n groundTruth: v.groundTruth,\n expectedTrajectory: v.expectedTrajectory,\n toolMocks: v.toolMocks ?? undefined,\n scorerIds: v.scorerIds ?? undefined,\n requestContext: v.requestContext ?? undefined,\n metadata: v.metadata ?? undefined,\n validTo: null,\n isDeleted: false,\n createdAt: v.createdAt,\n updatedAt: v.updatedAt,\n isLatest: latestVersion != null ? datasetVersion === latestVersion : false,\n };\n },\n ...queryOptions,\n });\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions } from '../shared/query-options';\n\nexport interface DatasetVersion {\n id?: string;\n datasetId?: string;\n version: number;\n createdAt?: Date | string;\n isCurrent: boolean;\n}\n\ntype DatasetVersionsPage = Awaited<ReturnType<MastraClient['listDatasetVersions']>>;\n\nconst PER_PAGE = 10;\n\n/**\n * Hook to fetch dataset versions from the API with infinite pagination.\n * `data` defaults to the flattened `DatasetVersion[]`; a user `select` replaces that.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetVersions = <TData = DatasetVersion[]>({\n datasetId,\n queryOptions,\n}: {\n datasetId: string;\n queryOptions?: MastraInfiniteQueryOptions<DatasetVersionsPage, TData, QueryKey, number>;\n}) => {\n const client = useMastraClient();\n\n return useInfiniteQuery({\n queryKey: ['dataset-versions', datasetId],\n queryFn: async ({ pageParam }) => {\n return client.listDatasetVersions(datasetId, { page: pageParam, perPage: PER_PAGE });\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (lastPage?.pagination?.hasMore) {\n return lastPageParam + 1;\n }\n return undefined;\n },\n select: (data: InfiniteData<DatasetVersionsPage, number>) => {\n return data.pages\n .flatMap(page => page?.versions ?? [])\n .map(\n (v, index): DatasetVersion => ({\n id: v.id,\n datasetId: v.datasetId,\n version: v.version,\n createdAt: v.createdAt,\n isCurrent: index === 0,\n }),\n ) as TData;\n },\n ...queryOptions,\n });\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\ntype GetExperimentResponse = Awaited<ReturnType<MastraClient['getExperiment']>>;\n\n/**\n * Hook to list all experiments across all datasets with optional pagination\n */\nexport const useExperiments = <TData = ListExperimentsResponse>({\n pagination,\n queryOptions,\n}: {\n pagination?: { page?: number; perPage?: number };\n queryOptions?: MastraQueryOptions<ListExperimentsResponse, TData>;\n} = {}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['experiments', pagination],\n queryFn: () => client.listExperiments(pagination),\n ...queryOptions,\n });\n};\n\n/**\n * Hook to fetch a single experiment by ID without knowing its dataset\n */\nexport const useExperiment = <TData = GetExperimentResponse>({\n experimentId,\n queryOptions,\n}: {\n experimentId: string;\n queryOptions?: MastraQueryOptions<GetExperimentResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['experiment', experimentId],\n queryFn: () => client.getExperiment(experimentId),\n ...queryOptions,\n });\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype WorkflowSchemaResponse = Awaited<ReturnType<ReturnType<MastraClient['getWorkflow']>['getSchema']>>;\n\n/**\n * Hook to fetch workflow input/output schema by workflow ID.\n * Returns { inputSchema, outputSchema } where each is Record<string, unknown> | null.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport function useWorkflowSchema<TData = WorkflowSchemaResponse>({\n workflowId,\n queryOptions,\n}: {\n workflowId: string | null;\n queryOptions?: MastraQueryOptions<WorkflowSchemaResponse, TData>;\n}): UseQueryResult<TData, Error> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['workflow-schema', workflowId],\n queryFn: async () => {\n if (!workflowId) throw new Error('No workflow selected');\n return client.getWorkflow(workflowId).getSchema();\n },\n staleTime: 5 * 60 * 1000, // Cache for 5 minutes\n ...queryOptions,\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["useMastraClient","PER_PAGE","useInView","useMastraClient","useMastraClient","useInView","useMastraClient","useMastraClient","useCombineByIds","useInView","useMastraClient","useMastraClient","useMastraClient","useMastraClient"],"sources":["../../../src/hooks/datasets/use-dataset-items.ts","../../../src/hooks/datasets/use-dataset-mutations.ts","../../../src/hooks/datasets/use-datasets.ts","../../../src/hooks/datasets/use-compare-experiments.ts","../../../src/hooks/datasets/use-dataset-experiments.ts","../../../src/hooks/datasets/use-dataset-item-versions.ts","../../../src/hooks/datasets/use-dataset-versions.ts","../../../src/hooks/datasets/use-experiments.ts","../../../src/hooks/datasets/use-workflow-schema.ts"],"sourcesContent":["import type { MastraClient } from '@mastra/client-js';\nimport { useQuery, useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult, UseQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\n\n/**\n * Hook to fetch a single dataset item by ID\n */\ntype DatasetItemResponse = Awaited<ReturnType<MastraClient['getDatasetItem']>>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItem = <TData = DatasetItemResponse>({\n datasetId,\n itemId,\n queryOptions,\n}: {\n datasetId: string;\n itemId: string;\n queryOptions?: MastraQueryOptions<DatasetItemResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['dataset-item', datasetId, itemId],\n queryFn: () => client.getDatasetItem(datasetId, itemId),\n retry: false, // Don't retry 404s for deleted items\n ...queryOptions,\n });\n};\n\nconst PER_PAGE = 10;\n\ntype ListDatasetItemsResponse = Awaited<ReturnType<MastraClient['listDatasetItems']>>;\n\nexport type UseDatasetItemsResult = Omit<\n UseInfiniteQueryResult<InfiniteData<ListDatasetItemsResponse>, Error>,\n 'data'\n> & {\n data: ListDatasetItemsResponse['items'];\n total: number | undefined;\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n};\n\n/**\n * Hook to list items in a dataset with infinite scroll pagination and optional search\n * @param version - Optional version timestamp to view historical snapshot\n */\nexport type DatasetItemsOrderBy = NonNullable<NonNullable<Parameters<MastraClient['listDatasetItems']>[1]>['orderBy']>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItems = ({\n datasetId,\n search,\n version,\n orderBy,\n queryOptions,\n}: {\n datasetId: string;\n search?: string;\n version?: number | null;\n orderBy?: DatasetItemsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<\n ListDatasetItemsResponse,\n InfiniteData<ListDatasetItemsResponse, number>,\n QueryKey,\n number\n >;\n}): UseDatasetItemsResult => {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n\n const query = useInfiniteQuery({\n queryKey: ['dataset-items', datasetId, search, version, orderBy],\n queryFn: async ({ pageParam }) => {\n const res = await client.listDatasetItems(datasetId, {\n page: pageParam,\n perPage: PER_PAGE,\n search: search || undefined,\n version: version || undefined,\n orderBy,\n });\n return res;\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.items?.length) {\n return undefined;\n }\n const totalFetched = (lastPageParam + 1) * PER_PAGE;\n const total = lastPage?.pagination?.total ?? 0;\n if (totalFetched >= total) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n retry: false,\n ...queryOptions,\n });\n\n const items = query.data?.pages.flatMap(page => page?.items ?? []) ?? [];\n const total = query.data?.pages[0]?.pagination?.total;\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, data: items, total, setEndOfListElement };\n};\n","import type {\n CreateDatasetParams,\n UpdateDatasetParams,\n AddDatasetItemParams,\n UpdateDatasetItemParams,\n TriggerDatasetExperimentParams,\n UpdateDatasetExperimentParams,\n UpdateExperimentResultParams,\n BatchInsertDatasetItemsParams,\n BatchDeleteDatasetItemsParams,\n MastraClient,\n} from '@mastra/client-js';\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraMutationOptions } from '../shared/query-options';\n\ntype DatasetItemMutationVariables = {\n datasetId: string;\n itemId: string;\n};\n\ntype ClientResult<K extends keyof MastraClient> = MastraClient[K] extends (...args: any[]) => Promise<infer R>\n ? R\n : never;\n\nexport interface DatasetMutationsQueryOptions {\n createDataset?: MastraMutationOptions<ClientResult<'createDataset'>, CreateDatasetParams>;\n updateDataset?: MastraMutationOptions<ClientResult<'updateDataset'>, UpdateDatasetParams>;\n deleteDataset?: MastraMutationOptions<ClientResult<'deleteDataset'>, string>;\n addItem?: MastraMutationOptions<ClientResult<'addDatasetItem'>, AddDatasetItemParams>;\n updateItem?: MastraMutationOptions<ClientResult<'updateDatasetItem'>, UpdateDatasetItemParams>;\n deleteItem?: MastraMutationOptions<ClientResult<'deleteDatasetItem'>, DatasetItemMutationVariables>;\n purgeItem?: MastraMutationOptions<ClientResult<'purgeDatasetItem'>, DatasetItemMutationVariables>;\n deleteItems?: MastraMutationOptions<\n ClientResult<'batchDeleteDatasetItems'>,\n { datasetId: string; itemIds: string[] }\n >;\n batchInsertItems?: MastraMutationOptions<ClientResult<'batchInsertDatasetItems'>, BatchInsertDatasetItemsParams>;\n batchDeleteItems?: MastraMutationOptions<ClientResult<'batchDeleteDatasetItems'>, BatchDeleteDatasetItemsParams>;\n triggerExperiment?: MastraMutationOptions<ClientResult<'triggerDatasetExperiment'>, TriggerDatasetExperimentParams>;\n deleteExperiment?: MastraMutationOptions<ClientResult<'deleteExperiment'>, string>;\n updateExperiment?: MastraMutationOptions<ClientResult<'updateDatasetExperiment'>, UpdateDatasetExperimentParams>;\n updateExperimentResult?: MastraMutationOptions<\n ClientResult<'updateDatasetExperimentResult'>,\n UpdateExperimentResultParams\n >;\n}\n\n/**\n * Hook providing mutation functions for datasets, items, and runs\n * All mutations invalidate relevant query caches on success.\n * `queryOptions` is keyed by returned mutation name and spread last; a user `onSuccess` replaces the internal invalidation.\n */\nexport const useDatasetMutations = ({ queryOptions }: { queryOptions?: DatasetMutationsQueryOptions } = {}) => {\n const client = useMastraClient();\n const queryClient = useQueryClient();\n\n const createDataset = useMutation({\n mutationFn: (params: CreateDatasetParams) => client.createDataset(params),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['datasets'] });\n },\n ...queryOptions?.createDataset,\n });\n\n const updateDataset = useMutation({\n mutationFn: (params: UpdateDatasetParams) => client.updateDataset(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['datasets'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n },\n ...queryOptions?.updateDataset,\n });\n\n const deleteDataset = useMutation({\n mutationFn: (datasetId: string) => client.deleteDataset(datasetId),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['datasets'] });\n },\n ...queryOptions?.deleteDataset,\n });\n\n const addItem = useMutation({\n mutationFn: (params: AddDatasetItemParams) => client.addDatasetItem(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.addItem,\n });\n\n const updateItem = useMutation({\n mutationFn: (params: UpdateDatasetItemParams) => client.updateDatasetItem(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-item', variables.datasetId, variables.itemId] });\n void queryClient.invalidateQueries({\n queryKey: ['dataset-item-versions', variables.datasetId, variables.itemId],\n });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.updateItem,\n });\n\n const deleteItem = useMutation({\n mutationFn: ({ datasetId, itemId }: DatasetItemMutationVariables) => client.deleteDatasetItem(datasetId, itemId),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.deleteItem,\n });\n\n const purgeItem = useMutation({\n mutationFn: ({ datasetId, itemId }: DatasetItemMutationVariables) => client.purgeDatasetItem(datasetId, itemId),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-item', variables.datasetId, variables.itemId] });\n void queryClient.invalidateQueries({\n queryKey: ['dataset-item-versions', variables.datasetId, variables.itemId],\n });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-completed-items'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-review-summary'] });\n },\n ...queryOptions?.purgeItem,\n });\n\n // Batch insert items using the batch endpoint\n const batchInsertItems = useMutation({\n mutationFn: (params: BatchInsertDatasetItemsParams) => client.batchInsertDatasetItems(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.batchInsertItems,\n });\n\n // Batch delete items using the batch endpoint\n const batchDeleteItems = useMutation({\n mutationFn: (params: BatchDeleteDatasetItemsParams) => client.batchDeleteDatasetItems(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.batchDeleteItems,\n });\n\n // @deprecated - use batchDeleteItems mutation instead\n const deleteItems = useMutation({\n mutationFn: async ({ datasetId, itemIds }: { datasetId: string; itemIds: string[] }) => {\n return client.batchDeleteDatasetItems({ datasetId, itemIds });\n },\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.deleteItems,\n });\n\n const triggerExperiment = useMutation({\n mutationFn: (params: TriggerDatasetExperimentParams) => client.triggerDatasetExperiment(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiments', variables.datasetId] });\n },\n ...queryOptions?.triggerExperiment,\n });\n\n const deleteExperiment = useMutation({\n mutationFn: (experimentId: string) => client.deleteExperiment(experimentId),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['experiments'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiments'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['completed-items'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-review-summary'] });\n },\n ...queryOptions?.deleteExperiment,\n });\n\n const updateExperiment = useMutation({\n mutationFn: (params: UpdateDatasetExperimentParams) => client.updateDatasetExperiment(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['experiments'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment', variables.experimentId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiments', variables.datasetId] });\n void queryClient.invalidateQueries({\n queryKey: ['dataset-experiment', variables.datasetId, variables.experimentId],\n });\n },\n ...queryOptions?.updateExperiment,\n });\n\n const updateExperimentResult = useMutation({\n mutationFn: (params: UpdateExperimentResultParams) => client.updateDatasetExperimentResult(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['experiment-results', variables.experimentId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-completed-items'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-review-summary'] });\n },\n ...queryOptions?.updateExperimentResult,\n });\n\n return {\n createDataset,\n updateDataset,\n deleteDataset,\n addItem,\n updateItem,\n deleteItem,\n purgeItem,\n deleteItems,\n batchInsertItems,\n batchDeleteItems,\n triggerExperiment,\n deleteExperiment,\n updateExperiment,\n updateExperimentResult,\n };\n};\n","import type { ExperimentTargetType, ListDatasetsParams, MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery, useQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult, UseQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\n\ntype ListDatasetsResponse = Awaited<ReturnType<MastraClient['listDatasets']>>;\ntype DatasetResponse = Awaited<ReturnType<MastraClient['getDataset']>>;\n\n/**\n * Hook to list all datasets with optional pagination\n */\nexport const useDatasets = <TData = ListDatasetsResponse>({\n pagination,\n queryOptions,\n}: {\n pagination?: { page?: number; perPage?: number };\n queryOptions?: MastraQueryOptions<ListDatasetsResponse, TData>;\n} = {}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['datasets', pagination],\n queryFn: () => client.listDatasets(pagination),\n placeholderData: previousData => previousData,\n ...queryOptions,\n });\n};\n\nconst DATASETS_PER_PAGE = 20;\n\nexport interface DatasetTargetFilter {\n targetType?: ExperimentTargetType | '';\n targetId?: string;\n}\n\nexport type DatasetsOrderBy = NonNullable<ListDatasetsParams['orderBy']>;\n\ntype DatasetRecord = ListDatasetsResponse['datasets'][number];\n\nexport type UseInfiniteDatasetsResult<TData = DatasetRecord[]> = UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n};\n\n/**\n * Hook to list datasets with infinite scroll pagination, optionally scoped server-side to a target.\n * `data` defaults to the flattened dataset list; a user `select` replaces that flattening.\n */\nexport const useInfiniteDatasets = <TData = DatasetRecord[]>({\n filter,\n orderBy,\n queryOptions,\n}: {\n filter?: DatasetTargetFilter;\n orderBy?: DatasetsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ListDatasetsResponse, TData, QueryKey, number>;\n} = {}): UseInfiniteDatasetsResult<TData> => {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n const targetType = filter?.targetType || undefined;\n const targetIds = filter?.targetId ? [filter.targetId] : undefined;\n\n const query = useInfiniteQuery({\n queryKey: ['datasets', 'infinite', { targetType, targetIds, orderBy }],\n queryFn: ({ pageParam }) =>\n client.listDatasets({ page: pageParam, perPage: DATASETS_PER_PAGE, targetType, targetIds, orderBy }),\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.datasets?.length || !lastPage.pagination?.hasMore) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n select: (data: InfiniteData<ListDatasetsResponse, number>) =>\n data.pages.flatMap(page => page?.datasets ?? []) as TData,\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n};\n\n/**\n * Hook to fetch a single dataset by ID\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDataset = <TData = DatasetResponse>({\n datasetId,\n queryOptions,\n}: {\n datasetId: string;\n queryOptions?: MastraQueryOptions<DatasetResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['dataset', datasetId],\n queryFn: () => client.getDataset(datasetId),\n ...queryOptions,\n });\n};\n","import type { CompareExperimentsResponse } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\n/**\n * Hook to compare two to ten dataset experiments item by item against a baseline.\n * @param datasetId - ID of the dataset\n * @param experimentIds - IDs of the experiments to compare\n * @param baselineId - ID of the baseline experiment; must be one of `experimentIds` (defaults to the first)\n * @param queryOptions - TanStack Query options, spread last to override defaults\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useCompareExperiments = <TData = CompareExperimentsResponse>({\n datasetId,\n experimentIds,\n baselineId,\n queryOptions,\n}: {\n datasetId: string;\n experimentIds: string[];\n baselineId?: string;\n queryOptions?: MastraQueryOptions<CompareExperimentsResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['compare-experiments', datasetId, experimentIds, baselineId],\n queryFn: () => client.compareExperiments({ datasetId, experimentIds, baselineId }),\n ...queryOptions,\n });\n};\n","import type { ClientScoreRowData, DatasetExperimentResult, MastraClient } from '@mastra/client-js';\nimport type { ExperimentStatus } from '@mastra/core/storage';\nimport { queryOptions as tanstackQueryOptions, useInfiniteQuery, useQueries, useQuery } from '@tanstack/react-query';\nimport type {\n InfiniteData,\n QueryKey,\n UseInfiniteQueryResult,\n UseQueryOptions,\n UseQueryResult,\n} from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport { useCombineByIds } from '../shared/combine-by-ids';\nimport type { ExperimentQueriesResult } from '../shared/combine-by-ids';\nimport type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options';\n\nexport type { ExperimentQueriesResult } from '../shared/combine-by-ids';\nimport { useInView } from '../shared/use-in-view';\n\ntype DatasetExperimentResponse = Awaited<ReturnType<MastraClient['getDatasetExperiment']>>;\ntype ExperimentResultsPage = Awaited<ReturnType<MastraClient['listDatasetExperimentResults']>>;\ntype ExperimentScoresByEntity = Record<string, ClientScoreRowData[]>;\ntype DatasetExperimentQueryKey = string[];\ntype ExperimentStatusQueryKey = (string | undefined)[];\n\nconst POLL_INTERVAL_MS = 2000;\nconst RESULTS_PER_PAGE = 100;\nconst SCORES_PER_PAGE = 100;\n\nconst isInProgress = (status: string | undefined) => status === 'running' || status === 'pending';\n\n/**\n * Key, fetcher and polling policy of the `dataset-experiment` query, shared by the single and\n * multi-experiment hooks so they hit the same cache entry.\n * Polls every 2 seconds while the experiment is 'running' or 'pending'.\n */\nexport const datasetExperimentQueryOptions = (\n client: MastraClient,\n datasetId: string,\n experimentId: string,\n): UseQueryOptions<DatasetExperimentResponse, Error, DatasetExperimentResponse, DatasetExperimentQueryKey> =>\n tanstackQueryOptions({\n queryKey: ['dataset-experiment', datasetId, experimentId],\n queryFn: () => client.getDatasetExperiment(datasetId, experimentId),\n gcTime: 0,\n staleTime: 0,\n refetchInterval: query => (isInProgress(query.state.data?.status) ? POLL_INTERVAL_MS : false),\n });\n\n/**\n * Key and fetcher of the `dataset-experiment-scores` query: every score of an experiment, across all\n * pages, grouped by dataset item id. Polls every 2 seconds while `experimentStatus` is in progress.\n */\nexport const experimentScoresQueryOptions = (\n client: MastraClient,\n experimentId: string,\n experimentStatus: ExperimentStatus | undefined,\n): UseQueryOptions<ExperimentScoresByEntity, Error, ExperimentScoresByEntity, ExperimentStatusQueryKey> =>\n tanstackQueryOptions({\n queryKey: ['dataset-experiment-scores', experimentId, experimentStatus],\n queryFn: async (): Promise<ExperimentScoresByEntity> => {\n const allScores: ClientScoreRowData[] = [];\n let page = 0;\n\n while (true) {\n const response = await client.listScoresByRunId({ runId: experimentId, page, perPage: SCORES_PER_PAGE });\n allScores.push(...response.scores);\n if (!response.pagination.hasMore) break;\n page++;\n }\n\n const grouped: ExperimentScoresByEntity = {};\n for (const row of allScores) {\n (grouped[row.entityId] ??= []).push(row);\n }\n return grouped;\n },\n refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false,\n });\n\n/**\n * Key and fetcher of the `dataset-experiment-results-all` query: every result of an experiment, across\n * all pages. Polls every 2 seconds while `experimentStatus` is in progress.\n */\nexport const allDatasetExperimentResultsQueryOptions = (\n client: MastraClient,\n datasetId: string,\n experimentId: string,\n experimentStatus: ExperimentStatus | undefined,\n): UseQueryOptions<DatasetExperimentResult[], Error, DatasetExperimentResult[], ExperimentStatusQueryKey> =>\n tanstackQueryOptions({\n queryKey: ['dataset-experiment-results-all', datasetId, experimentId, experimentStatus],\n queryFn: async (): Promise<DatasetExperimentResult[]> => {\n const allResults: DatasetExperimentResult[] = [];\n let page = 0;\n\n while (true) {\n const response = await client.listDatasetExperimentResults(datasetId, experimentId, {\n page,\n perPage: RESULTS_PER_PAGE,\n });\n allResults.push(...response.results);\n if (!response.pagination.hasMore || response.results.length === 0) break;\n page++;\n }\n\n return allResults;\n },\n refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false,\n });\n\n/** An experiment id plus its status, which drives polling of its dependent queries. */\nexport interface ExperimentRef {\n id: string;\n status?: ExperimentStatus;\n}\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetExperiment = <TData = DatasetExperimentResponse>({\n datasetId,\n experimentId,\n queryOptions,\n}: {\n datasetId: string;\n experimentId: string;\n queryOptions?: MastraQueryOptions<DatasetExperimentResponse, TData, DatasetExperimentQueryKey>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n const { queryKey, queryFn, gcTime, staleTime, refetchInterval } = datasetExperimentQueryOptions(\n client,\n datasetId,\n experimentId,\n );\n return useQuery<DatasetExperimentResponse, Error, TData, DatasetExperimentQueryKey>({\n queryKey,\n queryFn,\n gcTime,\n staleTime,\n refetchInterval,\n ...queryOptions,\n });\n};\n\n/**\n * Fetches several experiments of one dataset in parallel, each polled while it runs.\n * The server 404s an experiment that does not belong to `datasetId`, which surfaces as `error`.\n */\nexport const useDatasetExperimentsQueries = ({\n datasetId,\n experimentIds,\n}: {\n datasetId: string;\n experimentIds: string[];\n}): ExperimentQueriesResult<DatasetExperimentResponse> => {\n const client = useMastraClient();\n const combine = useCombineByIds<DatasetExperimentResponse>(experimentIds);\n return useQueries({\n queries: experimentIds.map(id => datasetExperimentQueryOptions(client, datasetId, id)),\n combine,\n });\n};\n\nexport type ExperimentResultsOrderBy = NonNullable<\n NonNullable<Parameters<MastraClient['listDatasetExperimentResults']>[2]>['orderBy']\n>;\n\ninterface UseDatasetExperimentResultsParams<TData = DatasetExperimentResult[]> {\n datasetId: string;\n experimentId: string;\n experimentStatus?: ExperimentStatus;\n orderBy?: ExperimentResultsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ExperimentResultsPage, TData, QueryKey, number>;\n}\n\n/**\n * Hook to list results for a dataset experiment with infinite scroll pagination.\n * Polls every 2 seconds while experiment status is 'pending' or 'running'.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetExperimentResults = <TData = DatasetExperimentResult[]>({\n datasetId,\n experimentId,\n experimentStatus,\n orderBy,\n queryOptions,\n}: UseDatasetExperimentResultsParams<TData>): UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n} => {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n\n const query = useInfiniteQuery({\n queryKey: ['dataset-experiment-results', datasetId, experimentId, experimentStatus, orderBy],\n queryFn: async ({ pageParam }) => {\n return client.listDatasetExperimentResults(datasetId, experimentId, {\n page: pageParam,\n perPage: RESULTS_PER_PAGE,\n orderBy,\n });\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.results?.length) {\n return undefined;\n }\n const totalFetched = (lastPageParam + 1) * RESULTS_PER_PAGE;\n const total = lastPage?.pagination?.total ?? 0;\n if (totalFetched >= total) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false,\n select: (data: InfiniteData<ExperimentResultsPage, number>) => {\n return data.pages.flatMap(page => page?.results ?? []) as TData;\n },\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n};\n\n/**\n * Fetches every result (all pages) of several experiments of one dataset in parallel.\n * Each experiment is polled while its `status` is in progress.\n */\nexport const useAllDatasetExperimentResultsQueries = ({\n datasetId,\n experiments,\n}: {\n datasetId: string;\n experiments: ExperimentRef[];\n}): ExperimentQueriesResult<DatasetExperimentResult[]> => {\n const client = useMastraClient();\n const combine = useCombineByIds<DatasetExperimentResult[]>(experiments.map(experiment => experiment.id));\n return useQueries({\n queries: experiments.map(experiment =>\n allDatasetExperimentResultsQueryOptions(client, datasetId, experiment.id, experiment.status),\n ),\n combine,\n });\n};\n\n/**\n * Hook to fetch all scores for an experiment, transformed to Record<entityId, ClientScoreRowData[]>\n * Paginates through all pages to ensure no scores are silently dropped.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useScoresByExperimentId = <TData = ExperimentScoresByEntity>({\n experimentId,\n experimentStatus,\n queryOptions,\n}: {\n experimentId: string;\n experimentStatus?: ExperimentStatus;\n queryOptions?: MastraQueryOptions<ExperimentScoresByEntity, TData, ExperimentStatusQueryKey>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n const { queryKey, queryFn, refetchInterval } = experimentScoresQueryOptions(client, experimentId, experimentStatus);\n return useQuery<ExperimentScoresByEntity, Error, TData, ExperimentStatusQueryKey>({\n queryKey,\n queryFn,\n refetchInterval,\n ...queryOptions,\n });\n};\n\n/**\n * Fetches every score of several experiments in parallel, each grouped by dataset item id.\n * Each experiment is polled while its `status` is in progress.\n */\nexport const useScoresByExperimentIdsQueries = ({\n experiments,\n}: {\n experiments: ExperimentRef[];\n}): ExperimentQueriesResult<ExperimentScoresByEntity> => {\n const client = useMastraClient();\n const combine = useCombineByIds<ExperimentScoresByEntity>(experiments.map(experiment => experiment.id));\n return useQueries({\n queries: experiments.map(experiment => experimentScoresQueryOptions(client, experiment.id, experiment.status)),\n combine,\n });\n};\n","import type { DatasetItemVersionResponse } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\nexport type DatasetItemVersion = DatasetItemVersionResponse & {\n validTo: number | null;\n isDeleted: boolean;\n isLatest: boolean;\n};\n\n/**\n * Hook to fetch full item history (SCD-2 rows).\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItemVersions = <TData = DatasetItemVersion[]>({\n datasetId,\n itemId,\n queryOptions,\n}: {\n datasetId: string;\n itemId: string;\n queryOptions?: MastraQueryOptions<DatasetItemVersion[], TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['dataset-item-versions', datasetId, itemId],\n queryFn: async (): Promise<DatasetItemVersion[]> => {\n const res = await client.getItemHistory(datasetId, itemId);\n\n return (res?.history ?? []).map(\n (version, index): DatasetItemVersion => ({\n id: version.id,\n datasetId: version.datasetId,\n datasetVersion: version.datasetVersion,\n input: version.input,\n groundTruth: version.groundTruth,\n expectedTrajectory: version.expectedTrajectory,\n toolMocks: version.toolMocks ?? undefined,\n scorerIds: version.scorerIds ?? undefined,\n requestContext: version.requestContext ?? undefined,\n metadata: version.metadata ?? undefined,\n validTo: version.validTo,\n isDeleted: version.isDeleted,\n createdAt: version.createdAt,\n updatedAt: version.updatedAt,\n isLatest: index === 0,\n }),\n );\n },\n ...queryOptions,\n });\n};\n\n/**\n * Hook to fetch a specific version of a dataset item.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItemVersion = <TData = DatasetItemVersion>({\n datasetId,\n itemId,\n datasetVersion,\n latestVersion,\n queryOptions,\n}: {\n datasetId: string;\n itemId: string;\n datasetVersion: number;\n latestVersion?: number;\n queryOptions?: MastraQueryOptions<DatasetItemVersion, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['dataset-item-version', datasetId, itemId, datasetVersion],\n queryFn: async (): Promise<DatasetItemVersion> => {\n const v = await client.getDatasetItemVersion(datasetId, itemId, datasetVersion);\n\n return {\n id: v.id,\n datasetId: v.datasetId,\n datasetVersion: v.datasetVersion,\n input: v.input,\n groundTruth: v.groundTruth,\n expectedTrajectory: v.expectedTrajectory,\n toolMocks: v.toolMocks ?? undefined,\n scorerIds: v.scorerIds ?? undefined,\n requestContext: v.requestContext ?? undefined,\n metadata: v.metadata ?? undefined,\n validTo: null,\n isDeleted: false,\n createdAt: v.createdAt,\n updatedAt: v.updatedAt,\n isLatest: latestVersion != null ? datasetVersion === latestVersion : false,\n };\n },\n ...queryOptions,\n });\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions } from '../shared/query-options';\n\nexport interface DatasetVersion {\n id?: string;\n datasetId?: string;\n version: number;\n createdAt?: Date | string;\n isCurrent: boolean;\n}\n\ntype DatasetVersionsPage = Awaited<ReturnType<MastraClient['listDatasetVersions']>>;\n\nconst PER_PAGE = 10;\n\n/**\n * Hook to fetch dataset versions from the API with infinite pagination.\n * `data` defaults to the flattened `DatasetVersion[]`; a user `select` replaces that.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetVersions = <TData = DatasetVersion[]>({\n datasetId,\n queryOptions,\n}: {\n datasetId: string;\n queryOptions?: MastraInfiniteQueryOptions<DatasetVersionsPage, TData, QueryKey, number>;\n}) => {\n const client = useMastraClient();\n\n return useInfiniteQuery({\n queryKey: ['dataset-versions', datasetId],\n queryFn: async ({ pageParam }) => {\n return client.listDatasetVersions(datasetId, { page: pageParam, perPage: PER_PAGE });\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (lastPage?.pagination?.hasMore) {\n return lastPageParam + 1;\n }\n return undefined;\n },\n select: (data: InfiniteData<DatasetVersionsPage, number>) => {\n return data.pages\n .flatMap(page => page?.versions ?? [])\n .map(\n (v, index): DatasetVersion => ({\n id: v.id,\n datasetId: v.datasetId,\n version: v.version,\n createdAt: v.createdAt,\n isCurrent: index === 0,\n }),\n ) as TData;\n },\n ...queryOptions,\n });\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\ntype GetExperimentResponse = Awaited<ReturnType<MastraClient['getExperiment']>>;\n\n/**\n * Hook to list all experiments across all datasets with optional pagination\n */\nexport const useExperiments = <TData = ListExperimentsResponse>({\n pagination,\n queryOptions,\n}: {\n pagination?: { page?: number; perPage?: number };\n queryOptions?: MastraQueryOptions<ListExperimentsResponse, TData>;\n} = {}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['experiments', pagination],\n queryFn: () => client.listExperiments(pagination),\n ...queryOptions,\n });\n};\n\n/**\n * Hook to fetch a single experiment by ID without knowing its dataset\n */\nexport const useExperiment = <TData = GetExperimentResponse>({\n experimentId,\n queryOptions,\n}: {\n experimentId: string;\n queryOptions?: MastraQueryOptions<GetExperimentResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['experiment', experimentId],\n queryFn: () => client.getExperiment(experimentId),\n ...queryOptions,\n });\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype WorkflowSchemaResponse = Awaited<ReturnType<ReturnType<MastraClient['getWorkflow']>['getSchema']>>;\n\n/**\n * Hook to fetch workflow input/output schema by workflow ID.\n * Returns { inputSchema, outputSchema } where each is Record<string, unknown> | null.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport function useWorkflowSchema<TData = WorkflowSchemaResponse>({\n workflowId,\n queryOptions,\n}: {\n workflowId: string | null;\n queryOptions?: MastraQueryOptions<WorkflowSchemaResponse, TData>;\n}): UseQueryResult<TData, Error> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['workflow-schema', workflowId],\n queryFn: async () => {\n if (!workflowId) throw new Error('No workflow selected');\n return client.getWorkflow(workflowId).getSchema();\n },\n staleTime: 5 * 60 * 1000, // Cache for 5 minutes\n ...queryOptions,\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { n as useMastraClient } from "../../mastra-client-context-Bx_g84YB.js";
|
|
2
2
|
import { t as useInView } from "../../use-in-view-C9sYPGRm.js";
|
|
3
|
-
import {
|
|
3
|
+
import { t as useCombineByIds } from "../../combine-by-ids-CcaZKGT9.js";
|
|
4
|
+
import { useEffect } from "react";
|
|
4
5
|
import { queryOptions, useInfiniteQuery, useMutation, useQueries, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
5
6
|
//#region src/hooks/datasets/use-dataset-items.ts
|
|
6
7
|
/**
|
|
@@ -423,24 +424,6 @@ const allDatasetExperimentResultsQueryOptions = (client, datasetId, experimentId
|
|
|
423
424
|
refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false
|
|
424
425
|
});
|
|
425
426
|
/**
|
|
426
|
-
* Stable `combine` for `useQueries`: keyed on the ids' contents (callers pass a fresh array every
|
|
427
|
-
* render), so TanStack only recombines when a query result actually changes.
|
|
428
|
-
*/
|
|
429
|
-
const useCombineByIds = (ids) => {
|
|
430
|
-
const idsKey = JSON.stringify(ids);
|
|
431
|
-
return useCallback((results) => {
|
|
432
|
-
const data = {};
|
|
433
|
-
JSON.parse(idsKey).forEach((id, index) => {
|
|
434
|
-
data[id] = results[index]?.data;
|
|
435
|
-
});
|
|
436
|
-
return {
|
|
437
|
-
data,
|
|
438
|
-
isLoading: results.some((result) => result.isLoading),
|
|
439
|
-
error: results.find((result) => result.error)?.error ?? null
|
|
440
|
-
};
|
|
441
|
-
}, [idsKey]);
|
|
442
|
-
};
|
|
443
|
-
/**
|
|
444
427
|
* Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.
|
|
445
428
|
*/
|
|
446
429
|
const useDatasetExperiment = ({ datasetId, experimentId, queryOptions }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["PER_PAGE","tanstackQueryOptions"],"sources":["../../../src/hooks/datasets/use-dataset-items.ts","../../../src/hooks/datasets/use-dataset-mutations.ts","../../../src/hooks/datasets/use-datasets.ts","../../../src/hooks/datasets/use-compare-experiments.ts","../../../src/hooks/datasets/use-dataset-experiments.ts","../../../src/hooks/datasets/use-dataset-item-versions.ts","../../../src/hooks/datasets/use-dataset-versions.ts","../../../src/hooks/datasets/use-experiments.ts","../../../src/hooks/datasets/use-workflow-schema.ts"],"sourcesContent":["import type { MastraClient } from '@mastra/client-js';\nimport { useQuery, useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult, UseQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\n\n/**\n * Hook to fetch a single dataset item by ID\n */\ntype DatasetItemResponse = Awaited<ReturnType<MastraClient['getDatasetItem']>>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItem = <TData = DatasetItemResponse>({\n datasetId,\n itemId,\n queryOptions,\n}: {\n datasetId: string;\n itemId: string;\n queryOptions?: MastraQueryOptions<DatasetItemResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['dataset-item', datasetId, itemId],\n queryFn: () => client.getDatasetItem(datasetId, itemId),\n retry: false, // Don't retry 404s for deleted items\n ...queryOptions,\n });\n};\n\nconst PER_PAGE = 10;\n\ntype ListDatasetItemsResponse = Awaited<ReturnType<MastraClient['listDatasetItems']>>;\n\nexport type UseDatasetItemsResult = Omit<\n UseInfiniteQueryResult<InfiniteData<ListDatasetItemsResponse>, Error>,\n 'data'\n> & {\n data: ListDatasetItemsResponse['items'];\n total: number | undefined;\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n};\n\n/**\n * Hook to list items in a dataset with infinite scroll pagination and optional search\n * @param version - Optional version timestamp to view historical snapshot\n */\nexport type DatasetItemsOrderBy = NonNullable<NonNullable<Parameters<MastraClient['listDatasetItems']>[1]>['orderBy']>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItems = ({\n datasetId,\n search,\n version,\n orderBy,\n queryOptions,\n}: {\n datasetId: string;\n search?: string;\n version?: number | null;\n orderBy?: DatasetItemsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<\n ListDatasetItemsResponse,\n InfiniteData<ListDatasetItemsResponse, number>,\n QueryKey,\n number\n >;\n}): UseDatasetItemsResult => {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n\n const query = useInfiniteQuery({\n queryKey: ['dataset-items', datasetId, search, version, orderBy],\n queryFn: async ({ pageParam }) => {\n const res = await client.listDatasetItems(datasetId, {\n page: pageParam,\n perPage: PER_PAGE,\n search: search || undefined,\n version: version || undefined,\n orderBy,\n });\n return res;\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.items?.length) {\n return undefined;\n }\n const totalFetched = (lastPageParam + 1) * PER_PAGE;\n const total = lastPage?.pagination?.total ?? 0;\n if (totalFetched >= total) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n retry: false,\n ...queryOptions,\n });\n\n const items = query.data?.pages.flatMap(page => page?.items ?? []) ?? [];\n const total = query.data?.pages[0]?.pagination?.total;\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, data: items, total, setEndOfListElement };\n};\n","import type {\n CreateDatasetParams,\n UpdateDatasetParams,\n AddDatasetItemParams,\n UpdateDatasetItemParams,\n TriggerDatasetExperimentParams,\n UpdateDatasetExperimentParams,\n UpdateExperimentResultParams,\n BatchInsertDatasetItemsParams,\n BatchDeleteDatasetItemsParams,\n MastraClient,\n} from '@mastra/client-js';\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraMutationOptions } from '../shared/query-options';\n\ntype DatasetItemMutationVariables = {\n datasetId: string;\n itemId: string;\n};\n\ntype ClientResult<K extends keyof MastraClient> = MastraClient[K] extends (...args: any[]) => Promise<infer R>\n ? R\n : never;\n\nexport interface DatasetMutationsQueryOptions {\n createDataset?: MastraMutationOptions<ClientResult<'createDataset'>, CreateDatasetParams>;\n updateDataset?: MastraMutationOptions<ClientResult<'updateDataset'>, UpdateDatasetParams>;\n deleteDataset?: MastraMutationOptions<ClientResult<'deleteDataset'>, string>;\n addItem?: MastraMutationOptions<ClientResult<'addDatasetItem'>, AddDatasetItemParams>;\n updateItem?: MastraMutationOptions<ClientResult<'updateDatasetItem'>, UpdateDatasetItemParams>;\n deleteItem?: MastraMutationOptions<ClientResult<'deleteDatasetItem'>, DatasetItemMutationVariables>;\n purgeItem?: MastraMutationOptions<ClientResult<'purgeDatasetItem'>, DatasetItemMutationVariables>;\n deleteItems?: MastraMutationOptions<\n ClientResult<'batchDeleteDatasetItems'>,\n { datasetId: string; itemIds: string[] }\n >;\n batchInsertItems?: MastraMutationOptions<ClientResult<'batchInsertDatasetItems'>, BatchInsertDatasetItemsParams>;\n batchDeleteItems?: MastraMutationOptions<ClientResult<'batchDeleteDatasetItems'>, BatchDeleteDatasetItemsParams>;\n triggerExperiment?: MastraMutationOptions<ClientResult<'triggerDatasetExperiment'>, TriggerDatasetExperimentParams>;\n deleteExperiment?: MastraMutationOptions<ClientResult<'deleteExperiment'>, string>;\n updateExperiment?: MastraMutationOptions<ClientResult<'updateDatasetExperiment'>, UpdateDatasetExperimentParams>;\n updateExperimentResult?: MastraMutationOptions<\n ClientResult<'updateDatasetExperimentResult'>,\n UpdateExperimentResultParams\n >;\n}\n\n/**\n * Hook providing mutation functions for datasets, items, and runs\n * All mutations invalidate relevant query caches on success.\n * `queryOptions` is keyed by returned mutation name and spread last; a user `onSuccess` replaces the internal invalidation.\n */\nexport const useDatasetMutations = ({ queryOptions }: { queryOptions?: DatasetMutationsQueryOptions } = {}) => {\n const client = useMastraClient();\n const queryClient = useQueryClient();\n\n const createDataset = useMutation({\n mutationFn: (params: CreateDatasetParams) => client.createDataset(params),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['datasets'] });\n },\n ...queryOptions?.createDataset,\n });\n\n const updateDataset = useMutation({\n mutationFn: (params: UpdateDatasetParams) => client.updateDataset(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['datasets'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n },\n ...queryOptions?.updateDataset,\n });\n\n const deleteDataset = useMutation({\n mutationFn: (datasetId: string) => client.deleteDataset(datasetId),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['datasets'] });\n },\n ...queryOptions?.deleteDataset,\n });\n\n const addItem = useMutation({\n mutationFn: (params: AddDatasetItemParams) => client.addDatasetItem(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.addItem,\n });\n\n const updateItem = useMutation({\n mutationFn: (params: UpdateDatasetItemParams) => client.updateDatasetItem(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-item', variables.datasetId, variables.itemId] });\n void queryClient.invalidateQueries({\n queryKey: ['dataset-item-versions', variables.datasetId, variables.itemId],\n });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.updateItem,\n });\n\n const deleteItem = useMutation({\n mutationFn: ({ datasetId, itemId }: DatasetItemMutationVariables) => client.deleteDatasetItem(datasetId, itemId),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.deleteItem,\n });\n\n const purgeItem = useMutation({\n mutationFn: ({ datasetId, itemId }: DatasetItemMutationVariables) => client.purgeDatasetItem(datasetId, itemId),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-item', variables.datasetId, variables.itemId] });\n void queryClient.invalidateQueries({\n queryKey: ['dataset-item-versions', variables.datasetId, variables.itemId],\n });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-completed-items'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-review-summary'] });\n },\n ...queryOptions?.purgeItem,\n });\n\n // Batch insert items using the batch endpoint\n const batchInsertItems = useMutation({\n mutationFn: (params: BatchInsertDatasetItemsParams) => client.batchInsertDatasetItems(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.batchInsertItems,\n });\n\n // Batch delete items using the batch endpoint\n const batchDeleteItems = useMutation({\n mutationFn: (params: BatchDeleteDatasetItemsParams) => client.batchDeleteDatasetItems(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.batchDeleteItems,\n });\n\n // @deprecated - use batchDeleteItems mutation instead\n const deleteItems = useMutation({\n mutationFn: async ({ datasetId, itemIds }: { datasetId: string; itemIds: string[] }) => {\n return client.batchDeleteDatasetItems({ datasetId, itemIds });\n },\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.deleteItems,\n });\n\n const triggerExperiment = useMutation({\n mutationFn: (params: TriggerDatasetExperimentParams) => client.triggerDatasetExperiment(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiments', variables.datasetId] });\n },\n ...queryOptions?.triggerExperiment,\n });\n\n const deleteExperiment = useMutation({\n mutationFn: (experimentId: string) => client.deleteExperiment(experimentId),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['experiments'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiments'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['completed-items'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-review-summary'] });\n },\n ...queryOptions?.deleteExperiment,\n });\n\n const updateExperiment = useMutation({\n mutationFn: (params: UpdateDatasetExperimentParams) => client.updateDatasetExperiment(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['experiments'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment', variables.experimentId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiments', variables.datasetId] });\n void queryClient.invalidateQueries({\n queryKey: ['dataset-experiment', variables.datasetId, variables.experimentId],\n });\n },\n ...queryOptions?.updateExperiment,\n });\n\n const updateExperimentResult = useMutation({\n mutationFn: (params: UpdateExperimentResultParams) => client.updateDatasetExperimentResult(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['experiment-results', variables.experimentId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-completed-items'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-review-summary'] });\n },\n ...queryOptions?.updateExperimentResult,\n });\n\n return {\n createDataset,\n updateDataset,\n deleteDataset,\n addItem,\n updateItem,\n deleteItem,\n purgeItem,\n deleteItems,\n batchInsertItems,\n batchDeleteItems,\n triggerExperiment,\n deleteExperiment,\n updateExperiment,\n updateExperimentResult,\n };\n};\n","import type { ExperimentTargetType, ListDatasetsParams, MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery, useQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult, UseQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\n\ntype ListDatasetsResponse = Awaited<ReturnType<MastraClient['listDatasets']>>;\ntype DatasetResponse = Awaited<ReturnType<MastraClient['getDataset']>>;\n\n/**\n * Hook to list all datasets with optional pagination\n */\nexport const useDatasets = <TData = ListDatasetsResponse>({\n pagination,\n queryOptions,\n}: {\n pagination?: { page?: number; perPage?: number };\n queryOptions?: MastraQueryOptions<ListDatasetsResponse, TData>;\n} = {}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['datasets', pagination],\n queryFn: () => client.listDatasets(pagination),\n placeholderData: previousData => previousData,\n ...queryOptions,\n });\n};\n\nconst DATASETS_PER_PAGE = 20;\n\nexport interface DatasetTargetFilter {\n targetType?: ExperimentTargetType | '';\n targetId?: string;\n}\n\nexport type DatasetsOrderBy = NonNullable<ListDatasetsParams['orderBy']>;\n\ntype DatasetRecord = ListDatasetsResponse['datasets'][number];\n\nexport type UseInfiniteDatasetsResult<TData = DatasetRecord[]> = UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n};\n\n/**\n * Hook to list datasets with infinite scroll pagination, optionally scoped server-side to a target.\n * `data` defaults to the flattened dataset list; a user `select` replaces that flattening.\n */\nexport const useInfiniteDatasets = <TData = DatasetRecord[]>({\n filter,\n orderBy,\n queryOptions,\n}: {\n filter?: DatasetTargetFilter;\n orderBy?: DatasetsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ListDatasetsResponse, TData, QueryKey, number>;\n} = {}): UseInfiniteDatasetsResult<TData> => {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n const targetType = filter?.targetType || undefined;\n const targetIds = filter?.targetId ? [filter.targetId] : undefined;\n\n const query = useInfiniteQuery({\n queryKey: ['datasets', 'infinite', { targetType, targetIds, orderBy }],\n queryFn: ({ pageParam }) =>\n client.listDatasets({ page: pageParam, perPage: DATASETS_PER_PAGE, targetType, targetIds, orderBy }),\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.datasets?.length || !lastPage.pagination?.hasMore) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n select: (data: InfiniteData<ListDatasetsResponse, number>) =>\n data.pages.flatMap(page => page?.datasets ?? []) as TData,\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n};\n\n/**\n * Hook to fetch a single dataset by ID\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDataset = <TData = DatasetResponse>({\n datasetId,\n queryOptions,\n}: {\n datasetId: string;\n queryOptions?: MastraQueryOptions<DatasetResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['dataset', datasetId],\n queryFn: () => client.getDataset(datasetId),\n ...queryOptions,\n });\n};\n","import type { CompareExperimentsResponse } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\n/**\n * Hook to compare two to ten dataset experiments item by item against a baseline.\n * @param datasetId - ID of the dataset\n * @param experimentIds - IDs of the experiments to compare\n * @param baselineId - ID of the baseline experiment; must be one of `experimentIds` (defaults to the first)\n * @param queryOptions - TanStack Query options, spread last to override defaults\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useCompareExperiments = <TData = CompareExperimentsResponse>({\n datasetId,\n experimentIds,\n baselineId,\n queryOptions,\n}: {\n datasetId: string;\n experimentIds: string[];\n baselineId?: string;\n queryOptions?: MastraQueryOptions<CompareExperimentsResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['compare-experiments', datasetId, experimentIds, baselineId],\n queryFn: () => client.compareExperiments({ datasetId, experimentIds, baselineId }),\n ...queryOptions,\n });\n};\n","import type { ClientScoreRowData, DatasetExperimentResult, MastraClient } from '@mastra/client-js';\nimport type { ExperimentStatus } from '@mastra/core/storage';\nimport { queryOptions as tanstackQueryOptions, useInfiniteQuery, useQueries, useQuery } from '@tanstack/react-query';\nimport type {\n InfiniteData,\n QueryKey,\n UseInfiniteQueryResult,\n UseQueryOptions,\n UseQueryResult,\n} from '@tanstack/react-query';\nimport { useCallback, useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\n\ntype DatasetExperimentResponse = Awaited<ReturnType<MastraClient['getDatasetExperiment']>>;\ntype ExperimentResultsPage = Awaited<ReturnType<MastraClient['listDatasetExperimentResults']>>;\ntype ExperimentScoresByEntity = Record<string, ClientScoreRowData[]>;\ntype DatasetExperimentQueryKey = string[];\ntype ExperimentStatusQueryKey = (string | undefined)[];\n\nconst POLL_INTERVAL_MS = 2000;\nconst RESULTS_PER_PAGE = 100;\nconst SCORES_PER_PAGE = 100;\n\nconst isInProgress = (status: string | undefined) => status === 'running' || status === 'pending';\n\n/**\n * Key, fetcher and polling policy of the `dataset-experiment` query, shared by the single and\n * multi-experiment hooks so they hit the same cache entry.\n * Polls every 2 seconds while the experiment is 'running' or 'pending'.\n */\nexport const datasetExperimentQueryOptions = (\n client: MastraClient,\n datasetId: string,\n experimentId: string,\n): UseQueryOptions<DatasetExperimentResponse, Error, DatasetExperimentResponse, DatasetExperimentQueryKey> =>\n tanstackQueryOptions({\n queryKey: ['dataset-experiment', datasetId, experimentId],\n queryFn: () => client.getDatasetExperiment(datasetId, experimentId),\n gcTime: 0,\n staleTime: 0,\n refetchInterval: query => (isInProgress(query.state.data?.status) ? POLL_INTERVAL_MS : false),\n });\n\n/**\n * Key and fetcher of the `dataset-experiment-scores` query: every score of an experiment, across all\n * pages, grouped by dataset item id. Polls every 2 seconds while `experimentStatus` is in progress.\n */\nexport const experimentScoresQueryOptions = (\n client: MastraClient,\n experimentId: string,\n experimentStatus: ExperimentStatus | undefined,\n): UseQueryOptions<ExperimentScoresByEntity, Error, ExperimentScoresByEntity, ExperimentStatusQueryKey> =>\n tanstackQueryOptions({\n queryKey: ['dataset-experiment-scores', experimentId, experimentStatus],\n queryFn: async (): Promise<ExperimentScoresByEntity> => {\n const allScores: ClientScoreRowData[] = [];\n let page = 0;\n\n while (true) {\n const response = await client.listScoresByRunId({ runId: experimentId, page, perPage: SCORES_PER_PAGE });\n allScores.push(...response.scores);\n if (!response.pagination.hasMore) break;\n page++;\n }\n\n const grouped: ExperimentScoresByEntity = {};\n for (const row of allScores) {\n (grouped[row.entityId] ??= []).push(row);\n }\n return grouped;\n },\n refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false,\n });\n\n/**\n * Key and fetcher of the `dataset-experiment-results-all` query: every result of an experiment, across\n * all pages. Polls every 2 seconds while `experimentStatus` is in progress.\n */\nexport const allDatasetExperimentResultsQueryOptions = (\n client: MastraClient,\n datasetId: string,\n experimentId: string,\n experimentStatus: ExperimentStatus | undefined,\n): UseQueryOptions<DatasetExperimentResult[], Error, DatasetExperimentResult[], ExperimentStatusQueryKey> =>\n tanstackQueryOptions({\n queryKey: ['dataset-experiment-results-all', datasetId, experimentId, experimentStatus],\n queryFn: async (): Promise<DatasetExperimentResult[]> => {\n const allResults: DatasetExperimentResult[] = [];\n let page = 0;\n\n while (true) {\n const response = await client.listDatasetExperimentResults(datasetId, experimentId, {\n page,\n perPage: RESULTS_PER_PAGE,\n });\n allResults.push(...response.results);\n if (!response.pagination.hasMore || response.results.length === 0) break;\n page++;\n }\n\n return allResults;\n },\n refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false,\n });\n\n/** One entry per requested experiment id, in the order the ids were given. */\nexport interface ExperimentQueriesResult<T> {\n data: Record<string, T | undefined>;\n /** True while any experiment has not loaded yet. */\n isLoading: boolean;\n /** First error among the experiments, if any. */\n error: Error | null;\n}\n\n/**\n * Stable `combine` for `useQueries`: keyed on the ids' contents (callers pass a fresh array every\n * render), so TanStack only recombines when a query result actually changes.\n */\nconst useCombineByIds = <T>(ids: string[]) => {\n const idsKey = JSON.stringify(ids);\n return useCallback(\n (results: Array<UseQueryResult<T, Error>>): ExperimentQueriesResult<T> => {\n const data: Record<string, T | undefined> = {};\n (JSON.parse(idsKey) as string[]).forEach((id, index) => {\n data[id] = results[index]?.data;\n });\n return {\n data,\n isLoading: results.some(result => result.isLoading),\n error: results.find(result => result.error)?.error ?? null,\n };\n },\n [idsKey],\n );\n};\n\n/** An experiment id plus its status, which drives polling of its dependent queries. */\nexport interface ExperimentRef {\n id: string;\n status?: ExperimentStatus;\n}\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetExperiment = <TData = DatasetExperimentResponse>({\n datasetId,\n experimentId,\n queryOptions,\n}: {\n datasetId: string;\n experimentId: string;\n queryOptions?: MastraQueryOptions<DatasetExperimentResponse, TData, DatasetExperimentQueryKey>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n const { queryKey, queryFn, gcTime, staleTime, refetchInterval } = datasetExperimentQueryOptions(\n client,\n datasetId,\n experimentId,\n );\n return useQuery<DatasetExperimentResponse, Error, TData, DatasetExperimentQueryKey>({\n queryKey,\n queryFn,\n gcTime,\n staleTime,\n refetchInterval,\n ...queryOptions,\n });\n};\n\n/**\n * Fetches several experiments of one dataset in parallel, each polled while it runs.\n * The server 404s an experiment that does not belong to `datasetId`, which surfaces as `error`.\n */\nexport const useDatasetExperimentsQueries = ({\n datasetId,\n experimentIds,\n}: {\n datasetId: string;\n experimentIds: string[];\n}): ExperimentQueriesResult<DatasetExperimentResponse> => {\n const client = useMastraClient();\n const combine = useCombineByIds<DatasetExperimentResponse>(experimentIds);\n return useQueries({\n queries: experimentIds.map(id => datasetExperimentQueryOptions(client, datasetId, id)),\n combine,\n });\n};\n\nexport type ExperimentResultsOrderBy = NonNullable<\n NonNullable<Parameters<MastraClient['listDatasetExperimentResults']>[2]>['orderBy']\n>;\n\ninterface UseDatasetExperimentResultsParams<TData = DatasetExperimentResult[]> {\n datasetId: string;\n experimentId: string;\n experimentStatus?: ExperimentStatus;\n orderBy?: ExperimentResultsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ExperimentResultsPage, TData, QueryKey, number>;\n}\n\n/**\n * Hook to list results for a dataset experiment with infinite scroll pagination.\n * Polls every 2 seconds while experiment status is 'pending' or 'running'.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetExperimentResults = <TData = DatasetExperimentResult[]>({\n datasetId,\n experimentId,\n experimentStatus,\n orderBy,\n queryOptions,\n}: UseDatasetExperimentResultsParams<TData>): UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n} => {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n\n const query = useInfiniteQuery({\n queryKey: ['dataset-experiment-results', datasetId, experimentId, experimentStatus, orderBy],\n queryFn: async ({ pageParam }) => {\n return client.listDatasetExperimentResults(datasetId, experimentId, {\n page: pageParam,\n perPage: RESULTS_PER_PAGE,\n orderBy,\n });\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.results?.length) {\n return undefined;\n }\n const totalFetched = (lastPageParam + 1) * RESULTS_PER_PAGE;\n const total = lastPage?.pagination?.total ?? 0;\n if (totalFetched >= total) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false,\n select: (data: InfiniteData<ExperimentResultsPage, number>) => {\n return data.pages.flatMap(page => page?.results ?? []) as TData;\n },\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n};\n\n/**\n * Fetches every result (all pages) of several experiments of one dataset in parallel.\n * Each experiment is polled while its `status` is in progress.\n */\nexport const useAllDatasetExperimentResultsQueries = ({\n datasetId,\n experiments,\n}: {\n datasetId: string;\n experiments: ExperimentRef[];\n}): ExperimentQueriesResult<DatasetExperimentResult[]> => {\n const client = useMastraClient();\n const combine = useCombineByIds<DatasetExperimentResult[]>(experiments.map(experiment => experiment.id));\n return useQueries({\n queries: experiments.map(experiment =>\n allDatasetExperimentResultsQueryOptions(client, datasetId, experiment.id, experiment.status),\n ),\n combine,\n });\n};\n\n/**\n * Hook to fetch all scores for an experiment, transformed to Record<entityId, ClientScoreRowData[]>\n * Paginates through all pages to ensure no scores are silently dropped.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useScoresByExperimentId = <TData = ExperimentScoresByEntity>({\n experimentId,\n experimentStatus,\n queryOptions,\n}: {\n experimentId: string;\n experimentStatus?: ExperimentStatus;\n queryOptions?: MastraQueryOptions<ExperimentScoresByEntity, TData, ExperimentStatusQueryKey>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n const { queryKey, queryFn, refetchInterval } = experimentScoresQueryOptions(client, experimentId, experimentStatus);\n return useQuery<ExperimentScoresByEntity, Error, TData, ExperimentStatusQueryKey>({\n queryKey,\n queryFn,\n refetchInterval,\n ...queryOptions,\n });\n};\n\n/**\n * Fetches every score of several experiments in parallel, each grouped by dataset item id.\n * Each experiment is polled while its `status` is in progress.\n */\nexport const useScoresByExperimentIdsQueries = ({\n experiments,\n}: {\n experiments: ExperimentRef[];\n}): ExperimentQueriesResult<ExperimentScoresByEntity> => {\n const client = useMastraClient();\n const combine = useCombineByIds<ExperimentScoresByEntity>(experiments.map(experiment => experiment.id));\n return useQueries({\n queries: experiments.map(experiment => experimentScoresQueryOptions(client, experiment.id, experiment.status)),\n combine,\n });\n};\n","import type { DatasetItemVersionResponse } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\nexport type DatasetItemVersion = DatasetItemVersionResponse & {\n validTo: number | null;\n isDeleted: boolean;\n isLatest: boolean;\n};\n\n/**\n * Hook to fetch full item history (SCD-2 rows).\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItemVersions = <TData = DatasetItemVersion[]>({\n datasetId,\n itemId,\n queryOptions,\n}: {\n datasetId: string;\n itemId: string;\n queryOptions?: MastraQueryOptions<DatasetItemVersion[], TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['dataset-item-versions', datasetId, itemId],\n queryFn: async (): Promise<DatasetItemVersion[]> => {\n const res = await client.getItemHistory(datasetId, itemId);\n\n return (res?.history ?? []).map(\n (version, index): DatasetItemVersion => ({\n id: version.id,\n datasetId: version.datasetId,\n datasetVersion: version.datasetVersion,\n input: version.input,\n groundTruth: version.groundTruth,\n expectedTrajectory: version.expectedTrajectory,\n toolMocks: version.toolMocks ?? undefined,\n scorerIds: version.scorerIds ?? undefined,\n requestContext: version.requestContext ?? undefined,\n metadata: version.metadata ?? undefined,\n validTo: version.validTo,\n isDeleted: version.isDeleted,\n createdAt: version.createdAt,\n updatedAt: version.updatedAt,\n isLatest: index === 0,\n }),\n );\n },\n ...queryOptions,\n });\n};\n\n/**\n * Hook to fetch a specific version of a dataset item.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItemVersion = <TData = DatasetItemVersion>({\n datasetId,\n itemId,\n datasetVersion,\n latestVersion,\n queryOptions,\n}: {\n datasetId: string;\n itemId: string;\n datasetVersion: number;\n latestVersion?: number;\n queryOptions?: MastraQueryOptions<DatasetItemVersion, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['dataset-item-version', datasetId, itemId, datasetVersion],\n queryFn: async (): Promise<DatasetItemVersion> => {\n const v = await client.getDatasetItemVersion(datasetId, itemId, datasetVersion);\n\n return {\n id: v.id,\n datasetId: v.datasetId,\n datasetVersion: v.datasetVersion,\n input: v.input,\n groundTruth: v.groundTruth,\n expectedTrajectory: v.expectedTrajectory,\n toolMocks: v.toolMocks ?? undefined,\n scorerIds: v.scorerIds ?? undefined,\n requestContext: v.requestContext ?? undefined,\n metadata: v.metadata ?? undefined,\n validTo: null,\n isDeleted: false,\n createdAt: v.createdAt,\n updatedAt: v.updatedAt,\n isLatest: latestVersion != null ? datasetVersion === latestVersion : false,\n };\n },\n ...queryOptions,\n });\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions } from '../shared/query-options';\n\nexport interface DatasetVersion {\n id?: string;\n datasetId?: string;\n version: number;\n createdAt?: Date | string;\n isCurrent: boolean;\n}\n\ntype DatasetVersionsPage = Awaited<ReturnType<MastraClient['listDatasetVersions']>>;\n\nconst PER_PAGE = 10;\n\n/**\n * Hook to fetch dataset versions from the API with infinite pagination.\n * `data` defaults to the flattened `DatasetVersion[]`; a user `select` replaces that.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetVersions = <TData = DatasetVersion[]>({\n datasetId,\n queryOptions,\n}: {\n datasetId: string;\n queryOptions?: MastraInfiniteQueryOptions<DatasetVersionsPage, TData, QueryKey, number>;\n}) => {\n const client = useMastraClient();\n\n return useInfiniteQuery({\n queryKey: ['dataset-versions', datasetId],\n queryFn: async ({ pageParam }) => {\n return client.listDatasetVersions(datasetId, { page: pageParam, perPage: PER_PAGE });\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (lastPage?.pagination?.hasMore) {\n return lastPageParam + 1;\n }\n return undefined;\n },\n select: (data: InfiniteData<DatasetVersionsPage, number>) => {\n return data.pages\n .flatMap(page => page?.versions ?? [])\n .map(\n (v, index): DatasetVersion => ({\n id: v.id,\n datasetId: v.datasetId,\n version: v.version,\n createdAt: v.createdAt,\n isCurrent: index === 0,\n }),\n ) as TData;\n },\n ...queryOptions,\n });\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\ntype GetExperimentResponse = Awaited<ReturnType<MastraClient['getExperiment']>>;\n\n/**\n * Hook to list all experiments across all datasets with optional pagination\n */\nexport const useExperiments = <TData = ListExperimentsResponse>({\n pagination,\n queryOptions,\n}: {\n pagination?: { page?: number; perPage?: number };\n queryOptions?: MastraQueryOptions<ListExperimentsResponse, TData>;\n} = {}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['experiments', pagination],\n queryFn: () => client.listExperiments(pagination),\n ...queryOptions,\n });\n};\n\n/**\n * Hook to fetch a single experiment by ID without knowing its dataset\n */\nexport const useExperiment = <TData = GetExperimentResponse>({\n experimentId,\n queryOptions,\n}: {\n experimentId: string;\n queryOptions?: MastraQueryOptions<GetExperimentResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['experiment', experimentId],\n queryFn: () => client.getExperiment(experimentId),\n ...queryOptions,\n });\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype WorkflowSchemaResponse = Awaited<ReturnType<ReturnType<MastraClient['getWorkflow']>['getSchema']>>;\n\n/**\n * Hook to fetch workflow input/output schema by workflow ID.\n * Returns { inputSchema, outputSchema } where each is Record<string, unknown> | null.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport function useWorkflowSchema<TData = WorkflowSchemaResponse>({\n workflowId,\n queryOptions,\n}: {\n workflowId: string | null;\n queryOptions?: MastraQueryOptions<WorkflowSchemaResponse, TData>;\n}): UseQueryResult<TData, Error> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['workflow-schema', workflowId],\n queryFn: async () => {\n if (!workflowId) throw new Error('No workflow selected');\n return client.getWorkflow(workflowId).getSchema();\n },\n staleTime: 5 * 60 * 1000, // Cache for 5 minutes\n ...queryOptions,\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["PER_PAGE","tanstackQueryOptions"],"sources":["../../../src/hooks/datasets/use-dataset-items.ts","../../../src/hooks/datasets/use-dataset-mutations.ts","../../../src/hooks/datasets/use-datasets.ts","../../../src/hooks/datasets/use-compare-experiments.ts","../../../src/hooks/datasets/use-dataset-experiments.ts","../../../src/hooks/datasets/use-dataset-item-versions.ts","../../../src/hooks/datasets/use-dataset-versions.ts","../../../src/hooks/datasets/use-experiments.ts","../../../src/hooks/datasets/use-workflow-schema.ts"],"sourcesContent":["import type { MastraClient } from '@mastra/client-js';\nimport { useQuery, useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult, UseQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\n\n/**\n * Hook to fetch a single dataset item by ID\n */\ntype DatasetItemResponse = Awaited<ReturnType<MastraClient['getDatasetItem']>>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItem = <TData = DatasetItemResponse>({\n datasetId,\n itemId,\n queryOptions,\n}: {\n datasetId: string;\n itemId: string;\n queryOptions?: MastraQueryOptions<DatasetItemResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['dataset-item', datasetId, itemId],\n queryFn: () => client.getDatasetItem(datasetId, itemId),\n retry: false, // Don't retry 404s for deleted items\n ...queryOptions,\n });\n};\n\nconst PER_PAGE = 10;\n\ntype ListDatasetItemsResponse = Awaited<ReturnType<MastraClient['listDatasetItems']>>;\n\nexport type UseDatasetItemsResult = Omit<\n UseInfiniteQueryResult<InfiniteData<ListDatasetItemsResponse>, Error>,\n 'data'\n> & {\n data: ListDatasetItemsResponse['items'];\n total: number | undefined;\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n};\n\n/**\n * Hook to list items in a dataset with infinite scroll pagination and optional search\n * @param version - Optional version timestamp to view historical snapshot\n */\nexport type DatasetItemsOrderBy = NonNullable<NonNullable<Parameters<MastraClient['listDatasetItems']>[1]>['orderBy']>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItems = ({\n datasetId,\n search,\n version,\n orderBy,\n queryOptions,\n}: {\n datasetId: string;\n search?: string;\n version?: number | null;\n orderBy?: DatasetItemsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<\n ListDatasetItemsResponse,\n InfiniteData<ListDatasetItemsResponse, number>,\n QueryKey,\n number\n >;\n}): UseDatasetItemsResult => {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n\n const query = useInfiniteQuery({\n queryKey: ['dataset-items', datasetId, search, version, orderBy],\n queryFn: async ({ pageParam }) => {\n const res = await client.listDatasetItems(datasetId, {\n page: pageParam,\n perPage: PER_PAGE,\n search: search || undefined,\n version: version || undefined,\n orderBy,\n });\n return res;\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.items?.length) {\n return undefined;\n }\n const totalFetched = (lastPageParam + 1) * PER_PAGE;\n const total = lastPage?.pagination?.total ?? 0;\n if (totalFetched >= total) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n retry: false,\n ...queryOptions,\n });\n\n const items = query.data?.pages.flatMap(page => page?.items ?? []) ?? [];\n const total = query.data?.pages[0]?.pagination?.total;\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, data: items, total, setEndOfListElement };\n};\n","import type {\n CreateDatasetParams,\n UpdateDatasetParams,\n AddDatasetItemParams,\n UpdateDatasetItemParams,\n TriggerDatasetExperimentParams,\n UpdateDatasetExperimentParams,\n UpdateExperimentResultParams,\n BatchInsertDatasetItemsParams,\n BatchDeleteDatasetItemsParams,\n MastraClient,\n} from '@mastra/client-js';\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraMutationOptions } from '../shared/query-options';\n\ntype DatasetItemMutationVariables = {\n datasetId: string;\n itemId: string;\n};\n\ntype ClientResult<K extends keyof MastraClient> = MastraClient[K] extends (...args: any[]) => Promise<infer R>\n ? R\n : never;\n\nexport interface DatasetMutationsQueryOptions {\n createDataset?: MastraMutationOptions<ClientResult<'createDataset'>, CreateDatasetParams>;\n updateDataset?: MastraMutationOptions<ClientResult<'updateDataset'>, UpdateDatasetParams>;\n deleteDataset?: MastraMutationOptions<ClientResult<'deleteDataset'>, string>;\n addItem?: MastraMutationOptions<ClientResult<'addDatasetItem'>, AddDatasetItemParams>;\n updateItem?: MastraMutationOptions<ClientResult<'updateDatasetItem'>, UpdateDatasetItemParams>;\n deleteItem?: MastraMutationOptions<ClientResult<'deleteDatasetItem'>, DatasetItemMutationVariables>;\n purgeItem?: MastraMutationOptions<ClientResult<'purgeDatasetItem'>, DatasetItemMutationVariables>;\n deleteItems?: MastraMutationOptions<\n ClientResult<'batchDeleteDatasetItems'>,\n { datasetId: string; itemIds: string[] }\n >;\n batchInsertItems?: MastraMutationOptions<ClientResult<'batchInsertDatasetItems'>, BatchInsertDatasetItemsParams>;\n batchDeleteItems?: MastraMutationOptions<ClientResult<'batchDeleteDatasetItems'>, BatchDeleteDatasetItemsParams>;\n triggerExperiment?: MastraMutationOptions<ClientResult<'triggerDatasetExperiment'>, TriggerDatasetExperimentParams>;\n deleteExperiment?: MastraMutationOptions<ClientResult<'deleteExperiment'>, string>;\n updateExperiment?: MastraMutationOptions<ClientResult<'updateDatasetExperiment'>, UpdateDatasetExperimentParams>;\n updateExperimentResult?: MastraMutationOptions<\n ClientResult<'updateDatasetExperimentResult'>,\n UpdateExperimentResultParams\n >;\n}\n\n/**\n * Hook providing mutation functions for datasets, items, and runs\n * All mutations invalidate relevant query caches on success.\n * `queryOptions` is keyed by returned mutation name and spread last; a user `onSuccess` replaces the internal invalidation.\n */\nexport const useDatasetMutations = ({ queryOptions }: { queryOptions?: DatasetMutationsQueryOptions } = {}) => {\n const client = useMastraClient();\n const queryClient = useQueryClient();\n\n const createDataset = useMutation({\n mutationFn: (params: CreateDatasetParams) => client.createDataset(params),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['datasets'] });\n },\n ...queryOptions?.createDataset,\n });\n\n const updateDataset = useMutation({\n mutationFn: (params: UpdateDatasetParams) => client.updateDataset(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['datasets'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n },\n ...queryOptions?.updateDataset,\n });\n\n const deleteDataset = useMutation({\n mutationFn: (datasetId: string) => client.deleteDataset(datasetId),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['datasets'] });\n },\n ...queryOptions?.deleteDataset,\n });\n\n const addItem = useMutation({\n mutationFn: (params: AddDatasetItemParams) => client.addDatasetItem(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.addItem,\n });\n\n const updateItem = useMutation({\n mutationFn: (params: UpdateDatasetItemParams) => client.updateDatasetItem(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-item', variables.datasetId, variables.itemId] });\n void queryClient.invalidateQueries({\n queryKey: ['dataset-item-versions', variables.datasetId, variables.itemId],\n });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.updateItem,\n });\n\n const deleteItem = useMutation({\n mutationFn: ({ datasetId, itemId }: DatasetItemMutationVariables) => client.deleteDatasetItem(datasetId, itemId),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.deleteItem,\n });\n\n const purgeItem = useMutation({\n mutationFn: ({ datasetId, itemId }: DatasetItemMutationVariables) => client.purgeDatasetItem(datasetId, itemId),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-item', variables.datasetId, variables.itemId] });\n void queryClient.invalidateQueries({\n queryKey: ['dataset-item-versions', variables.datasetId, variables.itemId],\n });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-completed-items'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-review-summary'] });\n },\n ...queryOptions?.purgeItem,\n });\n\n // Batch insert items using the batch endpoint\n const batchInsertItems = useMutation({\n mutationFn: (params: BatchInsertDatasetItemsParams) => client.batchInsertDatasetItems(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.batchInsertItems,\n });\n\n // Batch delete items using the batch endpoint\n const batchDeleteItems = useMutation({\n mutationFn: (params: BatchDeleteDatasetItemsParams) => client.batchDeleteDatasetItems(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.batchDeleteItems,\n });\n\n // @deprecated - use batchDeleteItems mutation instead\n const deleteItems = useMutation({\n mutationFn: async ({ datasetId, itemIds }: { datasetId: string; itemIds: string[] }) => {\n return client.batchDeleteDatasetItems({ datasetId, itemIds });\n },\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-items', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset', variables.datasetId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-versions', variables.datasetId] });\n },\n ...queryOptions?.deleteItems,\n });\n\n const triggerExperiment = useMutation({\n mutationFn: (params: TriggerDatasetExperimentParams) => client.triggerDatasetExperiment(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiments', variables.datasetId] });\n },\n ...queryOptions?.triggerExperiment,\n });\n\n const deleteExperiment = useMutation({\n mutationFn: (experimentId: string) => client.deleteExperiment(experimentId),\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['experiments'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiments'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['completed-items'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-review-summary'] });\n },\n ...queryOptions?.deleteExperiment,\n });\n\n const updateExperiment = useMutation({\n mutationFn: (params: UpdateDatasetExperimentParams) => client.updateDatasetExperiment(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['experiments'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment', variables.experimentId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiments', variables.datasetId] });\n void queryClient.invalidateQueries({\n queryKey: ['dataset-experiment', variables.datasetId, variables.experimentId],\n });\n },\n ...queryOptions?.updateExperiment,\n });\n\n const updateExperimentResult = useMutation({\n mutationFn: (params: UpdateExperimentResultParams) => client.updateDatasetExperimentResult(params),\n onSuccess: (_, variables) => {\n void queryClient.invalidateQueries({ queryKey: ['experiment-results', variables.experimentId] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-experiment-results'] });\n void queryClient.invalidateQueries({ queryKey: ['review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-review-items'] });\n void queryClient.invalidateQueries({ queryKey: ['dataset-completed-items'] });\n void queryClient.invalidateQueries({ queryKey: ['experiment-review-summary'] });\n },\n ...queryOptions?.updateExperimentResult,\n });\n\n return {\n createDataset,\n updateDataset,\n deleteDataset,\n addItem,\n updateItem,\n deleteItem,\n purgeItem,\n deleteItems,\n batchInsertItems,\n batchDeleteItems,\n triggerExperiment,\n deleteExperiment,\n updateExperiment,\n updateExperimentResult,\n };\n};\n","import type { ExperimentTargetType, ListDatasetsParams, MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery, useQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult, UseQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\n\ntype ListDatasetsResponse = Awaited<ReturnType<MastraClient['listDatasets']>>;\ntype DatasetResponse = Awaited<ReturnType<MastraClient['getDataset']>>;\n\n/**\n * Hook to list all datasets with optional pagination\n */\nexport const useDatasets = <TData = ListDatasetsResponse>({\n pagination,\n queryOptions,\n}: {\n pagination?: { page?: number; perPage?: number };\n queryOptions?: MastraQueryOptions<ListDatasetsResponse, TData>;\n} = {}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['datasets', pagination],\n queryFn: () => client.listDatasets(pagination),\n placeholderData: previousData => previousData,\n ...queryOptions,\n });\n};\n\nconst DATASETS_PER_PAGE = 20;\n\nexport interface DatasetTargetFilter {\n targetType?: ExperimentTargetType | '';\n targetId?: string;\n}\n\nexport type DatasetsOrderBy = NonNullable<ListDatasetsParams['orderBy']>;\n\ntype DatasetRecord = ListDatasetsResponse['datasets'][number];\n\nexport type UseInfiniteDatasetsResult<TData = DatasetRecord[]> = UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n};\n\n/**\n * Hook to list datasets with infinite scroll pagination, optionally scoped server-side to a target.\n * `data` defaults to the flattened dataset list; a user `select` replaces that flattening.\n */\nexport const useInfiniteDatasets = <TData = DatasetRecord[]>({\n filter,\n orderBy,\n queryOptions,\n}: {\n filter?: DatasetTargetFilter;\n orderBy?: DatasetsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ListDatasetsResponse, TData, QueryKey, number>;\n} = {}): UseInfiniteDatasetsResult<TData> => {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n const targetType = filter?.targetType || undefined;\n const targetIds = filter?.targetId ? [filter.targetId] : undefined;\n\n const query = useInfiniteQuery({\n queryKey: ['datasets', 'infinite', { targetType, targetIds, orderBy }],\n queryFn: ({ pageParam }) =>\n client.listDatasets({ page: pageParam, perPage: DATASETS_PER_PAGE, targetType, targetIds, orderBy }),\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.datasets?.length || !lastPage.pagination?.hasMore) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n select: (data: InfiniteData<ListDatasetsResponse, number>) =>\n data.pages.flatMap(page => page?.datasets ?? []) as TData,\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n};\n\n/**\n * Hook to fetch a single dataset by ID\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDataset = <TData = DatasetResponse>({\n datasetId,\n queryOptions,\n}: {\n datasetId: string;\n queryOptions?: MastraQueryOptions<DatasetResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['dataset', datasetId],\n queryFn: () => client.getDataset(datasetId),\n ...queryOptions,\n });\n};\n","import type { CompareExperimentsResponse } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\n/**\n * Hook to compare two to ten dataset experiments item by item against a baseline.\n * @param datasetId - ID of the dataset\n * @param experimentIds - IDs of the experiments to compare\n * @param baselineId - ID of the baseline experiment; must be one of `experimentIds` (defaults to the first)\n * @param queryOptions - TanStack Query options, spread last to override defaults\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useCompareExperiments = <TData = CompareExperimentsResponse>({\n datasetId,\n experimentIds,\n baselineId,\n queryOptions,\n}: {\n datasetId: string;\n experimentIds: string[];\n baselineId?: string;\n queryOptions?: MastraQueryOptions<CompareExperimentsResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['compare-experiments', datasetId, experimentIds, baselineId],\n queryFn: () => client.compareExperiments({ datasetId, experimentIds, baselineId }),\n ...queryOptions,\n });\n};\n","import type { ClientScoreRowData, DatasetExperimentResult, MastraClient } from '@mastra/client-js';\nimport type { ExperimentStatus } from '@mastra/core/storage';\nimport { queryOptions as tanstackQueryOptions, useInfiniteQuery, useQueries, useQuery } from '@tanstack/react-query';\nimport type {\n InfiniteData,\n QueryKey,\n UseInfiniteQueryResult,\n UseQueryOptions,\n UseQueryResult,\n} from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport { useCombineByIds } from '../shared/combine-by-ids';\nimport type { ExperimentQueriesResult } from '../shared/combine-by-ids';\nimport type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options';\n\nexport type { ExperimentQueriesResult } from '../shared/combine-by-ids';\nimport { useInView } from '../shared/use-in-view';\n\ntype DatasetExperimentResponse = Awaited<ReturnType<MastraClient['getDatasetExperiment']>>;\ntype ExperimentResultsPage = Awaited<ReturnType<MastraClient['listDatasetExperimentResults']>>;\ntype ExperimentScoresByEntity = Record<string, ClientScoreRowData[]>;\ntype DatasetExperimentQueryKey = string[];\ntype ExperimentStatusQueryKey = (string | undefined)[];\n\nconst POLL_INTERVAL_MS = 2000;\nconst RESULTS_PER_PAGE = 100;\nconst SCORES_PER_PAGE = 100;\n\nconst isInProgress = (status: string | undefined) => status === 'running' || status === 'pending';\n\n/**\n * Key, fetcher and polling policy of the `dataset-experiment` query, shared by the single and\n * multi-experiment hooks so they hit the same cache entry.\n * Polls every 2 seconds while the experiment is 'running' or 'pending'.\n */\nexport const datasetExperimentQueryOptions = (\n client: MastraClient,\n datasetId: string,\n experimentId: string,\n): UseQueryOptions<DatasetExperimentResponse, Error, DatasetExperimentResponse, DatasetExperimentQueryKey> =>\n tanstackQueryOptions({\n queryKey: ['dataset-experiment', datasetId, experimentId],\n queryFn: () => client.getDatasetExperiment(datasetId, experimentId),\n gcTime: 0,\n staleTime: 0,\n refetchInterval: query => (isInProgress(query.state.data?.status) ? POLL_INTERVAL_MS : false),\n });\n\n/**\n * Key and fetcher of the `dataset-experiment-scores` query: every score of an experiment, across all\n * pages, grouped by dataset item id. Polls every 2 seconds while `experimentStatus` is in progress.\n */\nexport const experimentScoresQueryOptions = (\n client: MastraClient,\n experimentId: string,\n experimentStatus: ExperimentStatus | undefined,\n): UseQueryOptions<ExperimentScoresByEntity, Error, ExperimentScoresByEntity, ExperimentStatusQueryKey> =>\n tanstackQueryOptions({\n queryKey: ['dataset-experiment-scores', experimentId, experimentStatus],\n queryFn: async (): Promise<ExperimentScoresByEntity> => {\n const allScores: ClientScoreRowData[] = [];\n let page = 0;\n\n while (true) {\n const response = await client.listScoresByRunId({ runId: experimentId, page, perPage: SCORES_PER_PAGE });\n allScores.push(...response.scores);\n if (!response.pagination.hasMore) break;\n page++;\n }\n\n const grouped: ExperimentScoresByEntity = {};\n for (const row of allScores) {\n (grouped[row.entityId] ??= []).push(row);\n }\n return grouped;\n },\n refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false,\n });\n\n/**\n * Key and fetcher of the `dataset-experiment-results-all` query: every result of an experiment, across\n * all pages. Polls every 2 seconds while `experimentStatus` is in progress.\n */\nexport const allDatasetExperimentResultsQueryOptions = (\n client: MastraClient,\n datasetId: string,\n experimentId: string,\n experimentStatus: ExperimentStatus | undefined,\n): UseQueryOptions<DatasetExperimentResult[], Error, DatasetExperimentResult[], ExperimentStatusQueryKey> =>\n tanstackQueryOptions({\n queryKey: ['dataset-experiment-results-all', datasetId, experimentId, experimentStatus],\n queryFn: async (): Promise<DatasetExperimentResult[]> => {\n const allResults: DatasetExperimentResult[] = [];\n let page = 0;\n\n while (true) {\n const response = await client.listDatasetExperimentResults(datasetId, experimentId, {\n page,\n perPage: RESULTS_PER_PAGE,\n });\n allResults.push(...response.results);\n if (!response.pagination.hasMore || response.results.length === 0) break;\n page++;\n }\n\n return allResults;\n },\n refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false,\n });\n\n/** An experiment id plus its status, which drives polling of its dependent queries. */\nexport interface ExperimentRef {\n id: string;\n status?: ExperimentStatus;\n}\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetExperiment = <TData = DatasetExperimentResponse>({\n datasetId,\n experimentId,\n queryOptions,\n}: {\n datasetId: string;\n experimentId: string;\n queryOptions?: MastraQueryOptions<DatasetExperimentResponse, TData, DatasetExperimentQueryKey>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n const { queryKey, queryFn, gcTime, staleTime, refetchInterval } = datasetExperimentQueryOptions(\n client,\n datasetId,\n experimentId,\n );\n return useQuery<DatasetExperimentResponse, Error, TData, DatasetExperimentQueryKey>({\n queryKey,\n queryFn,\n gcTime,\n staleTime,\n refetchInterval,\n ...queryOptions,\n });\n};\n\n/**\n * Fetches several experiments of one dataset in parallel, each polled while it runs.\n * The server 404s an experiment that does not belong to `datasetId`, which surfaces as `error`.\n */\nexport const useDatasetExperimentsQueries = ({\n datasetId,\n experimentIds,\n}: {\n datasetId: string;\n experimentIds: string[];\n}): ExperimentQueriesResult<DatasetExperimentResponse> => {\n const client = useMastraClient();\n const combine = useCombineByIds<DatasetExperimentResponse>(experimentIds);\n return useQueries({\n queries: experimentIds.map(id => datasetExperimentQueryOptions(client, datasetId, id)),\n combine,\n });\n};\n\nexport type ExperimentResultsOrderBy = NonNullable<\n NonNullable<Parameters<MastraClient['listDatasetExperimentResults']>[2]>['orderBy']\n>;\n\ninterface UseDatasetExperimentResultsParams<TData = DatasetExperimentResult[]> {\n datasetId: string;\n experimentId: string;\n experimentStatus?: ExperimentStatus;\n orderBy?: ExperimentResultsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ExperimentResultsPage, TData, QueryKey, number>;\n}\n\n/**\n * Hook to list results for a dataset experiment with infinite scroll pagination.\n * Polls every 2 seconds while experiment status is 'pending' or 'running'.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetExperimentResults = <TData = DatasetExperimentResult[]>({\n datasetId,\n experimentId,\n experimentStatus,\n orderBy,\n queryOptions,\n}: UseDatasetExperimentResultsParams<TData>): UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n} => {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n\n const query = useInfiniteQuery({\n queryKey: ['dataset-experiment-results', datasetId, experimentId, experimentStatus, orderBy],\n queryFn: async ({ pageParam }) => {\n return client.listDatasetExperimentResults(datasetId, experimentId, {\n page: pageParam,\n perPage: RESULTS_PER_PAGE,\n orderBy,\n });\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.results?.length) {\n return undefined;\n }\n const totalFetched = (lastPageParam + 1) * RESULTS_PER_PAGE;\n const total = lastPage?.pagination?.total ?? 0;\n if (totalFetched >= total) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n refetchInterval: isInProgress(experimentStatus) ? POLL_INTERVAL_MS : false,\n select: (data: InfiniteData<ExperimentResultsPage, number>) => {\n return data.pages.flatMap(page => page?.results ?? []) as TData;\n },\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n};\n\n/**\n * Fetches every result (all pages) of several experiments of one dataset in parallel.\n * Each experiment is polled while its `status` is in progress.\n */\nexport const useAllDatasetExperimentResultsQueries = ({\n datasetId,\n experiments,\n}: {\n datasetId: string;\n experiments: ExperimentRef[];\n}): ExperimentQueriesResult<DatasetExperimentResult[]> => {\n const client = useMastraClient();\n const combine = useCombineByIds<DatasetExperimentResult[]>(experiments.map(experiment => experiment.id));\n return useQueries({\n queries: experiments.map(experiment =>\n allDatasetExperimentResultsQueryOptions(client, datasetId, experiment.id, experiment.status),\n ),\n combine,\n });\n};\n\n/**\n * Hook to fetch all scores for an experiment, transformed to Record<entityId, ClientScoreRowData[]>\n * Paginates through all pages to ensure no scores are silently dropped.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useScoresByExperimentId = <TData = ExperimentScoresByEntity>({\n experimentId,\n experimentStatus,\n queryOptions,\n}: {\n experimentId: string;\n experimentStatus?: ExperimentStatus;\n queryOptions?: MastraQueryOptions<ExperimentScoresByEntity, TData, ExperimentStatusQueryKey>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n const { queryKey, queryFn, refetchInterval } = experimentScoresQueryOptions(client, experimentId, experimentStatus);\n return useQuery<ExperimentScoresByEntity, Error, TData, ExperimentStatusQueryKey>({\n queryKey,\n queryFn,\n refetchInterval,\n ...queryOptions,\n });\n};\n\n/**\n * Fetches every score of several experiments in parallel, each grouped by dataset item id.\n * Each experiment is polled while its `status` is in progress.\n */\nexport const useScoresByExperimentIdsQueries = ({\n experiments,\n}: {\n experiments: ExperimentRef[];\n}): ExperimentQueriesResult<ExperimentScoresByEntity> => {\n const client = useMastraClient();\n const combine = useCombineByIds<ExperimentScoresByEntity>(experiments.map(experiment => experiment.id));\n return useQueries({\n queries: experiments.map(experiment => experimentScoresQueryOptions(client, experiment.id, experiment.status)),\n combine,\n });\n};\n","import type { DatasetItemVersionResponse } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\nexport type DatasetItemVersion = DatasetItemVersionResponse & {\n validTo: number | null;\n isDeleted: boolean;\n isLatest: boolean;\n};\n\n/**\n * Hook to fetch full item history (SCD-2 rows).\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItemVersions = <TData = DatasetItemVersion[]>({\n datasetId,\n itemId,\n queryOptions,\n}: {\n datasetId: string;\n itemId: string;\n queryOptions?: MastraQueryOptions<DatasetItemVersion[], TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['dataset-item-versions', datasetId, itemId],\n queryFn: async (): Promise<DatasetItemVersion[]> => {\n const res = await client.getItemHistory(datasetId, itemId);\n\n return (res?.history ?? []).map(\n (version, index): DatasetItemVersion => ({\n id: version.id,\n datasetId: version.datasetId,\n datasetVersion: version.datasetVersion,\n input: version.input,\n groundTruth: version.groundTruth,\n expectedTrajectory: version.expectedTrajectory,\n toolMocks: version.toolMocks ?? undefined,\n scorerIds: version.scorerIds ?? undefined,\n requestContext: version.requestContext ?? undefined,\n metadata: version.metadata ?? undefined,\n validTo: version.validTo,\n isDeleted: version.isDeleted,\n createdAt: version.createdAt,\n updatedAt: version.updatedAt,\n isLatest: index === 0,\n }),\n );\n },\n ...queryOptions,\n });\n};\n\n/**\n * Hook to fetch a specific version of a dataset item.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetItemVersion = <TData = DatasetItemVersion>({\n datasetId,\n itemId,\n datasetVersion,\n latestVersion,\n queryOptions,\n}: {\n datasetId: string;\n itemId: string;\n datasetVersion: number;\n latestVersion?: number;\n queryOptions?: MastraQueryOptions<DatasetItemVersion, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['dataset-item-version', datasetId, itemId, datasetVersion],\n queryFn: async (): Promise<DatasetItemVersion> => {\n const v = await client.getDatasetItemVersion(datasetId, itemId, datasetVersion);\n\n return {\n id: v.id,\n datasetId: v.datasetId,\n datasetVersion: v.datasetVersion,\n input: v.input,\n groundTruth: v.groundTruth,\n expectedTrajectory: v.expectedTrajectory,\n toolMocks: v.toolMocks ?? undefined,\n scorerIds: v.scorerIds ?? undefined,\n requestContext: v.requestContext ?? undefined,\n metadata: v.metadata ?? undefined,\n validTo: null,\n isDeleted: false,\n createdAt: v.createdAt,\n updatedAt: v.updatedAt,\n isLatest: latestVersion != null ? datasetVersion === latestVersion : false,\n };\n },\n ...queryOptions,\n });\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions } from '../shared/query-options';\n\nexport interface DatasetVersion {\n id?: string;\n datasetId?: string;\n version: number;\n createdAt?: Date | string;\n isCurrent: boolean;\n}\n\ntype DatasetVersionsPage = Awaited<ReturnType<MastraClient['listDatasetVersions']>>;\n\nconst PER_PAGE = 10;\n\n/**\n * Hook to fetch dataset versions from the API with infinite pagination.\n * `data` defaults to the flattened `DatasetVersion[]`; a user `select` replaces that.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useDatasetVersions = <TData = DatasetVersion[]>({\n datasetId,\n queryOptions,\n}: {\n datasetId: string;\n queryOptions?: MastraInfiniteQueryOptions<DatasetVersionsPage, TData, QueryKey, number>;\n}) => {\n const client = useMastraClient();\n\n return useInfiniteQuery({\n queryKey: ['dataset-versions', datasetId],\n queryFn: async ({ pageParam }) => {\n return client.listDatasetVersions(datasetId, { page: pageParam, perPage: PER_PAGE });\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (lastPage?.pagination?.hasMore) {\n return lastPageParam + 1;\n }\n return undefined;\n },\n select: (data: InfiniteData<DatasetVersionsPage, number>) => {\n return data.pages\n .flatMap(page => page?.versions ?? [])\n .map(\n (v, index): DatasetVersion => ({\n id: v.id,\n datasetId: v.datasetId,\n version: v.version,\n createdAt: v.createdAt,\n isCurrent: index === 0,\n }),\n ) as TData;\n },\n ...queryOptions,\n });\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\ntype GetExperimentResponse = Awaited<ReturnType<MastraClient['getExperiment']>>;\n\n/**\n * Hook to list all experiments across all datasets with optional pagination\n */\nexport const useExperiments = <TData = ListExperimentsResponse>({\n pagination,\n queryOptions,\n}: {\n pagination?: { page?: number; perPage?: number };\n queryOptions?: MastraQueryOptions<ListExperimentsResponse, TData>;\n} = {}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['experiments', pagination],\n queryFn: () => client.listExperiments(pagination),\n ...queryOptions,\n });\n};\n\n/**\n * Hook to fetch a single experiment by ID without knowing its dataset\n */\nexport const useExperiment = <TData = GetExperimentResponse>({\n experimentId,\n queryOptions,\n}: {\n experimentId: string;\n queryOptions?: MastraQueryOptions<GetExperimentResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n return useQuery({\n queryKey: ['experiment', experimentId],\n queryFn: () => client.getExperiment(experimentId),\n ...queryOptions,\n });\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype WorkflowSchemaResponse = Awaited<ReturnType<ReturnType<MastraClient['getWorkflow']>['getSchema']>>;\n\n/**\n * Hook to fetch workflow input/output schema by workflow ID.\n * Returns { inputSchema, outputSchema } where each is Record<string, unknown> | null.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport function useWorkflowSchema<TData = WorkflowSchemaResponse>({\n workflowId,\n queryOptions,\n}: {\n workflowId: string | null;\n queryOptions?: MastraQueryOptions<WorkflowSchemaResponse, TData>;\n}): UseQueryResult<TData, Error> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['workflow-schema', workflowId],\n queryFn: async () => {\n if (!workflowId) throw new Error('No workflow selected');\n return client.getWorkflow(workflowId).getSchema();\n },\n staleTime: 5 * 60 * 1000, // Cache for 5 minutes\n ...queryOptions,\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { ClientScoreRowData, DatasetExperimentResult, MastraClient } from '@mastra/client-js';
|
|
2
2
|
import type { ExperimentStatus } from '@mastra/core/storage';
|
|
3
3
|
import type { QueryKey, UseInfiniteQueryResult, UseQueryOptions, UseQueryResult } from '@tanstack/react-query';
|
|
4
|
+
import type { ExperimentQueriesResult } from '../shared/combine-by-ids.js';
|
|
4
5
|
import type { MastraInfiniteQueryOptions, MastraQueryOptions } from '../shared/query-options.js';
|
|
6
|
+
export type { ExperimentQueriesResult } from '../shared/combine-by-ids.js';
|
|
5
7
|
type DatasetExperimentResponse = Awaited<ReturnType<MastraClient['getDatasetExperiment']>>;
|
|
6
8
|
type ExperimentResultsPage = Awaited<ReturnType<MastraClient['listDatasetExperimentResults']>>;
|
|
7
9
|
type ExperimentScoresByEntity = Record<string, ClientScoreRowData[]>;
|
|
@@ -23,14 +25,6 @@ export declare const experimentScoresQueryOptions: (client: MastraClient, experi
|
|
|
23
25
|
* all pages. Polls every 2 seconds while `experimentStatus` is in progress.
|
|
24
26
|
*/
|
|
25
27
|
export declare const allDatasetExperimentResultsQueryOptions: (client: MastraClient, datasetId: string, experimentId: string, experimentStatus: ExperimentStatus | undefined) => UseQueryOptions<DatasetExperimentResult[], Error, DatasetExperimentResult[], ExperimentStatusQueryKey>;
|
|
26
|
-
/** One entry per requested experiment id, in the order the ids were given. */
|
|
27
|
-
export interface ExperimentQueriesResult<T> {
|
|
28
|
-
data: Record<string, T | undefined>;
|
|
29
|
-
/** True while any experiment has not loaded yet. */
|
|
30
|
-
isLoading: boolean;
|
|
31
|
-
/** First error among the experiments, if any. */
|
|
32
|
-
error: Error | null;
|
|
33
|
-
}
|
|
34
28
|
/** An experiment id plus its status, which drives polling of its dependent queries. */
|
|
35
29
|
export interface ExperimentRef {
|
|
36
30
|
id: string;
|
|
@@ -95,5 +89,4 @@ export declare const useScoresByExperimentId: <TData = ExperimentScoresByEntity>
|
|
|
95
89
|
export declare const useScoresByExperimentIdsQueries: ({ experiments, }: {
|
|
96
90
|
experiments: ExperimentRef[];
|
|
97
91
|
}) => ExperimentQueriesResult<ExperimentScoresByEntity>;
|
|
98
|
-
export {};
|
|
99
92
|
//# sourceMappingURL=use-dataset-experiments.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-dataset-experiments.d.ts","sourceRoot":"","sources":["../../../src/hooks/datasets/use-dataset-experiments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACnG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,KAAK,EAEV,QAAQ,EACR,sBAAsB,EACtB,eAAe,EACf,cAAc,EACf,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"use-dataset-experiments.d.ts","sourceRoot":"","sources":["../../../src/hooks/datasets/use-dataset-experiments.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,80 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_mastra_client_context = require("../../mastra-client-context-DzX3f0RF.cjs");
|
|
3
3
|
const require_use_in_view = require("../../use-in-view-B6eJO9Zi.cjs");
|
|
4
|
+
const require_combine_by_ids = require("../../combine-by-ids-D_lp6Dvq.cjs");
|
|
5
|
+
const require_map = require("../../map-wjmL1y5O.cjs");
|
|
4
6
|
let react = require("react");
|
|
5
7
|
let _tanstack_react_query = require("@tanstack/react-query");
|
|
8
|
+
//#region src/hooks/experiments/use-experiment-item-usage.ts
|
|
9
|
+
const INPUT_TOKEN_METRIC = "mastra_model_total_input_tokens";
|
|
10
|
+
const OUTPUT_TOKEN_METRIC = "mastra_model_total_output_tokens";
|
|
11
|
+
const POLL_INTERVAL_MS = 2e3;
|
|
12
|
+
const createAccumulator = () => ({
|
|
13
|
+
estimatedCost: 0,
|
|
14
|
+
costUnits: /* @__PURE__ */ new Set(),
|
|
15
|
+
hasUnknownCostUnit: false
|
|
16
|
+
});
|
|
17
|
+
function accumulate(accumulator, tokenField, group) {
|
|
18
|
+
accumulator[tokenField] = (accumulator[tokenField] ?? 0) + group.value;
|
|
19
|
+
if (group.estimatedCost == null) return;
|
|
20
|
+
accumulator.estimatedCost += group.estimatedCost;
|
|
21
|
+
if (group.costUnit) accumulator.costUnits.add(group.costUnit.toLowerCase());
|
|
22
|
+
else accumulator.hasUnknownCostUnit = true;
|
|
23
|
+
}
|
|
24
|
+
function toUsage(accumulator) {
|
|
25
|
+
const isPriced = !accumulator.hasUnknownCostUnit && accumulator.costUnits.size === 1;
|
|
26
|
+
return {
|
|
27
|
+
inputTokens: accumulator.inputTokens,
|
|
28
|
+
outputTokens: accumulator.outputTokens,
|
|
29
|
+
estimatedCost: isPriced ? accumulator.estimatedCost : void 0,
|
|
30
|
+
costUnit: isPriced ? [...accumulator.costUnits][0] : void 0
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** Builds the experiment totals and the per-trace usage in a single pass over the groups. */
|
|
34
|
+
function toExperimentUsage(response) {
|
|
35
|
+
const summary = createAccumulator();
|
|
36
|
+
const accumulators = /* @__PURE__ */ new Map();
|
|
37
|
+
for (const group of response.groups) {
|
|
38
|
+
const metricName = group.dimensions.name;
|
|
39
|
+
if (metricName !== INPUT_TOKEN_METRIC && metricName !== OUTPUT_TOKEN_METRIC) continue;
|
|
40
|
+
const tokenField = metricName === INPUT_TOKEN_METRIC ? "inputTokens" : "outputTokens";
|
|
41
|
+
accumulate(summary, tokenField, group);
|
|
42
|
+
const traceId = group.dimensions.traceId;
|
|
43
|
+
if (traceId) accumulate(require_map.getOrCreate(accumulators, traceId, createAccumulator), tokenField, group);
|
|
44
|
+
}
|
|
45
|
+
const traces = {};
|
|
46
|
+
for (const [traceId, accumulator] of accumulators) traces[traceId] = toUsage(accumulator);
|
|
47
|
+
return {
|
|
48
|
+
summary: toUsage(summary),
|
|
49
|
+
traces
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Token and cost usage of several experiments, keyed by experiment id: each entry holds the
|
|
54
|
+
* experiment totals (`summary`) and every item's usage keyed by trace id (`traces`).
|
|
55
|
+
* Sends one metric breakdown request per experiment, filtered by its id rather than by trace ids,
|
|
56
|
+
* so it does not wait for the experiment results. Polls every 2 seconds while an experiment is
|
|
57
|
+
* running or pending. No request is made when the observability store cannot serve metrics.
|
|
58
|
+
*/
|
|
59
|
+
const useExperimentsItemUsage = ({ experiments, supportsMetrics }) => {
|
|
60
|
+
const client = require_mastra_client_context.useMastraClient();
|
|
61
|
+
const combine = require_combine_by_ids.useCombineByIds(experiments.map((experiment) => experiment.id));
|
|
62
|
+
return (0, _tanstack_react_query.useQueries)({
|
|
63
|
+
queries: experiments.map(({ id, status }) => ({
|
|
64
|
+
queryKey: ["experiment-item-usage", id],
|
|
65
|
+
queryFn: async () => toExperimentUsage(await client.getMetricBreakdown({
|
|
66
|
+
name: [INPUT_TOKEN_METRIC, OUTPUT_TOKEN_METRIC],
|
|
67
|
+
aggregation: "sum",
|
|
68
|
+
groupBy: ["traceId", "name"],
|
|
69
|
+
filters: { experimentId: id }
|
|
70
|
+
})),
|
|
71
|
+
enabled: supportsMetrics,
|
|
72
|
+
refetchInterval: status === "running" || status === "pending" ? POLL_INTERVAL_MS : false
|
|
73
|
+
})),
|
|
74
|
+
combine
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
//#endregion
|
|
6
78
|
//#region src/hooks/experiments/use-experiment-metrics.ts
|
|
7
79
|
/**
|
|
8
80
|
* Experiment-scoped metrics (tokens, cost, avg agent latency).
|
|
@@ -147,6 +219,7 @@ exports.EXPERIMENTS_PER_PAGE = EXPERIMENTS_PER_PAGE;
|
|
|
147
219
|
exports.useExperimentMetrics = useExperimentMetrics;
|
|
148
220
|
exports.useExperimentTrace = useExperimentTrace;
|
|
149
221
|
exports.useExperimentsForDatasetFilter = useExperimentsForDatasetFilter;
|
|
222
|
+
exports.useExperimentsItemUsage = useExperimentsItemUsage;
|
|
150
223
|
exports.useInfiniteExperiments = useInfiniteExperiments;
|
|
151
224
|
|
|
152
225
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["useMastraClient","useMastraClient","useMastraClient","useMastraClient","useInView"],"sources":["../../../src/hooks/experiments/use-experiment-metrics.ts","../../../src/hooks/experiments/use-experiment-trace.ts","../../../src/hooks/experiments/use-experiments-for-dataset-filter.ts","../../../src/hooks/experiments/use-infinite-experiments.ts"],"sourcesContent":["import type { DatasetExperiment } from '@mastra/client-js';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\nexport interface ExperimentMetrics {\n totalTokens: number | null;\n estimatedCost: number | null;\n costUnit: string | null;\n avgAgentDurationMs: number | null;\n agentRuns: number | null;\n}\n\ninterface UseExperimentMetricsArgs {\n experimentId: string | undefined;\n experimentStatus: DatasetExperiment['status'] | undefined;\n /** Whether the observability store can serve metrics; no requests are made when false. */\n supportsMetrics: boolean;\n queryOptions?: MastraQueryOptions<ExperimentMetrics>;\n}\n\n/**\n * Experiment-scoped metrics (tokens, cost, avg agent latency).\n * Filters only by experimentId — no time window, since the experiment already bounds the row set.\n * Polls every 2 seconds while the experiment is running or pending.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useExperimentMetrics = ({\n experimentId,\n experimentStatus,\n supportsMetrics,\n queryOptions,\n}: UseExperimentMetricsArgs) => {\n const client = useMastraClient();\n const isEnabled = Boolean(experimentId) && supportsMetrics;\n const isActive = experimentStatus === 'running' || experimentStatus === 'pending';\n\n const query = useQuery({\n queryKey: ['experiment-metrics', experimentId],\n refetchInterval: isActive ? 2000 : false,\n queryFn: async (): Promise<ExperimentMetrics> => {\n // `enabled` already guards this; the check exists to narrow the type.\n if (!experimentId) throw new Error('experimentId is required');\n const filters = { experimentId };\n\n const [tokens, avgDuration, runs] = await Promise.all([\n client.getMetricAggregate({\n name: ['mastra_model_total_input_tokens', 'mastra_model_total_output_tokens'],\n aggregation: 'sum',\n filters,\n }),\n client.getMetricAggregate({ name: ['mastra_agent_duration_ms'], aggregation: 'avg', filters }),\n client.getMetricAggregate({ name: ['mastra_agent_duration_ms'], aggregation: 'count', filters }),\n ]);\n\n return {\n totalTokens: tokens.value ?? null,\n estimatedCost: tokens.estimatedCost ?? null,\n costUnit: tokens.costUnit ?? null,\n avgAgentDurationMs: avgDuration.value ?? null,\n agentRuns: runs.value ?? null,\n };\n },\n ...queryOptions,\n });\n\n return { data: query.data, isLoading: query.isLoading, isEnabled };\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype TraceLightResponse = Awaited<ReturnType<MastraClient['getTraceLight']>>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useExperimentTrace = <TData = TraceLightResponse>({\n traceId,\n queryOptions,\n}: {\n traceId: string | null | undefined;\n queryOptions?: MastraQueryOptions<TraceLightResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['experiment-trace-light', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n return client.getTraceLight(traceId);\n },\n ...queryOptions,\n });\n};\n","import type { ExperimentTargetType, ListExperimentsParams, MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\n/** Explicit page size: server defaults are 20 (global) / 10 (per dataset), which is too small for the list. */\nexport const EXPERIMENTS_PAGE_SIZE = 100;\n\nexport interface ExperimentTargetFilter {\n targetType?: ExperimentTargetType | '';\n targetId?: string;\n}\n\n/**\n * Experiments for the list page: the global list, or the dataset-scoped list when a dataset filter is active.\n * A dataset's runs may not be in the first page of the global list, so filtering client-side is not enough.\n * The optional target filter is applied server-side for the same reason.\n */\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\n\nexport function useExperimentsForDatasetFilter<TData = ListExperimentsResponse>({\n datasetId,\n target,\n queryOptions,\n}: {\n datasetId: string | undefined;\n target?: ExperimentTargetFilter;\n queryOptions?: MastraQueryOptions<ListExperimentsResponse, TData>;\n}): UseQueryResult<TData, Error> {\n const client = useMastraClient();\n const params: ListExperimentsParams = { perPage: EXPERIMENTS_PAGE_SIZE };\n if (target?.targetType) params.targetType = target.targetType;\n if (target?.targetId) params.targetId = target.targetId;\n\n return useQuery({\n // Prefixes match the keys invalidated by dataset/experiment mutations.\n queryKey: datasetId ? ['dataset-experiments', datasetId, params] : ['experiments', params],\n queryFn: () => (datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params)),\n ...queryOptions,\n });\n}\n","import type { DatasetExperiment, ListExperimentsParams, MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\nimport type { ExperimentTargetFilter } from './use-experiments-for-dataset-filter';\n\nexport const EXPERIMENTS_PER_PAGE = 100;\n\n/**\n * Infinite-scroll experiments for the list page: the global list, or the dataset-scoped list when a\n * dataset filter is active (a dataset's runs may not be in the first pages of the global list). The\n * optional target filter is applied server-side for the same reason.\n */\nexport type ExperimentsOrderBy = NonNullable<ListExperimentsParams['orderBy']>;\n\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\n\nexport function useInfiniteExperiments<TData = DatasetExperiment[]>({\n datasetId,\n target,\n orderBy,\n queryOptions,\n}: {\n datasetId: string | undefined;\n target?: ExperimentTargetFilter;\n orderBy?: ExperimentsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ListExperimentsResponse, TData, QueryKey, number>;\n}): UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n} {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n const targetType = target?.targetType || undefined;\n const targetId = target?.targetId || undefined;\n\n const query = useInfiniteQuery({\n // Prefixes match the keys invalidated by dataset/experiment mutations.\n queryKey: datasetId\n ? ['dataset-experiments', datasetId, 'infinite', { targetType, targetId, orderBy }]\n : ['experiments', 'infinite', { targetType, targetId, orderBy }],\n queryFn: ({ pageParam }) => {\n const params: ListExperimentsParams = { page: pageParam, perPage: EXPERIMENTS_PER_PAGE };\n if (targetType) params.targetType = targetType;\n if (targetId) params.targetId = targetId;\n if (orderBy) params.orderBy = orderBy;\n return datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params);\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.experiments?.length || !lastPage.pagination?.hasMore) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n select: (data: InfiniteData<ListExperimentsResponse, number>) =>\n data.pages.flatMap(page => page?.experiments ?? []) as TData,\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["getOrCreate","useMastraClient","useCombineByIds","useMastraClient","useMastraClient","useMastraClient","useMastraClient","useInView"],"sources":["../../../src/hooks/experiments/use-experiment-item-usage.ts","../../../src/hooks/experiments/use-experiment-metrics.ts","../../../src/hooks/experiments/use-experiment-trace.ts","../../../src/hooks/experiments/use-experiments-for-dataset-filter.ts","../../../src/hooks/experiments/use-infinite-experiments.ts"],"sourcesContent":["import type { GetMetricBreakdownResponse } from '@mastra/core/storage';\nimport { useQueries } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { ExperimentRef } from '../datasets/use-dataset-experiments';\nimport { useCombineByIds } from '../shared/combine-by-ids';\nimport type { ExperimentQueriesResult } from '../shared/combine-by-ids';\nimport { getOrCreate } from '../shared/map';\n\nconst INPUT_TOKEN_METRIC = 'mastra_model_total_input_tokens';\nconst OUTPUT_TOKEN_METRIC = 'mastra_model_total_output_tokens';\nconst POLL_INTERVAL_MS = 2000;\n\nexport interface ExperimentItemUsage {\n inputTokens?: number;\n outputTokens?: number;\n /** Undefined when no group is priced or when groups use different cost units. */\n estimatedCost?: number;\n costUnit?: string;\n}\n\n/** Usage of one experiment: its totals, and each item's usage keyed by the trace id of its run. */\nexport interface ExperimentUsage {\n /** Totals across every item. The cost sums priced groups only. */\n summary: ExperimentItemUsage;\n traces: Record<string, ExperimentItemUsage>;\n}\n\ntype UsageAccumulator = {\n inputTokens?: number;\n outputTokens?: number;\n estimatedCost: number;\n costUnits: Set<string>;\n hasUnknownCostUnit: boolean;\n};\n\nconst createAccumulator = (): UsageAccumulator => ({\n estimatedCost: 0,\n costUnits: new Set(),\n hasUnknownCostUnit: false,\n});\n\ntype BreakdownGroup = GetMetricBreakdownResponse['groups'][number];\n\nfunction accumulate(accumulator: UsageAccumulator, tokenField: 'inputTokens' | 'outputTokens', group: BreakdownGroup) {\n accumulator[tokenField] = (accumulator[tokenField] ?? 0) + group.value;\n\n if (group.estimatedCost == null) return;\n accumulator.estimatedCost += group.estimatedCost;\n if (group.costUnit) {\n accumulator.costUnits.add(group.costUnit.toLowerCase());\n } else {\n accumulator.hasUnknownCostUnit = true;\n }\n}\n\nfunction toUsage(accumulator: UsageAccumulator): ExperimentItemUsage {\n // A single known unit implies at least one priced group.\n const isPriced = !accumulator.hasUnknownCostUnit && accumulator.costUnits.size === 1;\n return {\n inputTokens: accumulator.inputTokens,\n outputTokens: accumulator.outputTokens,\n estimatedCost: isPriced ? accumulator.estimatedCost : undefined,\n costUnit: isPriced ? [...accumulator.costUnits][0] : undefined,\n };\n}\n\n/** Builds the experiment totals and the per-trace usage in a single pass over the groups. */\nfunction toExperimentUsage(response: GetMetricBreakdownResponse): ExperimentUsage {\n const summary = createAccumulator();\n const accumulators = new Map<string, UsageAccumulator>();\n\n for (const group of response.groups) {\n const metricName = group.dimensions.name;\n if (metricName !== INPUT_TOKEN_METRIC && metricName !== OUTPUT_TOKEN_METRIC) continue;\n\n const tokenField = metricName === INPUT_TOKEN_METRIC ? 'inputTokens' : 'outputTokens';\n accumulate(summary, tokenField, group);\n\n const traceId = group.dimensions.traceId;\n if (traceId) accumulate(getOrCreate(accumulators, traceId, createAccumulator), tokenField, group);\n }\n\n const traces: Record<string, ExperimentItemUsage> = {};\n for (const [traceId, accumulator] of accumulators) {\n traces[traceId] = toUsage(accumulator);\n }\n return { summary: toUsage(summary), traces };\n}\n\n/**\n * Token and cost usage of several experiments, keyed by experiment id: each entry holds the\n * experiment totals (`summary`) and every item's usage keyed by trace id (`traces`).\n * Sends one metric breakdown request per experiment, filtered by its id rather than by trace ids,\n * so it does not wait for the experiment results. Polls every 2 seconds while an experiment is\n * running or pending. No request is made when the observability store cannot serve metrics.\n */\nexport const useExperimentsItemUsage = ({\n experiments,\n supportsMetrics,\n}: {\n experiments: ExperimentRef[];\n supportsMetrics: boolean;\n}): ExperimentQueriesResult<ExperimentUsage> => {\n const client = useMastraClient();\n const combine = useCombineByIds<ExperimentUsage>(experiments.map(experiment => experiment.id));\n\n return useQueries({\n queries: experiments.map(({ id, status }) => ({\n queryKey: ['experiment-item-usage', id],\n queryFn: async () =>\n toExperimentUsage(\n await client.getMetricBreakdown({\n name: [INPUT_TOKEN_METRIC, OUTPUT_TOKEN_METRIC],\n aggregation: 'sum',\n groupBy: ['traceId', 'name'],\n filters: { experimentId: id },\n }),\n ),\n enabled: supportsMetrics,\n refetchInterval: status === 'running' || status === 'pending' ? POLL_INTERVAL_MS : false,\n })),\n combine,\n });\n};\n","import type { DatasetExperiment } from '@mastra/client-js';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\nexport interface ExperimentMetrics {\n totalTokens: number | null;\n estimatedCost: number | null;\n costUnit: string | null;\n avgAgentDurationMs: number | null;\n agentRuns: number | null;\n}\n\ninterface UseExperimentMetricsArgs {\n experimentId: string | undefined;\n experimentStatus: DatasetExperiment['status'] | undefined;\n /** Whether the observability store can serve metrics; no requests are made when false. */\n supportsMetrics: boolean;\n queryOptions?: MastraQueryOptions<ExperimentMetrics>;\n}\n\n/**\n * Experiment-scoped metrics (tokens, cost, avg agent latency).\n * Filters only by experimentId — no time window, since the experiment already bounds the row set.\n * Polls every 2 seconds while the experiment is running or pending.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useExperimentMetrics = ({\n experimentId,\n experimentStatus,\n supportsMetrics,\n queryOptions,\n}: UseExperimentMetricsArgs) => {\n const client = useMastraClient();\n const isEnabled = Boolean(experimentId) && supportsMetrics;\n const isActive = experimentStatus === 'running' || experimentStatus === 'pending';\n\n const query = useQuery({\n queryKey: ['experiment-metrics', experimentId],\n refetchInterval: isActive ? 2000 : false,\n queryFn: async (): Promise<ExperimentMetrics> => {\n // `enabled` already guards this; the check exists to narrow the type.\n if (!experimentId) throw new Error('experimentId is required');\n const filters = { experimentId };\n\n const [tokens, avgDuration, runs] = await Promise.all([\n client.getMetricAggregate({\n name: ['mastra_model_total_input_tokens', 'mastra_model_total_output_tokens'],\n aggregation: 'sum',\n filters,\n }),\n client.getMetricAggregate({ name: ['mastra_agent_duration_ms'], aggregation: 'avg', filters }),\n client.getMetricAggregate({ name: ['mastra_agent_duration_ms'], aggregation: 'count', filters }),\n ]);\n\n return {\n totalTokens: tokens.value ?? null,\n estimatedCost: tokens.estimatedCost ?? null,\n costUnit: tokens.costUnit ?? null,\n avgAgentDurationMs: avgDuration.value ?? null,\n agentRuns: runs.value ?? null,\n };\n },\n ...queryOptions,\n });\n\n return { data: query.data, isLoading: query.isLoading, isEnabled };\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype TraceLightResponse = Awaited<ReturnType<MastraClient['getTraceLight']>>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useExperimentTrace = <TData = TraceLightResponse>({\n traceId,\n queryOptions,\n}: {\n traceId: string | null | undefined;\n queryOptions?: MastraQueryOptions<TraceLightResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['experiment-trace-light', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n return client.getTraceLight(traceId);\n },\n ...queryOptions,\n });\n};\n","import type { ExperimentTargetType, ListExperimentsParams, MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\n/** Explicit page size: server defaults are 20 (global) / 10 (per dataset), which is too small for the list. */\nexport const EXPERIMENTS_PAGE_SIZE = 100;\n\nexport interface ExperimentTargetFilter {\n targetType?: ExperimentTargetType | '';\n targetId?: string;\n}\n\n/**\n * Experiments for the list page: the global list, or the dataset-scoped list when a dataset filter is active.\n * A dataset's runs may not be in the first page of the global list, so filtering client-side is not enough.\n * The optional target filter is applied server-side for the same reason.\n */\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\n\nexport function useExperimentsForDatasetFilter<TData = ListExperimentsResponse>({\n datasetId,\n target,\n queryOptions,\n}: {\n datasetId: string | undefined;\n target?: ExperimentTargetFilter;\n queryOptions?: MastraQueryOptions<ListExperimentsResponse, TData>;\n}): UseQueryResult<TData, Error> {\n const client = useMastraClient();\n const params: ListExperimentsParams = { perPage: EXPERIMENTS_PAGE_SIZE };\n if (target?.targetType) params.targetType = target.targetType;\n if (target?.targetId) params.targetId = target.targetId;\n\n return useQuery({\n // Prefixes match the keys invalidated by dataset/experiment mutations.\n queryKey: datasetId ? ['dataset-experiments', datasetId, params] : ['experiments', params],\n queryFn: () => (datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params)),\n ...queryOptions,\n });\n}\n","import type { DatasetExperiment, ListExperimentsParams, MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\nimport type { ExperimentTargetFilter } from './use-experiments-for-dataset-filter';\n\nexport const EXPERIMENTS_PER_PAGE = 100;\n\n/**\n * Infinite-scroll experiments for the list page: the global list, or the dataset-scoped list when a\n * dataset filter is active (a dataset's runs may not be in the first pages of the global list). The\n * optional target filter is applied server-side for the same reason.\n */\nexport type ExperimentsOrderBy = NonNullable<ListExperimentsParams['orderBy']>;\n\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\n\nexport function useInfiniteExperiments<TData = DatasetExperiment[]>({\n datasetId,\n target,\n orderBy,\n queryOptions,\n}: {\n datasetId: string | undefined;\n target?: ExperimentTargetFilter;\n orderBy?: ExperimentsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ListExperimentsResponse, TData, QueryKey, number>;\n}): UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n} {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n const targetType = target?.targetType || undefined;\n const targetId = target?.targetId || undefined;\n\n const query = useInfiniteQuery({\n // Prefixes match the keys invalidated by dataset/experiment mutations.\n queryKey: datasetId\n ? ['dataset-experiments', datasetId, 'infinite', { targetType, targetId, orderBy }]\n : ['experiments', 'infinite', { targetType, targetId, orderBy }],\n queryFn: ({ pageParam }) => {\n const params: ListExperimentsParams = { page: pageParam, perPage: EXPERIMENTS_PER_PAGE };\n if (targetType) params.targetType = targetType;\n if (targetId) params.targetId = targetId;\n if (orderBy) params.orderBy = orderBy;\n return datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params);\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.experiments?.length || !lastPage.pagination?.hasMore) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n select: (data: InfiniteData<ListExperimentsResponse, number>) =>\n data.pages.flatMap(page => page?.experiments ?? []) as TData,\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/experiments/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sCAAsC,CAAC;AACrD,cAAc,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/experiments/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sCAAsC,CAAC;AACrD,cAAc,4BAA4B,CAAC"}
|
|
@@ -1,7 +1,79 @@
|
|
|
1
1
|
import { n as useMastraClient } from "../../mastra-client-context-Bx_g84YB.js";
|
|
2
2
|
import { t as useInView } from "../../use-in-view-C9sYPGRm.js";
|
|
3
|
+
import { t as useCombineByIds } from "../../combine-by-ids-CcaZKGT9.js";
|
|
4
|
+
import { t as getOrCreate } from "../../map-CDv4fbu4.js";
|
|
3
5
|
import { useEffect } from "react";
|
|
4
|
-
import { useInfiniteQuery, useQuery } from "@tanstack/react-query";
|
|
6
|
+
import { useInfiniteQuery, useQueries, useQuery } from "@tanstack/react-query";
|
|
7
|
+
//#region src/hooks/experiments/use-experiment-item-usage.ts
|
|
8
|
+
const INPUT_TOKEN_METRIC = "mastra_model_total_input_tokens";
|
|
9
|
+
const OUTPUT_TOKEN_METRIC = "mastra_model_total_output_tokens";
|
|
10
|
+
const POLL_INTERVAL_MS = 2e3;
|
|
11
|
+
const createAccumulator = () => ({
|
|
12
|
+
estimatedCost: 0,
|
|
13
|
+
costUnits: /* @__PURE__ */ new Set(),
|
|
14
|
+
hasUnknownCostUnit: false
|
|
15
|
+
});
|
|
16
|
+
function accumulate(accumulator, tokenField, group) {
|
|
17
|
+
accumulator[tokenField] = (accumulator[tokenField] ?? 0) + group.value;
|
|
18
|
+
if (group.estimatedCost == null) return;
|
|
19
|
+
accumulator.estimatedCost += group.estimatedCost;
|
|
20
|
+
if (group.costUnit) accumulator.costUnits.add(group.costUnit.toLowerCase());
|
|
21
|
+
else accumulator.hasUnknownCostUnit = true;
|
|
22
|
+
}
|
|
23
|
+
function toUsage(accumulator) {
|
|
24
|
+
const isPriced = !accumulator.hasUnknownCostUnit && accumulator.costUnits.size === 1;
|
|
25
|
+
return {
|
|
26
|
+
inputTokens: accumulator.inputTokens,
|
|
27
|
+
outputTokens: accumulator.outputTokens,
|
|
28
|
+
estimatedCost: isPriced ? accumulator.estimatedCost : void 0,
|
|
29
|
+
costUnit: isPriced ? [...accumulator.costUnits][0] : void 0
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** Builds the experiment totals and the per-trace usage in a single pass over the groups. */
|
|
33
|
+
function toExperimentUsage(response) {
|
|
34
|
+
const summary = createAccumulator();
|
|
35
|
+
const accumulators = /* @__PURE__ */ new Map();
|
|
36
|
+
for (const group of response.groups) {
|
|
37
|
+
const metricName = group.dimensions.name;
|
|
38
|
+
if (metricName !== INPUT_TOKEN_METRIC && metricName !== OUTPUT_TOKEN_METRIC) continue;
|
|
39
|
+
const tokenField = metricName === INPUT_TOKEN_METRIC ? "inputTokens" : "outputTokens";
|
|
40
|
+
accumulate(summary, tokenField, group);
|
|
41
|
+
const traceId = group.dimensions.traceId;
|
|
42
|
+
if (traceId) accumulate(getOrCreate(accumulators, traceId, createAccumulator), tokenField, group);
|
|
43
|
+
}
|
|
44
|
+
const traces = {};
|
|
45
|
+
for (const [traceId, accumulator] of accumulators) traces[traceId] = toUsage(accumulator);
|
|
46
|
+
return {
|
|
47
|
+
summary: toUsage(summary),
|
|
48
|
+
traces
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Token and cost usage of several experiments, keyed by experiment id: each entry holds the
|
|
53
|
+
* experiment totals (`summary`) and every item's usage keyed by trace id (`traces`).
|
|
54
|
+
* Sends one metric breakdown request per experiment, filtered by its id rather than by trace ids,
|
|
55
|
+
* so it does not wait for the experiment results. Polls every 2 seconds while an experiment is
|
|
56
|
+
* running or pending. No request is made when the observability store cannot serve metrics.
|
|
57
|
+
*/
|
|
58
|
+
const useExperimentsItemUsage = ({ experiments, supportsMetrics }) => {
|
|
59
|
+
const client = useMastraClient();
|
|
60
|
+
const combine = useCombineByIds(experiments.map((experiment) => experiment.id));
|
|
61
|
+
return useQueries({
|
|
62
|
+
queries: experiments.map(({ id, status }) => ({
|
|
63
|
+
queryKey: ["experiment-item-usage", id],
|
|
64
|
+
queryFn: async () => toExperimentUsage(await client.getMetricBreakdown({
|
|
65
|
+
name: [INPUT_TOKEN_METRIC, OUTPUT_TOKEN_METRIC],
|
|
66
|
+
aggregation: "sum",
|
|
67
|
+
groupBy: ["traceId", "name"],
|
|
68
|
+
filters: { experimentId: id }
|
|
69
|
+
})),
|
|
70
|
+
enabled: supportsMetrics,
|
|
71
|
+
refetchInterval: status === "running" || status === "pending" ? POLL_INTERVAL_MS : false
|
|
72
|
+
})),
|
|
73
|
+
combine
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
//#endregion
|
|
5
77
|
//#region src/hooks/experiments/use-experiment-metrics.ts
|
|
6
78
|
/**
|
|
7
79
|
* Experiment-scoped metrics (tokens, cost, avg agent latency).
|
|
@@ -141,6 +213,6 @@ function useInfiniteExperiments({ datasetId, target, orderBy, queryOptions }) {
|
|
|
141
213
|
};
|
|
142
214
|
}
|
|
143
215
|
//#endregion
|
|
144
|
-
export { EXPERIMENTS_PAGE_SIZE, EXPERIMENTS_PER_PAGE, useExperimentMetrics, useExperimentTrace, useExperimentsForDatasetFilter, useInfiniteExperiments };
|
|
216
|
+
export { EXPERIMENTS_PAGE_SIZE, EXPERIMENTS_PER_PAGE, useExperimentMetrics, useExperimentTrace, useExperimentsForDatasetFilter, useExperimentsItemUsage, useInfiniteExperiments };
|
|
145
217
|
|
|
146
218
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/hooks/experiments/use-experiment-metrics.ts","../../../src/hooks/experiments/use-experiment-trace.ts","../../../src/hooks/experiments/use-experiments-for-dataset-filter.ts","../../../src/hooks/experiments/use-infinite-experiments.ts"],"sourcesContent":["import type { DatasetExperiment } from '@mastra/client-js';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\nexport interface ExperimentMetrics {\n totalTokens: number | null;\n estimatedCost: number | null;\n costUnit: string | null;\n avgAgentDurationMs: number | null;\n agentRuns: number | null;\n}\n\ninterface UseExperimentMetricsArgs {\n experimentId: string | undefined;\n experimentStatus: DatasetExperiment['status'] | undefined;\n /** Whether the observability store can serve metrics; no requests are made when false. */\n supportsMetrics: boolean;\n queryOptions?: MastraQueryOptions<ExperimentMetrics>;\n}\n\n/**\n * Experiment-scoped metrics (tokens, cost, avg agent latency).\n * Filters only by experimentId — no time window, since the experiment already bounds the row set.\n * Polls every 2 seconds while the experiment is running or pending.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useExperimentMetrics = ({\n experimentId,\n experimentStatus,\n supportsMetrics,\n queryOptions,\n}: UseExperimentMetricsArgs) => {\n const client = useMastraClient();\n const isEnabled = Boolean(experimentId) && supportsMetrics;\n const isActive = experimentStatus === 'running' || experimentStatus === 'pending';\n\n const query = useQuery({\n queryKey: ['experiment-metrics', experimentId],\n refetchInterval: isActive ? 2000 : false,\n queryFn: async (): Promise<ExperimentMetrics> => {\n // `enabled` already guards this; the check exists to narrow the type.\n if (!experimentId) throw new Error('experimentId is required');\n const filters = { experimentId };\n\n const [tokens, avgDuration, runs] = await Promise.all([\n client.getMetricAggregate({\n name: ['mastra_model_total_input_tokens', 'mastra_model_total_output_tokens'],\n aggregation: 'sum',\n filters,\n }),\n client.getMetricAggregate({ name: ['mastra_agent_duration_ms'], aggregation: 'avg', filters }),\n client.getMetricAggregate({ name: ['mastra_agent_duration_ms'], aggregation: 'count', filters }),\n ]);\n\n return {\n totalTokens: tokens.value ?? null,\n estimatedCost: tokens.estimatedCost ?? null,\n costUnit: tokens.costUnit ?? null,\n avgAgentDurationMs: avgDuration.value ?? null,\n agentRuns: runs.value ?? null,\n };\n },\n ...queryOptions,\n });\n\n return { data: query.data, isLoading: query.isLoading, isEnabled };\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype TraceLightResponse = Awaited<ReturnType<MastraClient['getTraceLight']>>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useExperimentTrace = <TData = TraceLightResponse>({\n traceId,\n queryOptions,\n}: {\n traceId: string | null | undefined;\n queryOptions?: MastraQueryOptions<TraceLightResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['experiment-trace-light', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n return client.getTraceLight(traceId);\n },\n ...queryOptions,\n });\n};\n","import type { ExperimentTargetType, ListExperimentsParams, MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\n/** Explicit page size: server defaults are 20 (global) / 10 (per dataset), which is too small for the list. */\nexport const EXPERIMENTS_PAGE_SIZE = 100;\n\nexport interface ExperimentTargetFilter {\n targetType?: ExperimentTargetType | '';\n targetId?: string;\n}\n\n/**\n * Experiments for the list page: the global list, or the dataset-scoped list when a dataset filter is active.\n * A dataset's runs may not be in the first page of the global list, so filtering client-side is not enough.\n * The optional target filter is applied server-side for the same reason.\n */\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\n\nexport function useExperimentsForDatasetFilter<TData = ListExperimentsResponse>({\n datasetId,\n target,\n queryOptions,\n}: {\n datasetId: string | undefined;\n target?: ExperimentTargetFilter;\n queryOptions?: MastraQueryOptions<ListExperimentsResponse, TData>;\n}): UseQueryResult<TData, Error> {\n const client = useMastraClient();\n const params: ListExperimentsParams = { perPage: EXPERIMENTS_PAGE_SIZE };\n if (target?.targetType) params.targetType = target.targetType;\n if (target?.targetId) params.targetId = target.targetId;\n\n return useQuery({\n // Prefixes match the keys invalidated by dataset/experiment mutations.\n queryKey: datasetId ? ['dataset-experiments', datasetId, params] : ['experiments', params],\n queryFn: () => (datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params)),\n ...queryOptions,\n });\n}\n","import type { DatasetExperiment, ListExperimentsParams, MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\nimport type { ExperimentTargetFilter } from './use-experiments-for-dataset-filter';\n\nexport const EXPERIMENTS_PER_PAGE = 100;\n\n/**\n * Infinite-scroll experiments for the list page: the global list, or the dataset-scoped list when a\n * dataset filter is active (a dataset's runs may not be in the first pages of the global list). The\n * optional target filter is applied server-side for the same reason.\n */\nexport type ExperimentsOrderBy = NonNullable<ListExperimentsParams['orderBy']>;\n\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\n\nexport function useInfiniteExperiments<TData = DatasetExperiment[]>({\n datasetId,\n target,\n orderBy,\n queryOptions,\n}: {\n datasetId: string | undefined;\n target?: ExperimentTargetFilter;\n orderBy?: ExperimentsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ListExperimentsResponse, TData, QueryKey, number>;\n}): UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n} {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n const targetType = target?.targetType || undefined;\n const targetId = target?.targetId || undefined;\n\n const query = useInfiniteQuery({\n // Prefixes match the keys invalidated by dataset/experiment mutations.\n queryKey: datasetId\n ? ['dataset-experiments', datasetId, 'infinite', { targetType, targetId, orderBy }]\n : ['experiments', 'infinite', { targetType, targetId, orderBy }],\n queryFn: ({ pageParam }) => {\n const params: ListExperimentsParams = { page: pageParam, perPage: EXPERIMENTS_PER_PAGE };\n if (targetType) params.targetType = targetType;\n if (targetId) params.targetId = targetId;\n if (orderBy) params.orderBy = orderBy;\n return datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params);\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.experiments?.length || !lastPage.pagination?.hasMore) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n select: (data: InfiniteData<ListExperimentsResponse, number>) =>\n data.pages.flatMap(page => page?.experiments ?? []) as TData,\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/hooks/experiments/use-experiment-item-usage.ts","../../../src/hooks/experiments/use-experiment-metrics.ts","../../../src/hooks/experiments/use-experiment-trace.ts","../../../src/hooks/experiments/use-experiments-for-dataset-filter.ts","../../../src/hooks/experiments/use-infinite-experiments.ts"],"sourcesContent":["import type { GetMetricBreakdownResponse } from '@mastra/core/storage';\nimport { useQueries } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { ExperimentRef } from '../datasets/use-dataset-experiments';\nimport { useCombineByIds } from '../shared/combine-by-ids';\nimport type { ExperimentQueriesResult } from '../shared/combine-by-ids';\nimport { getOrCreate } from '../shared/map';\n\nconst INPUT_TOKEN_METRIC = 'mastra_model_total_input_tokens';\nconst OUTPUT_TOKEN_METRIC = 'mastra_model_total_output_tokens';\nconst POLL_INTERVAL_MS = 2000;\n\nexport interface ExperimentItemUsage {\n inputTokens?: number;\n outputTokens?: number;\n /** Undefined when no group is priced or when groups use different cost units. */\n estimatedCost?: number;\n costUnit?: string;\n}\n\n/** Usage of one experiment: its totals, and each item's usage keyed by the trace id of its run. */\nexport interface ExperimentUsage {\n /** Totals across every item. The cost sums priced groups only. */\n summary: ExperimentItemUsage;\n traces: Record<string, ExperimentItemUsage>;\n}\n\ntype UsageAccumulator = {\n inputTokens?: number;\n outputTokens?: number;\n estimatedCost: number;\n costUnits: Set<string>;\n hasUnknownCostUnit: boolean;\n};\n\nconst createAccumulator = (): UsageAccumulator => ({\n estimatedCost: 0,\n costUnits: new Set(),\n hasUnknownCostUnit: false,\n});\n\ntype BreakdownGroup = GetMetricBreakdownResponse['groups'][number];\n\nfunction accumulate(accumulator: UsageAccumulator, tokenField: 'inputTokens' | 'outputTokens', group: BreakdownGroup) {\n accumulator[tokenField] = (accumulator[tokenField] ?? 0) + group.value;\n\n if (group.estimatedCost == null) return;\n accumulator.estimatedCost += group.estimatedCost;\n if (group.costUnit) {\n accumulator.costUnits.add(group.costUnit.toLowerCase());\n } else {\n accumulator.hasUnknownCostUnit = true;\n }\n}\n\nfunction toUsage(accumulator: UsageAccumulator): ExperimentItemUsage {\n // A single known unit implies at least one priced group.\n const isPriced = !accumulator.hasUnknownCostUnit && accumulator.costUnits.size === 1;\n return {\n inputTokens: accumulator.inputTokens,\n outputTokens: accumulator.outputTokens,\n estimatedCost: isPriced ? accumulator.estimatedCost : undefined,\n costUnit: isPriced ? [...accumulator.costUnits][0] : undefined,\n };\n}\n\n/** Builds the experiment totals and the per-trace usage in a single pass over the groups. */\nfunction toExperimentUsage(response: GetMetricBreakdownResponse): ExperimentUsage {\n const summary = createAccumulator();\n const accumulators = new Map<string, UsageAccumulator>();\n\n for (const group of response.groups) {\n const metricName = group.dimensions.name;\n if (metricName !== INPUT_TOKEN_METRIC && metricName !== OUTPUT_TOKEN_METRIC) continue;\n\n const tokenField = metricName === INPUT_TOKEN_METRIC ? 'inputTokens' : 'outputTokens';\n accumulate(summary, tokenField, group);\n\n const traceId = group.dimensions.traceId;\n if (traceId) accumulate(getOrCreate(accumulators, traceId, createAccumulator), tokenField, group);\n }\n\n const traces: Record<string, ExperimentItemUsage> = {};\n for (const [traceId, accumulator] of accumulators) {\n traces[traceId] = toUsage(accumulator);\n }\n return { summary: toUsage(summary), traces };\n}\n\n/**\n * Token and cost usage of several experiments, keyed by experiment id: each entry holds the\n * experiment totals (`summary`) and every item's usage keyed by trace id (`traces`).\n * Sends one metric breakdown request per experiment, filtered by its id rather than by trace ids,\n * so it does not wait for the experiment results. Polls every 2 seconds while an experiment is\n * running or pending. No request is made when the observability store cannot serve metrics.\n */\nexport const useExperimentsItemUsage = ({\n experiments,\n supportsMetrics,\n}: {\n experiments: ExperimentRef[];\n supportsMetrics: boolean;\n}): ExperimentQueriesResult<ExperimentUsage> => {\n const client = useMastraClient();\n const combine = useCombineByIds<ExperimentUsage>(experiments.map(experiment => experiment.id));\n\n return useQueries({\n queries: experiments.map(({ id, status }) => ({\n queryKey: ['experiment-item-usage', id],\n queryFn: async () =>\n toExperimentUsage(\n await client.getMetricBreakdown({\n name: [INPUT_TOKEN_METRIC, OUTPUT_TOKEN_METRIC],\n aggregation: 'sum',\n groupBy: ['traceId', 'name'],\n filters: { experimentId: id },\n }),\n ),\n enabled: supportsMetrics,\n refetchInterval: status === 'running' || status === 'pending' ? POLL_INTERVAL_MS : false,\n })),\n combine,\n });\n};\n","import type { DatasetExperiment } from '@mastra/client-js';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\nexport interface ExperimentMetrics {\n totalTokens: number | null;\n estimatedCost: number | null;\n costUnit: string | null;\n avgAgentDurationMs: number | null;\n agentRuns: number | null;\n}\n\ninterface UseExperimentMetricsArgs {\n experimentId: string | undefined;\n experimentStatus: DatasetExperiment['status'] | undefined;\n /** Whether the observability store can serve metrics; no requests are made when false. */\n supportsMetrics: boolean;\n queryOptions?: MastraQueryOptions<ExperimentMetrics>;\n}\n\n/**\n * Experiment-scoped metrics (tokens, cost, avg agent latency).\n * Filters only by experimentId — no time window, since the experiment already bounds the row set.\n * Polls every 2 seconds while the experiment is running or pending.\n *\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useExperimentMetrics = ({\n experimentId,\n experimentStatus,\n supportsMetrics,\n queryOptions,\n}: UseExperimentMetricsArgs) => {\n const client = useMastraClient();\n const isEnabled = Boolean(experimentId) && supportsMetrics;\n const isActive = experimentStatus === 'running' || experimentStatus === 'pending';\n\n const query = useQuery({\n queryKey: ['experiment-metrics', experimentId],\n refetchInterval: isActive ? 2000 : false,\n queryFn: async (): Promise<ExperimentMetrics> => {\n // `enabled` already guards this; the check exists to narrow the type.\n if (!experimentId) throw new Error('experimentId is required');\n const filters = { experimentId };\n\n const [tokens, avgDuration, runs] = await Promise.all([\n client.getMetricAggregate({\n name: ['mastra_model_total_input_tokens', 'mastra_model_total_output_tokens'],\n aggregation: 'sum',\n filters,\n }),\n client.getMetricAggregate({ name: ['mastra_agent_duration_ms'], aggregation: 'avg', filters }),\n client.getMetricAggregate({ name: ['mastra_agent_duration_ms'], aggregation: 'count', filters }),\n ]);\n\n return {\n totalTokens: tokens.value ?? null,\n estimatedCost: tokens.estimatedCost ?? null,\n costUnit: tokens.costUnit ?? null,\n avgAgentDurationMs: avgDuration.value ?? null,\n agentRuns: runs.value ?? null,\n };\n },\n ...queryOptions,\n });\n\n return { data: query.data, isLoading: query.isLoading, isEnabled };\n};\n","import type { MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\ntype TraceLightResponse = Awaited<ReturnType<MastraClient['getTraceLight']>>;\n\n/**\n * Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.\n */\nexport const useExperimentTrace = <TData = TraceLightResponse>({\n traceId,\n queryOptions,\n}: {\n traceId: string | null | undefined;\n queryOptions?: MastraQueryOptions<TraceLightResponse, TData>;\n}): UseQueryResult<TData, Error> => {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['experiment-trace-light', traceId],\n queryFn: async () => {\n if (!traceId) {\n throw new Error('Trace ID is required');\n }\n return client.getTraceLight(traceId);\n },\n ...queryOptions,\n });\n};\n","import type { ExperimentTargetType, ListExperimentsParams, MastraClient } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useQuery } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraQueryOptions } from '../shared/query-options';\n\n/** Explicit page size: server defaults are 20 (global) / 10 (per dataset), which is too small for the list. */\nexport const EXPERIMENTS_PAGE_SIZE = 100;\n\nexport interface ExperimentTargetFilter {\n targetType?: ExperimentTargetType | '';\n targetId?: string;\n}\n\n/**\n * Experiments for the list page: the global list, or the dataset-scoped list when a dataset filter is active.\n * A dataset's runs may not be in the first page of the global list, so filtering client-side is not enough.\n * The optional target filter is applied server-side for the same reason.\n */\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\n\nexport function useExperimentsForDatasetFilter<TData = ListExperimentsResponse>({\n datasetId,\n target,\n queryOptions,\n}: {\n datasetId: string | undefined;\n target?: ExperimentTargetFilter;\n queryOptions?: MastraQueryOptions<ListExperimentsResponse, TData>;\n}): UseQueryResult<TData, Error> {\n const client = useMastraClient();\n const params: ListExperimentsParams = { perPage: EXPERIMENTS_PAGE_SIZE };\n if (target?.targetType) params.targetType = target.targetType;\n if (target?.targetId) params.targetId = target.targetId;\n\n return useQuery({\n // Prefixes match the keys invalidated by dataset/experiment mutations.\n queryKey: datasetId ? ['dataset-experiments', datasetId, params] : ['experiments', params],\n queryFn: () => (datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params)),\n ...queryOptions,\n });\n}\n","import type { DatasetExperiment, ListExperimentsParams, MastraClient } from '@mastra/client-js';\nimport { useInfiniteQuery } from '@tanstack/react-query';\nimport type { InfiniteData, QueryKey, UseInfiniteQueryResult } from '@tanstack/react-query';\nimport { useEffect } from 'react';\nimport { useMastraClient } from '../../mastra-client-context';\nimport type { MastraInfiniteQueryOptions } from '../shared/query-options';\nimport { useInView } from '../shared/use-in-view';\nimport type { ExperimentTargetFilter } from './use-experiments-for-dataset-filter';\n\nexport const EXPERIMENTS_PER_PAGE = 100;\n\n/**\n * Infinite-scroll experiments for the list page: the global list, or the dataset-scoped list when a\n * dataset filter is active (a dataset's runs may not be in the first pages of the global list). The\n * optional target filter is applied server-side for the same reason.\n */\nexport type ExperimentsOrderBy = NonNullable<ListExperimentsParams['orderBy']>;\n\ntype ListExperimentsResponse = Awaited<ReturnType<MastraClient['listExperiments']>>;\n\nexport function useInfiniteExperiments<TData = DatasetExperiment[]>({\n datasetId,\n target,\n orderBy,\n queryOptions,\n}: {\n datasetId: string | undefined;\n target?: ExperimentTargetFilter;\n orderBy?: ExperimentsOrderBy;\n queryOptions?: MastraInfiniteQueryOptions<ListExperimentsResponse, TData, QueryKey, number>;\n}): UseInfiniteQueryResult<TData, Error> & {\n setEndOfListElement: (element: HTMLDivElement | null) => void;\n} {\n const client = useMastraClient();\n const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();\n const targetType = target?.targetType || undefined;\n const targetId = target?.targetId || undefined;\n\n const query = useInfiniteQuery({\n // Prefixes match the keys invalidated by dataset/experiment mutations.\n queryKey: datasetId\n ? ['dataset-experiments', datasetId, 'infinite', { targetType, targetId, orderBy }]\n : ['experiments', 'infinite', { targetType, targetId, orderBy }],\n queryFn: ({ pageParam }) => {\n const params: ListExperimentsParams = { page: pageParam, perPage: EXPERIMENTS_PER_PAGE };\n if (targetType) params.targetType = targetType;\n if (targetId) params.targetId = targetId;\n if (orderBy) params.orderBy = orderBy;\n return datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params);\n },\n initialPageParam: 0,\n getNextPageParam: (lastPage, _, lastPageParam) => {\n if (!lastPage?.experiments?.length || !lastPage.pagination?.hasMore) {\n return undefined;\n }\n return lastPageParam + 1;\n },\n select: (data: InfiniteData<ListExperimentsResponse, number>) =>\n data.pages.flatMap(page => page?.experiments ?? []) as TData,\n ...queryOptions,\n });\n\n useEffect(() => {\n if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {\n void query.fetchNextPage();\n }\n }, [isEndOfListInView, query]);\n\n return { ...query, setEndOfListElement };\n}\n"],"mappings":";;;;;;;AAQA,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAC5B,MAAM,mBAAmB;AAyBzB,MAAM,2BAA6C;CACjD,eAAe;CACf,2BAAW,IAAI,IAAI;CACnB,oBAAoB;AACtB;AAIA,SAAS,WAAW,aAA+B,YAA4C,OAAuB;CACpH,YAAY,eAAe,YAAY,eAAe,KAAK,MAAM;CAEjE,IAAI,MAAM,iBAAiB,MAAM;CACjC,YAAY,iBAAiB,MAAM;CACnC,IAAI,MAAM,UACR,YAAY,UAAU,IAAI,MAAM,SAAS,YAAY,CAAC;MAEtD,YAAY,qBAAqB;AAErC;AAEA,SAAS,QAAQ,aAAoD;CAEnE,MAAM,WAAW,CAAC,YAAY,sBAAsB,YAAY,UAAU,SAAS;CACnF,OAAO;EACL,aAAa,YAAY;EACzB,cAAc,YAAY;EAC1B,eAAe,WAAW,YAAY,gBAAgB,KAAA;EACtD,UAAU,WAAW,CAAC,GAAG,YAAY,SAAS,CAAC,CAAC,KAAK,KAAA;CACvD;AACF;;AAGA,SAAS,kBAAkB,UAAuD;CAChF,MAAM,UAAU,kBAAkB;CAClC,MAAM,+BAAe,IAAI,IAA8B;CAEvD,KAAK,MAAM,SAAS,SAAS,QAAQ;EACnC,MAAM,aAAa,MAAM,WAAW;EACpC,IAAI,eAAe,sBAAsB,eAAe,qBAAqB;EAE7E,MAAM,aAAa,eAAe,qBAAqB,gBAAgB;EACvE,WAAW,SAAS,YAAY,KAAK;EAErC,MAAM,UAAU,MAAM,WAAW;EACjC,IAAI,SAAS,WAAW,YAAY,cAAc,SAAS,iBAAiB,GAAG,YAAY,KAAK;CAClG;CAEA,MAAM,SAA8C,CAAC;CACrD,KAAK,MAAM,CAAC,SAAS,gBAAgB,cACnC,OAAO,WAAW,QAAQ,WAAW;CAEvC,OAAO;EAAE,SAAS,QAAQ,OAAO;EAAG;CAAO;AAC7C;;;;;;;;AASA,MAAa,2BAA2B,EACtC,aACA,sBAI8C;CAC9C,MAAM,SAAS,gBAAgB;CAC/B,MAAM,UAAU,gBAAiC,YAAY,KAAI,eAAc,WAAW,EAAE,CAAC;CAE7F,OAAO,WAAW;EAChB,SAAS,YAAY,KAAK,EAAE,IAAI,cAAc;GAC5C,UAAU,CAAC,yBAAyB,EAAE;GACtC,SAAS,YACP,kBACE,MAAM,OAAO,mBAAmB;IAC9B,MAAM,CAAC,oBAAoB,mBAAmB;IAC9C,aAAa;IACb,SAAS,CAAC,WAAW,MAAM;IAC3B,SAAS,EAAE,cAAc,GAAG;GAC9B,CAAC,CACH;GACF,SAAS;GACT,iBAAiB,WAAW,aAAa,WAAW,YAAY,mBAAmB;EACrF,EAAE;EACF;CACF,CAAC;AACH;;;;;;;;;;AC/FA,MAAa,wBAAwB,EACnC,cACA,kBACA,iBACA,mBAC8B;CAC9B,MAAM,SAAS,gBAAgB;CAC/B,MAAM,YAAY,QAAQ,YAAY,KAAK;CAG3C,MAAM,QAAQ,SAAS;EACrB,UAAU,CAAC,sBAAsB,YAAY;EAC7C,iBAJe,qBAAqB,aAAa,qBAAqB,YAI1C,MAAO;EACnC,SAAS,YAAwC;GAE/C,IAAI,CAAC,cAAc,MAAM,IAAI,MAAM,0BAA0B;GAC7D,MAAM,UAAU,EAAE,aAAa;GAE/B,MAAM,CAAC,QAAQ,aAAa,QAAQ,MAAM,QAAQ,IAAI;IACpD,OAAO,mBAAmB;KACxB,MAAM,CAAC,mCAAmC,kCAAkC;KAC5E,aAAa;KACb;IACF,CAAC;IACD,OAAO,mBAAmB;KAAE,MAAM,CAAC,0BAA0B;KAAG,aAAa;KAAO;IAAQ,CAAC;IAC7F,OAAO,mBAAmB;KAAE,MAAM,CAAC,0BAA0B;KAAG,aAAa;KAAS;IAAQ,CAAC;GACjG,CAAC;GAED,OAAO;IACL,aAAa,OAAO,SAAS;IAC7B,eAAe,OAAO,iBAAiB;IACvC,UAAU,OAAO,YAAY;IAC7B,oBAAoB,YAAY,SAAS;IACzC,WAAW,KAAK,SAAS;GAC3B;EACF;EACA,GAAG;CACL,CAAC;CAED,OAAO;EAAE,MAAM,MAAM;EAAM,WAAW,MAAM;EAAW;CAAU;AACnE;;;;;;ACzDA,MAAa,sBAAkD,EAC7D,SACA,mBAIkC;CAClC,MAAM,SAAS,gBAAgB;CAE/B,OAAO,SAAS;EACd,UAAU,CAAC,0BAA0B,OAAO;EAC5C,SAAS,YAAY;GACnB,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,sBAAsB;GAExC,OAAO,OAAO,cAAc,OAAO;EACrC;EACA,GAAG;CACL,CAAC;AACH;;;;ACvBA,MAAa,wBAAwB;AAcrC,SAAgB,+BAAgE,EAC9E,WACA,QACA,gBAK+B;CAC/B,MAAM,SAAS,gBAAgB;CAC/B,MAAM,SAAgC,EAAE,SAAA,IAA+B;CACvE,IAAI,QAAQ,YAAY,OAAO,aAAa,OAAO;CACnD,IAAI,QAAQ,UAAU,OAAO,WAAW,OAAO;CAE/C,OAAO,SAAS;EAEd,UAAU,YAAY;GAAC;GAAuB;GAAW;EAAM,IAAI,CAAC,eAAe,MAAM;EACzF,eAAgB,YAAY,OAAO,uBAAuB,WAAW,MAAM,IAAI,OAAO,gBAAgB,MAAM;EAC5G,GAAG;CACL,CAAC;AACH;;;AChCA,MAAa,uBAAuB;AAWpC,SAAgB,uBAAoD,EAClE,WACA,QACA,SACA,gBAQA;CACA,MAAM,SAAS,gBAAgB;CAC/B,MAAM,EAAE,QAAQ,mBAAmB,QAAQ,wBAAwB,UAAU;CAC7E,MAAM,aAAa,QAAQ,cAAc,KAAA;CACzC,MAAM,WAAW,QAAQ,YAAY,KAAA;CAErC,MAAM,QAAQ,iBAAiB;EAE7B,UAAU,YACN;GAAC;GAAuB;GAAW;GAAY;IAAE;IAAY;IAAU;GAAQ;EAAC,IAChF;GAAC;GAAe;GAAY;IAAE;IAAY;IAAU;GAAQ;EAAC;EACjE,UAAU,EAAE,gBAAgB;GAC1B,MAAM,SAAgC;IAAE,MAAM;IAAW,SAAA;GAA8B;GACvF,IAAI,YAAY,OAAO,aAAa;GACpC,IAAI,UAAU,OAAO,WAAW;GAChC,IAAI,SAAS,OAAO,UAAU;GAC9B,OAAO,YAAY,OAAO,uBAAuB,WAAW,MAAM,IAAI,OAAO,gBAAgB,MAAM;EACrG;EACA,kBAAkB;EAClB,mBAAmB,UAAU,GAAG,kBAAkB;GAChD,IAAI,CAAC,UAAU,aAAa,UAAU,CAAC,SAAS,YAAY,SAC1D;GAEF,OAAO,gBAAgB;EACzB;EACA,SAAS,SACP,KAAK,MAAM,SAAQ,SAAQ,MAAM,eAAe,CAAC,CAAC;EACpD,GAAG;CACL,CAAC;CAED,gBAAgB;EACd,IAAI,qBAAqB,MAAM,eAAe,CAAC,MAAM,oBACnD,MAAW,cAAc;CAE7B,GAAG,CAAC,mBAAmB,KAAK,CAAC;CAE7B,OAAO;EAAE,GAAG;EAAO;CAAoB;AACzC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ExperimentRef } from '../datasets/use-dataset-experiments.js';
|
|
2
|
+
import type { ExperimentQueriesResult } from '../shared/combine-by-ids.js';
|
|
3
|
+
export interface ExperimentItemUsage {
|
|
4
|
+
inputTokens?: number;
|
|
5
|
+
outputTokens?: number;
|
|
6
|
+
/** Undefined when no group is priced or when groups use different cost units. */
|
|
7
|
+
estimatedCost?: number;
|
|
8
|
+
costUnit?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Usage of one experiment: its totals, and each item's usage keyed by the trace id of its run. */
|
|
11
|
+
export interface ExperimentUsage {
|
|
12
|
+
/** Totals across every item. The cost sums priced groups only. */
|
|
13
|
+
summary: ExperimentItemUsage;
|
|
14
|
+
traces: Record<string, ExperimentItemUsage>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Token and cost usage of several experiments, keyed by experiment id: each entry holds the
|
|
18
|
+
* experiment totals (`summary`) and every item's usage keyed by trace id (`traces`).
|
|
19
|
+
* Sends one metric breakdown request per experiment, filtered by its id rather than by trace ids,
|
|
20
|
+
* so it does not wait for the experiment results. Polls every 2 seconds while an experiment is
|
|
21
|
+
* running or pending. No request is made when the observability store cannot serve metrics.
|
|
22
|
+
*/
|
|
23
|
+
export declare const useExperimentsItemUsage: ({ experiments, supportsMetrics, }: {
|
|
24
|
+
experiments: ExperimentRef[];
|
|
25
|
+
supportsMetrics: boolean;
|
|
26
|
+
}) => ExperimentQueriesResult<ExperimentUsage>;
|
|
27
|
+
//# sourceMappingURL=use-experiment-item-usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-experiment-item-usage.d.ts","sourceRoot":"","sources":["../../../src/hooks/experiments/use-experiment-item-usage.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAEzE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAOxE,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mGAAmG;AACnG,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,OAAO,EAAE,mBAAmB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CAC7C;AAgED;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,sCAGjC;IACD,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,eAAe,EAAE,OAAO,CAAC;CAC1B,KAAG,uBAAuB,CAAC,eAAe,CAqB1C,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { UseQueryResult } from '@tanstack/react-query';
|
|
2
|
+
/** One entry per requested experiment id, in the order the ids were given. */
|
|
3
|
+
export interface ExperimentQueriesResult<T> {
|
|
4
|
+
data: Record<string, T | undefined>;
|
|
5
|
+
/** True while any experiment has not loaded yet. */
|
|
6
|
+
isLoading: boolean;
|
|
7
|
+
/** First error among the experiments, if any. */
|
|
8
|
+
error: Error | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Stable `combine` for `useQueries`: keyed on the ids' contents (callers pass a fresh array every
|
|
12
|
+
* render), so TanStack only recombines when a query result actually changes.
|
|
13
|
+
*/
|
|
14
|
+
export declare const useCombineByIds: <T>(ids: string[]) => (results: Array<UseQueryResult<T, Error>>) => ExperimentQueriesResult<T>;
|
|
15
|
+
//# sourceMappingURL=combine-by-ids.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combine-by-ids.d.ts","sourceRoot":"","sources":["../../../src/hooks/shared/combine-by-ids.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,8EAA8E;AAC9E,MAAM,WAAW,uBAAuB,CAAC,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC;IACpC,oDAAoD;IACpD,SAAS,EAAE,OAAO,CAAC;IACnB,iDAAiD;IACjD,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,OAAO,MAAM,EAAE,eAGlC,KAAK,CAAC,cAAc,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAG,uBAAuB,CAAC,CAAC,CAaxE,CAAC"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_mastra_client_context = require("../../mastra-client-context-DzX3f0RF.cjs");
|
|
3
3
|
const require_use_in_view = require("../../use-in-view-B6eJO9Zi.cjs");
|
|
4
|
+
const require_map = require("../../map-wjmL1y5O.cjs");
|
|
4
5
|
const require_query_utils = require("../../query-utils-CcrChYgz.cjs");
|
|
5
6
|
const require_feedback_refetch_interval = require("../../feedback-refetch-interval-XD5FVc2k.cjs");
|
|
6
|
-
const require_map = require("../../map-wjmL1y5O.cjs");
|
|
7
7
|
let _mastra_client_js = require("@mastra/client-js");
|
|
8
8
|
let react = require("react");
|
|
9
9
|
let _tanstack_react_query = require("@tanstack/react-query");
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as useMastraClient } from "../../mastra-client-context-Bx_g84YB.js";
|
|
2
2
|
import { t as useInView } from "../../use-in-view-C9sYPGRm.js";
|
|
3
|
+
import { t as getOrCreate } from "../../map-CDv4fbu4.js";
|
|
3
4
|
import { n as is403ForbiddenError } from "../../query-utils-D1NgFnWU.js";
|
|
4
5
|
import { t as getFeedbackRefetchInterval } from "../../feedback-refetch-interval-DLHzQoVV.js";
|
|
5
|
-
import { t as getOrCreate } from "../../map-CDv4fbu4.js";
|
|
6
6
|
import { MastraClient, MastraClientError } from "@mastra/client-js";
|
|
7
7
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
8
8
|
import { keepPreviousData, queryOptions, skipToken, useInfiniteQuery, useMutation, useQueries, useQuery, useQueryClient } from "@tanstack/react-query";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/react",
|
|
3
|
-
"version": "1.10.0-alpha.
|
|
3
|
+
"version": "1.10.0-alpha.3",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/mastra-ai/mastra.git",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"lucide-react": "^1.37.0",
|
|
70
70
|
"shiki": "^1.29.2",
|
|
71
71
|
"tailwind-merge": "^3.5.0",
|
|
72
|
-
"@mastra/client-js": "1.54.0-alpha.
|
|
72
|
+
"@mastra/client-js": "1.54.0-alpha.3"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
75
|
"@mastra/core": ">=1.67.0-0 <2.0.0-0",
|
|
@@ -102,9 +102,9 @@
|
|
|
102
102
|
"vite": "^7.3.1",
|
|
103
103
|
"vitest": "4.1.11",
|
|
104
104
|
"zod": "^3.25.76",
|
|
105
|
+
"@internal/types-builder": "0.0.117",
|
|
105
106
|
"@internal/lint": "0.0.142",
|
|
106
|
-
"@mastra/core": "1.77.0-alpha.
|
|
107
|
-
"@internal/types-builder": "0.0.117"
|
|
107
|
+
"@mastra/core": "1.77.0-alpha.3"
|
|
108
108
|
},
|
|
109
109
|
"eslintConfig": {
|
|
110
110
|
"extends": [
|