@mastra/react 1.12.0-alpha.11 → 1.12.0-alpha.12
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/experiments-B7vRMK5T.js +306 -0
- package/dist/experiments-B7vRMK5T.js.map +1 -0
- package/dist/experiments-CJw1N3FB.cjs +353 -0
- package/dist/experiments-CJw1N3FB.cjs.map +1 -0
- package/dist/hooks/datasets/index.cjs +24 -0
- package/dist/hooks/datasets/index.cjs.map +1 -1
- package/dist/hooks/datasets/index.js +24 -1
- package/dist/hooks/datasets/index.js.map +1 -1
- package/dist/hooks/datasets/use-datasets.d.ts +7 -0
- package/dist/hooks/datasets/use-datasets.d.ts.map +1 -1
- package/dist/hooks/experiments/index.cjs +9 -235
- 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 +1 -229
- package/dist/hooks/experiments/usage-accumulator.d.ts +25 -0
- package/dist/hooks/experiments/usage-accumulator.d.ts.map +1 -0
- package/dist/hooks/experiments/use-experiment-item-usage.d.ts +2 -7
- package/dist/hooks/experiments/use-experiment-item-usage.d.ts.map +1 -1
- package/dist/hooks/experiments/use-experiments-list-metrics.d.ts +19 -0
- package/dist/hooks/experiments/use-experiments-list-metrics.d.ts.map +1 -0
- package/dist/hooks/review/index.cjs +2 -2
- package/dist/hooks/review/index.cjs.map +1 -1
- package/dist/hooks/review/index.js +1 -1
- package/package.json +4 -4
- package/dist/hooks/experiments/index.cjs.map +0 -1
- package/dist/hooks/experiments/index.js.map +0 -1
|
@@ -1,236 +1,10 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
/** How many breakdowns to fetch after completion while the exporter may still be flushing metrics. */
|
|
53
|
-
const MAX_EMPTY_ATTEMPTS = 5;
|
|
54
|
-
const isEmptyUsage = (usage) => !usage || Object.keys(usage.traces).length === 0 && usage.summary.inputTokens === void 0 && usage.summary.outputTokens === void 0;
|
|
55
|
-
/**
|
|
56
|
-
* Token and cost usage of several experiments, keyed by experiment id: each entry holds the
|
|
57
|
-
* experiment totals (`summary`) and every item's usage keyed by trace id (`traces`).
|
|
58
|
-
* Sends one metric breakdown request per experiment, filtered by its id rather than by trace ids,
|
|
59
|
-
* so it does not wait for the experiment results. Usage is only fetched once an experiment has
|
|
60
|
-
* finished; while the breakdown is still empty (metrics flushing), it retries every 2 seconds up to
|
|
61
|
-
* 5 attempts. No request is made when the observability store cannot serve metrics.
|
|
62
|
-
*/
|
|
63
|
-
const useExperimentsItemUsage = ({ experiments, supportsMetrics }) => {
|
|
64
|
-
const client = require_mastra_client_context.useMastraClient();
|
|
65
|
-
const combine = require_combine_by_ids.useCombineByIds(experiments.map((experiment) => experiment.id));
|
|
66
|
-
return (0, _tanstack_react_query.useQueries)({
|
|
67
|
-
queries: experiments.map(({ id, status }) => {
|
|
68
|
-
const finished = status !== "running" && status !== "pending";
|
|
69
|
-
return {
|
|
70
|
-
queryKey: [
|
|
71
|
-
"experiment-item-usage",
|
|
72
|
-
id,
|
|
73
|
-
finished
|
|
74
|
-
],
|
|
75
|
-
queryFn: async () => toExperimentUsage(await client.getMetricBreakdown({
|
|
76
|
-
name: [INPUT_TOKEN_METRIC, OUTPUT_TOKEN_METRIC],
|
|
77
|
-
aggregation: "sum",
|
|
78
|
-
groupBy: ["traceId", "name"],
|
|
79
|
-
filters: { experimentId: id }
|
|
80
|
-
})),
|
|
81
|
-
enabled: supportsMetrics && finished,
|
|
82
|
-
refetchInterval: (query) => isEmptyUsage(query.state.data) && query.state.dataUpdateCount < MAX_EMPTY_ATTEMPTS ? POLL_INTERVAL_MS : false
|
|
83
|
-
};
|
|
84
|
-
}),
|
|
85
|
-
combine
|
|
86
|
-
});
|
|
87
|
-
};
|
|
88
|
-
//#endregion
|
|
89
|
-
//#region src/hooks/experiments/use-experiment-metrics.ts
|
|
90
|
-
/**
|
|
91
|
-
* Experiment-scoped metrics (tokens, cost, avg agent latency).
|
|
92
|
-
* Filters only by experimentId — no time window, since the experiment already bounds the row set.
|
|
93
|
-
* Polls every 2 seconds while the experiment is running or pending.
|
|
94
|
-
*
|
|
95
|
-
* Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.
|
|
96
|
-
*/
|
|
97
|
-
const useExperimentMetrics = ({ experimentId, experimentStatus, supportsMetrics, queryOptions }) => {
|
|
98
|
-
const client = require_mastra_client_context.useMastraClient();
|
|
99
|
-
const isEnabled = Boolean(experimentId) && supportsMetrics;
|
|
100
|
-
const query = (0, _tanstack_react_query.useQuery)({
|
|
101
|
-
queryKey: ["experiment-metrics", experimentId],
|
|
102
|
-
refetchInterval: experimentStatus === "running" || experimentStatus === "pending" ? 2e3 : false,
|
|
103
|
-
queryFn: async () => {
|
|
104
|
-
if (!experimentId) throw new Error("experimentId is required");
|
|
105
|
-
const filters = { experimentId };
|
|
106
|
-
const [tokens, avgDuration, runs] = await Promise.all([
|
|
107
|
-
client.getMetricAggregate({
|
|
108
|
-
name: ["mastra_model_total_input_tokens", "mastra_model_total_output_tokens"],
|
|
109
|
-
aggregation: "sum",
|
|
110
|
-
filters
|
|
111
|
-
}),
|
|
112
|
-
client.getMetricAggregate({
|
|
113
|
-
name: ["mastra_agent_duration_ms"],
|
|
114
|
-
aggregation: "avg",
|
|
115
|
-
filters
|
|
116
|
-
}),
|
|
117
|
-
client.getMetricAggregate({
|
|
118
|
-
name: ["mastra_agent_duration_ms"],
|
|
119
|
-
aggregation: "count",
|
|
120
|
-
filters
|
|
121
|
-
})
|
|
122
|
-
]);
|
|
123
|
-
return {
|
|
124
|
-
totalTokens: tokens.value ?? null,
|
|
125
|
-
estimatedCost: tokens.estimatedCost ?? null,
|
|
126
|
-
costUnit: tokens.costUnit ?? null,
|
|
127
|
-
avgAgentDurationMs: avgDuration.value ?? null,
|
|
128
|
-
agentRuns: runs.value ?? null
|
|
129
|
-
};
|
|
130
|
-
},
|
|
131
|
-
...queryOptions
|
|
132
|
-
});
|
|
133
|
-
return {
|
|
134
|
-
data: query.data,
|
|
135
|
-
isLoading: query.isLoading,
|
|
136
|
-
isEnabled
|
|
137
|
-
};
|
|
138
|
-
};
|
|
139
|
-
//#endregion
|
|
140
|
-
//#region src/hooks/experiments/use-experiment-trace.ts
|
|
141
|
-
/**
|
|
142
|
-
* Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.
|
|
143
|
-
*/
|
|
144
|
-
const useExperimentTrace = ({ traceId, queryOptions }) => {
|
|
145
|
-
const client = require_mastra_client_context.useMastraClient();
|
|
146
|
-
return (0, _tanstack_react_query.useQuery)({
|
|
147
|
-
queryKey: ["experiment-trace-light", traceId],
|
|
148
|
-
queryFn: async () => {
|
|
149
|
-
if (!traceId) throw new Error("Trace ID is required");
|
|
150
|
-
return client.getTraceLight(traceId);
|
|
151
|
-
},
|
|
152
|
-
...queryOptions
|
|
153
|
-
});
|
|
154
|
-
};
|
|
155
|
-
//#endregion
|
|
156
|
-
//#region src/hooks/experiments/use-experiments-for-dataset-filter.ts
|
|
157
|
-
/** Explicit page size: server defaults are 20 (global) / 10 (per dataset), which is too small for the list. */
|
|
158
|
-
const EXPERIMENTS_PAGE_SIZE = 100;
|
|
159
|
-
function useExperimentsForDatasetFilter({ datasetId, target, queryOptions }) {
|
|
160
|
-
const client = require_mastra_client_context.useMastraClient();
|
|
161
|
-
const params = { perPage: 100 };
|
|
162
|
-
if (target?.targetType) params.targetType = target.targetType;
|
|
163
|
-
if (target?.targetId) params.targetId = target.targetId;
|
|
164
|
-
return (0, _tanstack_react_query.useQuery)({
|
|
165
|
-
queryKey: datasetId ? [
|
|
166
|
-
"dataset-experiments",
|
|
167
|
-
datasetId,
|
|
168
|
-
params
|
|
169
|
-
] : ["experiments", params],
|
|
170
|
-
queryFn: () => datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params),
|
|
171
|
-
...queryOptions
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
//#endregion
|
|
175
|
-
//#region src/hooks/experiments/use-infinite-experiments.ts
|
|
176
|
-
const EXPERIMENTS_PER_PAGE = 100;
|
|
177
|
-
function useInfiniteExperiments({ datasetId, target, orderBy, queryOptions }) {
|
|
178
|
-
const client = require_mastra_client_context.useMastraClient();
|
|
179
|
-
const { inView: isEndOfListInView, setRef: setEndOfListElement } = require_use_in_view.useInView();
|
|
180
|
-
const targetType = target?.targetType || void 0;
|
|
181
|
-
const targetId = target?.targetId || void 0;
|
|
182
|
-
const query = (0, _tanstack_react_query.useInfiniteQuery)({
|
|
183
|
-
queryKey: datasetId ? [
|
|
184
|
-
"dataset-experiments",
|
|
185
|
-
datasetId,
|
|
186
|
-
"infinite",
|
|
187
|
-
{
|
|
188
|
-
targetType,
|
|
189
|
-
targetId,
|
|
190
|
-
orderBy
|
|
191
|
-
}
|
|
192
|
-
] : [
|
|
193
|
-
"experiments",
|
|
194
|
-
"infinite",
|
|
195
|
-
{
|
|
196
|
-
targetType,
|
|
197
|
-
targetId,
|
|
198
|
-
orderBy
|
|
199
|
-
}
|
|
200
|
-
],
|
|
201
|
-
queryFn: ({ pageParam }) => {
|
|
202
|
-
const params = {
|
|
203
|
-
page: pageParam,
|
|
204
|
-
perPage: 100
|
|
205
|
-
};
|
|
206
|
-
if (targetType) params.targetType = targetType;
|
|
207
|
-
if (targetId) params.targetId = targetId;
|
|
208
|
-
if (orderBy) params.orderBy = orderBy;
|
|
209
|
-
return datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params);
|
|
210
|
-
},
|
|
211
|
-
initialPageParam: 0,
|
|
212
|
-
getNextPageParam: (lastPage, _, lastPageParam) => {
|
|
213
|
-
if (!lastPage?.experiments?.length || !lastPage.pagination?.hasMore) return;
|
|
214
|
-
return lastPageParam + 1;
|
|
215
|
-
},
|
|
216
|
-
select: (data) => data.pages.flatMap((page) => page?.experiments ?? []),
|
|
217
|
-
...queryOptions
|
|
218
|
-
});
|
|
219
|
-
(0, react.useEffect)(() => {
|
|
220
|
-
if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) query.fetchNextPage();
|
|
221
|
-
}, [isEndOfListInView, query]);
|
|
222
|
-
return {
|
|
223
|
-
...query,
|
|
224
|
-
setEndOfListElement
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
//#endregion
|
|
228
|
-
exports.EXPERIMENTS_PAGE_SIZE = EXPERIMENTS_PAGE_SIZE;
|
|
229
|
-
exports.EXPERIMENTS_PER_PAGE = EXPERIMENTS_PER_PAGE;
|
|
230
|
-
exports.useExperimentMetrics = useExperimentMetrics;
|
|
231
|
-
exports.useExperimentTrace = useExperimentTrace;
|
|
232
|
-
exports.useExperimentsForDatasetFilter = useExperimentsForDatasetFilter;
|
|
233
|
-
exports.useExperimentsItemUsage = useExperimentsItemUsage;
|
|
234
|
-
exports.useInfiniteExperiments = useInfiniteExperiments;
|
|
235
|
-
|
|
236
|
-
//# sourceMappingURL=index.cjs.map
|
|
2
|
+
const require_experiments = require("../../experiments-CJw1N3FB.cjs");
|
|
3
|
+
exports.EXPERIMENTS_PAGE_SIZE = require_experiments.EXPERIMENTS_PAGE_SIZE;
|
|
4
|
+
exports.EXPERIMENTS_PER_PAGE = require_experiments.EXPERIMENTS_PER_PAGE;
|
|
5
|
+
exports.useExperimentMetrics = require_experiments.useExperimentMetrics;
|
|
6
|
+
exports.useExperimentTrace = require_experiments.useExperimentTrace;
|
|
7
|
+
exports.useExperimentsForDatasetFilter = require_experiments.useExperimentsForDatasetFilter;
|
|
8
|
+
exports.useExperimentsItemUsage = require_experiments.useExperimentsItemUsage;
|
|
9
|
+
exports.useExperimentsListMetrics = require_experiments.useExperimentsListMetrics;
|
|
10
|
+
exports.useInfiniteExperiments = require_experiments.useInfiniteExperiments;
|
|
@@ -2,5 +2,6 @@ export * from './use-experiment-item-usage.js';
|
|
|
2
2
|
export * from './use-experiment-metrics.js';
|
|
3
3
|
export * from './use-experiment-trace.js';
|
|
4
4
|
export * from './use-experiments-for-dataset-filter.js';
|
|
5
|
+
export * from './use-experiments-list-metrics.js';
|
|
5
6
|
export * from './use-infinite-experiments.js';
|
|
6
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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
|
+
{"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,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC"}
|
|
@@ -1,229 +1 @@
|
|
|
1
|
-
|
|
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";
|
|
5
|
-
import { useEffect } from "react";
|
|
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
|
-
/** How many breakdowns to fetch after completion while the exporter may still be flushing metrics. */
|
|
52
|
-
const MAX_EMPTY_ATTEMPTS = 5;
|
|
53
|
-
const isEmptyUsage = (usage) => !usage || Object.keys(usage.traces).length === 0 && usage.summary.inputTokens === void 0 && usage.summary.outputTokens === void 0;
|
|
54
|
-
/**
|
|
55
|
-
* Token and cost usage of several experiments, keyed by experiment id: each entry holds the
|
|
56
|
-
* experiment totals (`summary`) and every item's usage keyed by trace id (`traces`).
|
|
57
|
-
* Sends one metric breakdown request per experiment, filtered by its id rather than by trace ids,
|
|
58
|
-
* so it does not wait for the experiment results. Usage is only fetched once an experiment has
|
|
59
|
-
* finished; while the breakdown is still empty (metrics flushing), it retries every 2 seconds up to
|
|
60
|
-
* 5 attempts. No request is made when the observability store cannot serve metrics.
|
|
61
|
-
*/
|
|
62
|
-
const useExperimentsItemUsage = ({ experiments, supportsMetrics }) => {
|
|
63
|
-
const client = useMastraClient();
|
|
64
|
-
const combine = useCombineByIds(experiments.map((experiment) => experiment.id));
|
|
65
|
-
return useQueries({
|
|
66
|
-
queries: experiments.map(({ id, status }) => {
|
|
67
|
-
const finished = status !== "running" && status !== "pending";
|
|
68
|
-
return {
|
|
69
|
-
queryKey: [
|
|
70
|
-
"experiment-item-usage",
|
|
71
|
-
id,
|
|
72
|
-
finished
|
|
73
|
-
],
|
|
74
|
-
queryFn: async () => toExperimentUsage(await client.getMetricBreakdown({
|
|
75
|
-
name: [INPUT_TOKEN_METRIC, OUTPUT_TOKEN_METRIC],
|
|
76
|
-
aggregation: "sum",
|
|
77
|
-
groupBy: ["traceId", "name"],
|
|
78
|
-
filters: { experimentId: id }
|
|
79
|
-
})),
|
|
80
|
-
enabled: supportsMetrics && finished,
|
|
81
|
-
refetchInterval: (query) => isEmptyUsage(query.state.data) && query.state.dataUpdateCount < MAX_EMPTY_ATTEMPTS ? POLL_INTERVAL_MS : false
|
|
82
|
-
};
|
|
83
|
-
}),
|
|
84
|
-
combine
|
|
85
|
-
});
|
|
86
|
-
};
|
|
87
|
-
//#endregion
|
|
88
|
-
//#region src/hooks/experiments/use-experiment-metrics.ts
|
|
89
|
-
/**
|
|
90
|
-
* Experiment-scoped metrics (tokens, cost, avg agent latency).
|
|
91
|
-
* Filters only by experimentId — no time window, since the experiment already bounds the row set.
|
|
92
|
-
* Polls every 2 seconds while the experiment is running or pending.
|
|
93
|
-
*
|
|
94
|
-
* Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.
|
|
95
|
-
*/
|
|
96
|
-
const useExperimentMetrics = ({ experimentId, experimentStatus, supportsMetrics, queryOptions }) => {
|
|
97
|
-
const client = useMastraClient();
|
|
98
|
-
const isEnabled = Boolean(experimentId) && supportsMetrics;
|
|
99
|
-
const query = useQuery({
|
|
100
|
-
queryKey: ["experiment-metrics", experimentId],
|
|
101
|
-
refetchInterval: experimentStatus === "running" || experimentStatus === "pending" ? 2e3 : false,
|
|
102
|
-
queryFn: async () => {
|
|
103
|
-
if (!experimentId) throw new Error("experimentId is required");
|
|
104
|
-
const filters = { experimentId };
|
|
105
|
-
const [tokens, avgDuration, runs] = await Promise.all([
|
|
106
|
-
client.getMetricAggregate({
|
|
107
|
-
name: ["mastra_model_total_input_tokens", "mastra_model_total_output_tokens"],
|
|
108
|
-
aggregation: "sum",
|
|
109
|
-
filters
|
|
110
|
-
}),
|
|
111
|
-
client.getMetricAggregate({
|
|
112
|
-
name: ["mastra_agent_duration_ms"],
|
|
113
|
-
aggregation: "avg",
|
|
114
|
-
filters
|
|
115
|
-
}),
|
|
116
|
-
client.getMetricAggregate({
|
|
117
|
-
name: ["mastra_agent_duration_ms"],
|
|
118
|
-
aggregation: "count",
|
|
119
|
-
filters
|
|
120
|
-
})
|
|
121
|
-
]);
|
|
122
|
-
return {
|
|
123
|
-
totalTokens: tokens.value ?? null,
|
|
124
|
-
estimatedCost: tokens.estimatedCost ?? null,
|
|
125
|
-
costUnit: tokens.costUnit ?? null,
|
|
126
|
-
avgAgentDurationMs: avgDuration.value ?? null,
|
|
127
|
-
agentRuns: runs.value ?? null
|
|
128
|
-
};
|
|
129
|
-
},
|
|
130
|
-
...queryOptions
|
|
131
|
-
});
|
|
132
|
-
return {
|
|
133
|
-
data: query.data,
|
|
134
|
-
isLoading: query.isLoading,
|
|
135
|
-
isEnabled
|
|
136
|
-
};
|
|
137
|
-
};
|
|
138
|
-
//#endregion
|
|
139
|
-
//#region src/hooks/experiments/use-experiment-trace.ts
|
|
140
|
-
/**
|
|
141
|
-
* Does not guard on empty ids; pass `queryOptions: { enabled }` to skip the fetch.
|
|
142
|
-
*/
|
|
143
|
-
const useExperimentTrace = ({ traceId, queryOptions }) => {
|
|
144
|
-
const client = useMastraClient();
|
|
145
|
-
return useQuery({
|
|
146
|
-
queryKey: ["experiment-trace-light", traceId],
|
|
147
|
-
queryFn: async () => {
|
|
148
|
-
if (!traceId) throw new Error("Trace ID is required");
|
|
149
|
-
return client.getTraceLight(traceId);
|
|
150
|
-
},
|
|
151
|
-
...queryOptions
|
|
152
|
-
});
|
|
153
|
-
};
|
|
154
|
-
//#endregion
|
|
155
|
-
//#region src/hooks/experiments/use-experiments-for-dataset-filter.ts
|
|
156
|
-
/** Explicit page size: server defaults are 20 (global) / 10 (per dataset), which is too small for the list. */
|
|
157
|
-
const EXPERIMENTS_PAGE_SIZE = 100;
|
|
158
|
-
function useExperimentsForDatasetFilter({ datasetId, target, queryOptions }) {
|
|
159
|
-
const client = useMastraClient();
|
|
160
|
-
const params = { perPage: 100 };
|
|
161
|
-
if (target?.targetType) params.targetType = target.targetType;
|
|
162
|
-
if (target?.targetId) params.targetId = target.targetId;
|
|
163
|
-
return useQuery({
|
|
164
|
-
queryKey: datasetId ? [
|
|
165
|
-
"dataset-experiments",
|
|
166
|
-
datasetId,
|
|
167
|
-
params
|
|
168
|
-
] : ["experiments", params],
|
|
169
|
-
queryFn: () => datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params),
|
|
170
|
-
...queryOptions
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
//#endregion
|
|
174
|
-
//#region src/hooks/experiments/use-infinite-experiments.ts
|
|
175
|
-
const EXPERIMENTS_PER_PAGE = 100;
|
|
176
|
-
function useInfiniteExperiments({ datasetId, target, orderBy, queryOptions }) {
|
|
177
|
-
const client = useMastraClient();
|
|
178
|
-
const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();
|
|
179
|
-
const targetType = target?.targetType || void 0;
|
|
180
|
-
const targetId = target?.targetId || void 0;
|
|
181
|
-
const query = useInfiniteQuery({
|
|
182
|
-
queryKey: datasetId ? [
|
|
183
|
-
"dataset-experiments",
|
|
184
|
-
datasetId,
|
|
185
|
-
"infinite",
|
|
186
|
-
{
|
|
187
|
-
targetType,
|
|
188
|
-
targetId,
|
|
189
|
-
orderBy
|
|
190
|
-
}
|
|
191
|
-
] : [
|
|
192
|
-
"experiments",
|
|
193
|
-
"infinite",
|
|
194
|
-
{
|
|
195
|
-
targetType,
|
|
196
|
-
targetId,
|
|
197
|
-
orderBy
|
|
198
|
-
}
|
|
199
|
-
],
|
|
200
|
-
queryFn: ({ pageParam }) => {
|
|
201
|
-
const params = {
|
|
202
|
-
page: pageParam,
|
|
203
|
-
perPage: 100
|
|
204
|
-
};
|
|
205
|
-
if (targetType) params.targetType = targetType;
|
|
206
|
-
if (targetId) params.targetId = targetId;
|
|
207
|
-
if (orderBy) params.orderBy = orderBy;
|
|
208
|
-
return datasetId ? client.listDatasetExperiments(datasetId, params) : client.listExperiments(params);
|
|
209
|
-
},
|
|
210
|
-
initialPageParam: 0,
|
|
211
|
-
getNextPageParam: (lastPage, _, lastPageParam) => {
|
|
212
|
-
if (!lastPage?.experiments?.length || !lastPage.pagination?.hasMore) return;
|
|
213
|
-
return lastPageParam + 1;
|
|
214
|
-
},
|
|
215
|
-
select: (data) => data.pages.flatMap((page) => page?.experiments ?? []),
|
|
216
|
-
...queryOptions
|
|
217
|
-
});
|
|
218
|
-
useEffect(() => {
|
|
219
|
-
if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) query.fetchNextPage();
|
|
220
|
-
}, [isEndOfListInView, query]);
|
|
221
|
-
return {
|
|
222
|
-
...query,
|
|
223
|
-
setEndOfListElement
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
//#endregion
|
|
227
|
-
export { EXPERIMENTS_PAGE_SIZE, EXPERIMENTS_PER_PAGE, useExperimentMetrics, useExperimentTrace, useExperimentsForDatasetFilter, useExperimentsItemUsage, useInfiniteExperiments };
|
|
228
|
-
|
|
229
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
export { i as EXPERIMENTS_PAGE_SIZE, t as EXPERIMENTS_PER_PAGE, s as useExperimentMetrics, o as useExperimentTrace, a as useExperimentsForDatasetFilter, c as useExperimentsItemUsage, r as useExperimentsListMetrics, n as useInfiniteExperiments } from "../../experiments-B7vRMK5T.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { GetMetricBreakdownResponse } from '@mastra/core/storage';
|
|
2
|
+
export declare const INPUT_TOKEN_METRIC = "mastra_model_total_input_tokens";
|
|
3
|
+
export declare const OUTPUT_TOKEN_METRIC = "mastra_model_total_output_tokens";
|
|
4
|
+
export interface ExperimentItemUsage {
|
|
5
|
+
inputTokens?: number;
|
|
6
|
+
outputTokens?: number;
|
|
7
|
+
/** Undefined when no group is priced or when groups use different cost units. */
|
|
8
|
+
estimatedCost?: number;
|
|
9
|
+
costUnit?: string;
|
|
10
|
+
}
|
|
11
|
+
export type UsageAccumulator = {
|
|
12
|
+
inputTokens?: number;
|
|
13
|
+
outputTokens?: number;
|
|
14
|
+
estimatedCost: number;
|
|
15
|
+
costUnits: Set<string>;
|
|
16
|
+
hasUnknownCostUnit: boolean;
|
|
17
|
+
};
|
|
18
|
+
export declare const createAccumulator: () => UsageAccumulator;
|
|
19
|
+
type BreakdownGroup = GetMetricBreakdownResponse['groups'][number];
|
|
20
|
+
/** The token field a breakdown group feeds, or undefined when the group is not a token metric. */
|
|
21
|
+
export declare function tokenFieldOf(group: BreakdownGroup): 'inputTokens' | 'outputTokens' | undefined;
|
|
22
|
+
export declare function accumulate(accumulator: UsageAccumulator, tokenField: 'inputTokens' | 'outputTokens', group: BreakdownGroup): void;
|
|
23
|
+
export declare function toUsage(accumulator: UsageAccumulator): ExperimentItemUsage;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=usage-accumulator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-accumulator.d.ts","sourceRoot":"","sources":["../../../src/hooks/experiments/usage-accumulator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEvE,eAAO,MAAM,kBAAkB,oCAAoC,CAAC;AACpE,eAAO,MAAM,mBAAmB,qCAAqC,CAAC;AAEtE,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,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAO,gBAInC,CAAC;AAEH,KAAK,cAAc,GAAG,0BAA0B,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE,kGAAkG;AAClG,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,aAAa,GAAG,cAAc,GAAG,SAAS,CAK9F;AAED,wBAAgB,UAAU,CACxB,WAAW,EAAE,gBAAgB,EAC7B,UAAU,EAAE,aAAa,GAAG,cAAc,EAC1C,KAAK,EAAE,cAAc,QAWtB;AAED,wBAAgB,OAAO,CAAC,WAAW,EAAE,gBAAgB,GAAG,mBAAmB,CAS1E"}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import type { ExperimentRef } from '../datasets/use-dataset-experiments.js';
|
|
2
2
|
import type { ExperimentQueriesResult } from '../shared/combine-by-ids.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
outputTokens?: number;
|
|
6
|
-
/** Undefined when no group is priced or when groups use different cost units. */
|
|
7
|
-
estimatedCost?: number;
|
|
8
|
-
costUnit?: string;
|
|
9
|
-
}
|
|
3
|
+
import type { ExperimentItemUsage } from './usage-accumulator.js';
|
|
4
|
+
export type { ExperimentItemUsage } from './usage-accumulator.js';
|
|
10
5
|
/** Usage of one experiment: its totals, and each item's usage keyed by the trace id of its run. */
|
|
11
6
|
export interface ExperimentUsage {
|
|
12
7
|
/** Totals across every item. The cost sums priced groups only. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-experiment-item-usage.d.ts","sourceRoot":"","sources":["../../../src/hooks/experiments/use-experiment-item-usage.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAEzE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"use-experiment-item-usage.d.ts","sourceRoot":"","sources":["../../../src/hooks/experiments/use-experiment-item-usage.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAEzE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAUxE,OAAO,KAAK,EAAE,mBAAmB,EAAoB,MAAM,qBAAqB,CAAC;AAEjF,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAI/D,mGAAmG;AACnG,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,OAAO,EAAE,mBAAmB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CAC7C;AAiCD;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,sCAGjC;IACD,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,eAAe,EAAE,OAAO,CAAC;CAC1B,KAAG,uBAAuB,CAAC,eAAe,CAyB1C,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { UseQueryResult } from '@tanstack/react-query';
|
|
2
|
+
import type { ExperimentRef } from '../datasets/use-dataset-experiments.js';
|
|
3
|
+
import type { ExperimentItemUsage } from './usage-accumulator.js';
|
|
4
|
+
/** Totals of one experiment: token usage, its estimated cost, and the average agent run duration. */
|
|
5
|
+
export interface ExperimentListMetrics extends ExperimentItemUsage {
|
|
6
|
+
avgDurationMs?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Token usage, estimated cost and average agent duration of many experiments, keyed by experiment id.
|
|
10
|
+
* Sends two metric breakdowns per 500 experiments (tokens grouped by experiment and metric name,
|
|
11
|
+
* durations grouped by experiment) instead of one request per experiment.
|
|
12
|
+
* Experiments without any metric are absent from the map. Polls while an experiment is running
|
|
13
|
+
* or pending. No request is made when the observability store cannot serve metrics.
|
|
14
|
+
*/
|
|
15
|
+
export declare const useExperimentsListMetrics: ({ experiments, supportsMetrics, }: {
|
|
16
|
+
experiments: ExperimentRef[];
|
|
17
|
+
supportsMetrics: boolean;
|
|
18
|
+
}) => UseQueryResult<Map<string, ExperimentListMetrics>, Error>;
|
|
19
|
+
//# sourceMappingURL=use-experiments-list-metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-experiments-list-metrics.d.ts","sourceRoot":"","sources":["../../../src/hooks/experiments/use-experiments-list-metrics.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAUzE,OAAO,KAAK,EAAE,mBAAmB,EAAoB,MAAM,qBAAqB,CAAC;AAOjF,qGAAqG;AACrG,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA4CD;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,sCAGnC;IACD,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,eAAe,EAAE,OAAO,CAAC;CAC1B,KAAG,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,EAAE,KAAK,CAwC3D,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_mastra_client_context = require("../../mastra-client-context-DzX3f0RF.cjs");
|
|
3
|
-
const
|
|
3
|
+
const require_experiments = require("../../experiments-CJw1N3FB.cjs");
|
|
4
4
|
let _tanstack_react_query = require("@tanstack/react-query");
|
|
5
5
|
//#region src/hooks/review/use-dataset-review-items.ts
|
|
6
6
|
/**
|
|
@@ -10,7 +10,7 @@ let _tanstack_react_query = require("@tanstack/react-query");
|
|
|
10
10
|
const useReviewItemsByStatus = (status, { experimentId, targetType, targetId, experiments: suppliedExperiments, isLoadingExperiments = false, queryOptions }) => {
|
|
11
11
|
const client = require_mastra_client_context.useMastraClient();
|
|
12
12
|
const hasSuppliedExperiments = suppliedExperiments !== void 0;
|
|
13
|
-
const { data: experimentsData, isLoading: isDiscoveringExperiments } =
|
|
13
|
+
const { data: experimentsData, isLoading: isDiscoveringExperiments } = require_experiments.useExperimentsForDatasetFilter({
|
|
14
14
|
datasetId: void 0,
|
|
15
15
|
target: {
|
|
16
16
|
targetType,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["useMastraClient","useExperimentsForDatasetFilter","useQuery","useMastraClient","useQuery"],"sources":["../../../src/hooks/review/use-dataset-review-items.ts","../../../src/hooks/review/use-review-summary.ts"],"sourcesContent":["import type { DatasetExperiment } from '@mastra/client-js';\nimport { useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport { useExperimentsForDatasetFilter } from '../experiments';\nimport type { ExperimentTargetFilter } from '../experiments';\nimport type { MastraQueryOptions } from '../shared/query-options';\nimport type { ReviewItem } from './types';\n\ntype ReviewStatus = 'needs-review' | 'complete';\n\nexport interface ReviewItemsOptions extends ExperimentTargetFilter {\n /** When set, only this experiment's results are loaded; otherwise every experiment in the project. */\n experimentId?: string;\n /** Explicit source owned by the caller; an empty list disables discovery too. */\n experiments?: DatasetExperiment[];\n isLoadingExperiments?: boolean;\n /** TanStack overrides spread last into the review-items query. */\n queryOptions?: MastraQueryOptions<ReviewItem[]>;\n}\n\n/**\n * Loads experiment results with the given review status, across the project, scoped to a target,\n * or scoped to one experiment.\n */\nconst useReviewItemsByStatus = (\n status: ReviewStatus,\n {\n experimentId,\n targetType,\n targetId,\n experiments: suppliedExperiments,\n isLoadingExperiments = false,\n queryOptions,\n }: ReviewItemsOptions,\n): UseQueryResult<ReviewItem[], Error> => {\n const client = useMastraClient();\n const hasSuppliedExperiments = suppliedExperiments !== undefined;\n const { data: experimentsData, isLoading: isDiscoveringExperiments } = useExperimentsForDatasetFilter({\n datasetId: undefined,\n target: { targetType, targetId },\n queryOptions: { enabled: !hasSuppliedExperiments },\n });\n const experiments = hasSuppliedExperiments ? suppliedExperiments : experimentsData?.experiments;\n const isLoadingSource = hasSuppliedExperiments ? isLoadingExperiments : isDiscoveringExperiments;\n const scopedExperiments = experimentId ? experiments?.filter(exp => exp.id === experimentId) : experiments;\n\n const query = useQuery({\n queryKey: [\n 'review-items',\n status,\n experimentId ?? 'all',\n hasSuppliedExperiments ? 'supplied' : 'discovered',\n hasSuppliedExperiments ? undefined : targetType || 'all',\n hasSuppliedExperiments ? undefined : targetId || 'all',\n scopedExperiments?.map(e => [e.datasetId, e.id]),\n ],\n queryFn: async () => {\n if (!scopedExperiments || scopedExperiments.length === 0) return [] as ReviewItem[];\n\n const allResults = await Promise.all(\n scopedExperiments.map(async exp => {\n if (!exp.datasetId) return [];\n try {\n const { results } = await client.listDatasetExperimentResults(exp.datasetId, exp.id);\n return results\n .filter(r => r.status === status)\n .map(r => ({\n id: r.id,\n input: r.input,\n output: r.output,\n error: r.error,\n itemId: r.itemId,\n experimentId: r.experimentId,\n datasetId: exp.datasetId ?? undefined,\n traceId: r.traceId ?? undefined,\n scores: r.scores ? Object.fromEntries(r.scores.map(s => [s.scorerId, s.score ?? 0])) : {},\n tags: r.tags ?? [],\n targetType: r.targetType,\n createdAt: r.createdAt,\n startedAt: r.startedAt,\n completedAt: r.completedAt,\n status: r.status,\n groundTruth: r.groundTruth,\n toolMockReport: r.toolMockReport,\n }));\n } catch {\n return [];\n }\n }),\n );\n\n return allResults.flat() as ReviewItem[];\n },\n enabled: Boolean(experiments),\n refetchOnWindowFocus: false,\n ...queryOptions,\n });\n\n // The results query is disabled until experiments arrive, so its own `isLoading`\n // is false during that window; surface the upstream load to avoid an empty flash.\n return { ...query, isLoading: query.isLoading || isLoadingSource } as UseQueryResult<ReviewItem[], Error>;\n};\n\n/** Loads persisted review items (status='needs-review'), project-wide, per target or for one experiment. */\nexport const useReviewItems = (options: ReviewItemsOptions = {}) => useReviewItemsByStatus('needs-review', options);\n\n/** Loads completed review items (status='complete'), project-wide, per target or for one experiment. */\nexport const useCompletedItems = (options: ReviewItemsOptions = {}) => useReviewItemsByStatus('complete', options);\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 ReviewSummaryResponse = Awaited<ReturnType<MastraClient['getExperimentReviewSummary']>>;\n\nexport function useReviewSummary<TData = ReviewSummaryResponse>({\n queryOptions,\n}: {\n queryOptions?: MastraQueryOptions<ReviewSummaryResponse, TData>;\n} = {}): UseQueryResult<TData, Error> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['experiment-review-summary'],\n queryFn: () => client.getExperimentReviewSummary(),\n ...queryOptions,\n });\n}\n"],"mappings":";;;;;;;;;AAyBA,MAAM,0BACJ,QACA,EACE,cACA,YACA,UACA,aAAa,qBACb,uBAAuB,OACvB,mBAEsC;CACxC,MAAM,SAASA,8BAAAA,gBAAgB;CAC/B,MAAM,yBAAyB,wBAAwB,KAAA;CACvD,MAAM,EAAE,MAAM,iBAAiB,WAAW,6BAA6BC,
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["useMastraClient","useExperimentsForDatasetFilter","useQuery","useMastraClient","useQuery"],"sources":["../../../src/hooks/review/use-dataset-review-items.ts","../../../src/hooks/review/use-review-summary.ts"],"sourcesContent":["import type { DatasetExperiment } from '@mastra/client-js';\nimport { useQuery } from '@tanstack/react-query';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useMastraClient } from '../../mastra-client-context';\nimport { useExperimentsForDatasetFilter } from '../experiments';\nimport type { ExperimentTargetFilter } from '../experiments';\nimport type { MastraQueryOptions } from '../shared/query-options';\nimport type { ReviewItem } from './types';\n\ntype ReviewStatus = 'needs-review' | 'complete';\n\nexport interface ReviewItemsOptions extends ExperimentTargetFilter {\n /** When set, only this experiment's results are loaded; otherwise every experiment in the project. */\n experimentId?: string;\n /** Explicit source owned by the caller; an empty list disables discovery too. */\n experiments?: DatasetExperiment[];\n isLoadingExperiments?: boolean;\n /** TanStack overrides spread last into the review-items query. */\n queryOptions?: MastraQueryOptions<ReviewItem[]>;\n}\n\n/**\n * Loads experiment results with the given review status, across the project, scoped to a target,\n * or scoped to one experiment.\n */\nconst useReviewItemsByStatus = (\n status: ReviewStatus,\n {\n experimentId,\n targetType,\n targetId,\n experiments: suppliedExperiments,\n isLoadingExperiments = false,\n queryOptions,\n }: ReviewItemsOptions,\n): UseQueryResult<ReviewItem[], Error> => {\n const client = useMastraClient();\n const hasSuppliedExperiments = suppliedExperiments !== undefined;\n const { data: experimentsData, isLoading: isDiscoveringExperiments } = useExperimentsForDatasetFilter({\n datasetId: undefined,\n target: { targetType, targetId },\n queryOptions: { enabled: !hasSuppliedExperiments },\n });\n const experiments = hasSuppliedExperiments ? suppliedExperiments : experimentsData?.experiments;\n const isLoadingSource = hasSuppliedExperiments ? isLoadingExperiments : isDiscoveringExperiments;\n const scopedExperiments = experimentId ? experiments?.filter(exp => exp.id === experimentId) : experiments;\n\n const query = useQuery({\n queryKey: [\n 'review-items',\n status,\n experimentId ?? 'all',\n hasSuppliedExperiments ? 'supplied' : 'discovered',\n hasSuppliedExperiments ? undefined : targetType || 'all',\n hasSuppliedExperiments ? undefined : targetId || 'all',\n scopedExperiments?.map(e => [e.datasetId, e.id]),\n ],\n queryFn: async () => {\n if (!scopedExperiments || scopedExperiments.length === 0) return [] as ReviewItem[];\n\n const allResults = await Promise.all(\n scopedExperiments.map(async exp => {\n if (!exp.datasetId) return [];\n try {\n const { results } = await client.listDatasetExperimentResults(exp.datasetId, exp.id);\n return results\n .filter(r => r.status === status)\n .map(r => ({\n id: r.id,\n input: r.input,\n output: r.output,\n error: r.error,\n itemId: r.itemId,\n experimentId: r.experimentId,\n datasetId: exp.datasetId ?? undefined,\n traceId: r.traceId ?? undefined,\n scores: r.scores ? Object.fromEntries(r.scores.map(s => [s.scorerId, s.score ?? 0])) : {},\n tags: r.tags ?? [],\n targetType: r.targetType,\n createdAt: r.createdAt,\n startedAt: r.startedAt,\n completedAt: r.completedAt,\n status: r.status,\n groundTruth: r.groundTruth,\n toolMockReport: r.toolMockReport,\n }));\n } catch {\n return [];\n }\n }),\n );\n\n return allResults.flat() as ReviewItem[];\n },\n enabled: Boolean(experiments),\n refetchOnWindowFocus: false,\n ...queryOptions,\n });\n\n // The results query is disabled until experiments arrive, so its own `isLoading`\n // is false during that window; surface the upstream load to avoid an empty flash.\n return { ...query, isLoading: query.isLoading || isLoadingSource } as UseQueryResult<ReviewItem[], Error>;\n};\n\n/** Loads persisted review items (status='needs-review'), project-wide, per target or for one experiment. */\nexport const useReviewItems = (options: ReviewItemsOptions = {}) => useReviewItemsByStatus('needs-review', options);\n\n/** Loads completed review items (status='complete'), project-wide, per target or for one experiment. */\nexport const useCompletedItems = (options: ReviewItemsOptions = {}) => useReviewItemsByStatus('complete', options);\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 ReviewSummaryResponse = Awaited<ReturnType<MastraClient['getExperimentReviewSummary']>>;\n\nexport function useReviewSummary<TData = ReviewSummaryResponse>({\n queryOptions,\n}: {\n queryOptions?: MastraQueryOptions<ReviewSummaryResponse, TData>;\n} = {}): UseQueryResult<TData, Error> {\n const client = useMastraClient();\n\n return useQuery({\n queryKey: ['experiment-review-summary'],\n queryFn: () => client.getExperimentReviewSummary(),\n ...queryOptions,\n });\n}\n"],"mappings":";;;;;;;;;AAyBA,MAAM,0BACJ,QACA,EACE,cACA,YACA,UACA,aAAa,qBACb,uBAAuB,OACvB,mBAEsC;CACxC,MAAM,SAASA,8BAAAA,gBAAgB;CAC/B,MAAM,yBAAyB,wBAAwB,KAAA;CACvD,MAAM,EAAE,MAAM,iBAAiB,WAAW,6BAA6BC,oBAAAA,+BAA+B;EACpG,WAAW,KAAA;EACX,QAAQ;GAAE;GAAY;EAAS;EAC/B,cAAc,EAAE,SAAS,CAAC,uBAAuB;CACnD,CAAC;CACD,MAAM,cAAc,yBAAyB,sBAAsB,iBAAiB;CACpF,MAAM,kBAAkB,yBAAyB,uBAAuB;CACxE,MAAM,oBAAoB,eAAe,aAAa,QAAO,QAAO,IAAI,OAAO,YAAY,IAAI;CAE/F,MAAM,SAAA,GAAQC,sBAAAA,SAAAA,CAAS;EACrB,UAAU;GACR;GACA;GACA,gBAAgB;GAChB,yBAAyB,aAAa;GACtC,yBAAyB,KAAA,IAAY,cAAc;GACnD,yBAAyB,KAAA,IAAY,YAAY;GACjD,mBAAmB,KAAI,MAAK,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC;EACjD;EACA,SAAS,YAAY;GACnB,IAAI,CAAC,qBAAqB,kBAAkB,WAAW,GAAG,OAAO,CAAC;GAkClE,QAAO,MAhCkB,QAAQ,IAC/B,kBAAkB,IAAI,OAAM,QAAO;IACjC,IAAI,CAAC,IAAI,WAAW,OAAO,CAAC;IAC5B,IAAI;KACF,MAAM,EAAE,YAAY,MAAM,OAAO,6BAA6B,IAAI,WAAW,IAAI,EAAE;KACnF,OAAO,QACJ,QAAO,MAAK,EAAE,WAAW,MAAM,CAAC,CAChC,KAAI,OAAM;MACT,IAAI,EAAE;MACN,OAAO,EAAE;MACT,QAAQ,EAAE;MACV,OAAO,EAAE;MACT,QAAQ,EAAE;MACV,cAAc,EAAE;MAChB,WAAW,IAAI,aAAa,KAAA;MAC5B,SAAS,EAAE,WAAW,KAAA;MACtB,QAAQ,EAAE,SAAS,OAAO,YAAY,EAAE,OAAO,KAAI,MAAK,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;MACxF,MAAM,EAAE,QAAQ,CAAC;MACjB,YAAY,EAAE;MACd,WAAW,EAAE;MACb,WAAW,EAAE;MACb,aAAa,EAAE;MACf,QAAQ,EAAE;MACV,aAAa,EAAE;MACf,gBAAgB,EAAE;KACpB,EAAE;IACN,QAAQ;KACN,OAAO,CAAC;IACV;GACF,CAAC,CACH,EAAA,CAEkB,KAAK;EACzB;EACA,SAAS,QAAQ,WAAW;EAC5B,sBAAsB;EACtB,GAAG;CACL,CAAC;CAID,OAAO;EAAE,GAAG;EAAO,WAAW,MAAM,aAAa;CAAgB;AACnE;;AAGA,MAAa,kBAAkB,UAA8B,CAAC,MAAM,uBAAuB,gBAAgB,OAAO;;AAGlH,MAAa,qBAAqB,UAA8B,CAAC,MAAM,uBAAuB,YAAY,OAAO;;;ACpGjH,SAAgB,iBAAgD,EAC9D,iBAGE,CAAC,GAAiC;CACpC,MAAM,SAASC,8BAAAA,gBAAgB;CAE/B,QAAA,GAAOC,sBAAAA,SAAAA,CAAS;EACd,UAAU,CAAC,2BAA2B;EACtC,eAAe,OAAO,2BAA2B;EACjD,GAAG;CACL,CAAC;AACH"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as useMastraClient } from "../../mastra-client-context-Bx_g84YB.js";
|
|
2
|
-
import { useExperimentsForDatasetFilter } from "
|
|
2
|
+
import { a as useExperimentsForDatasetFilter } from "../../experiments-B7vRMK5T.js";
|
|
3
3
|
import { useQuery } from "@tanstack/react-query";
|
|
4
4
|
//#region src/hooks/review/use-dataset-review-items.ts
|
|
5
5
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/react",
|
|
3
|
-
"version": "1.12.0-alpha.
|
|
3
|
+
"version": "1.12.0-alpha.12",
|
|
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.56.0-alpha.
|
|
72
|
+
"@mastra/client-js": "1.56.0-alpha.12"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
75
|
"@mastra/core": ">=1.67.0-0 <2.0.0-0",
|
|
@@ -100,9 +100,9 @@
|
|
|
100
100
|
"vite": "^7.3.1",
|
|
101
101
|
"vitest": "4.1.11",
|
|
102
102
|
"zod": "^3.25.76",
|
|
103
|
+
"@internal/lint": "0.0.144",
|
|
103
104
|
"@internal/types-builder": "0.0.119",
|
|
104
|
-
"@mastra/core": "1.79.0-alpha.
|
|
105
|
-
"@internal/lint": "0.0.144"
|
|
105
|
+
"@mastra/core": "1.79.0-alpha.12"
|
|
106
106
|
},
|
|
107
107
|
"engines": {
|
|
108
108
|
"node": ">=22.13.0"
|