@sanity/ailf-studio 0.1.9 → 0.1.11
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/README.md +5 -4
- package/dist/index.d.ts +43 -2
- package/dist/index.js +615 -265
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -68,6 +68,314 @@ var GraduateToNativeAction = (props) => {
|
|
|
68
68
|
};
|
|
69
69
|
GraduateToNativeAction.displayName = "GraduateToNativeAction";
|
|
70
70
|
|
|
71
|
+
// src/actions/RunTaskEvaluationAction.tsx
|
|
72
|
+
import { PlayIcon } from "@sanity/icons";
|
|
73
|
+
import { useToast } from "@sanity/ui";
|
|
74
|
+
import { useCallback as useCallback2, useEffect, useRef, useState as useState2 } from "react";
|
|
75
|
+
import {
|
|
76
|
+
useClient as useClient2,
|
|
77
|
+
useCurrentUser,
|
|
78
|
+
useDataset,
|
|
79
|
+
useProjectId
|
|
80
|
+
} from "sanity";
|
|
81
|
+
|
|
82
|
+
// ../shared/dist/score-grades.js
|
|
83
|
+
var GRADE_BOUNDARIES = {
|
|
84
|
+
good: 80,
|
|
85
|
+
warning: 70,
|
|
86
|
+
critical: 50
|
|
87
|
+
};
|
|
88
|
+
function scoreGrade(score) {
|
|
89
|
+
if (score >= GRADE_BOUNDARIES.good)
|
|
90
|
+
return "good";
|
|
91
|
+
if (score >= GRADE_BOUNDARIES.warning)
|
|
92
|
+
return "warning";
|
|
93
|
+
if (score >= GRADE_BOUNDARIES.critical)
|
|
94
|
+
return "needs-work";
|
|
95
|
+
return "critical";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ../shared/dist/noise-threshold.js
|
|
99
|
+
var NOISE_THRESHOLD = 2;
|
|
100
|
+
|
|
101
|
+
// ../shared/dist/dimension-names.js
|
|
102
|
+
var DIMENSION_LABELS_KEBAB = {
|
|
103
|
+
"code-correctness": "Code Correctness",
|
|
104
|
+
"doc-coverage": "Doc Coverage",
|
|
105
|
+
"task-completion": "Task Completion"
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// src/types.ts
|
|
109
|
+
function formatPercent(n) {
|
|
110
|
+
if (n == null) return "\u2014";
|
|
111
|
+
return `${(n * 100).toFixed(0)}%`;
|
|
112
|
+
}
|
|
113
|
+
function formatRelativeTime(iso) {
|
|
114
|
+
const diff = Date.now() - new Date(iso).getTime();
|
|
115
|
+
const minutes = Math.floor(diff / 6e4);
|
|
116
|
+
if (minutes < 1) return "just now";
|
|
117
|
+
if (minutes === 1) return "1 minute ago";
|
|
118
|
+
if (minutes < 60) return `${minutes} minutes ago`;
|
|
119
|
+
const hours = Math.floor(minutes / 60);
|
|
120
|
+
if (hours === 1) return "1 hour ago";
|
|
121
|
+
if (hours < 24) return `${hours} hours ago`;
|
|
122
|
+
const days = Math.floor(hours / 24);
|
|
123
|
+
if (days === 1) return "yesterday";
|
|
124
|
+
if (days < 7) return `${days} days ago`;
|
|
125
|
+
const weeks = Math.floor(days / 7);
|
|
126
|
+
if (weeks === 1) return "1 week ago";
|
|
127
|
+
if (weeks < 5) return `${weeks} weeks ago`;
|
|
128
|
+
const months = Math.floor(days / 30);
|
|
129
|
+
if (months === 1) return "1 month ago";
|
|
130
|
+
if (months < 12) return `${months} months ago`;
|
|
131
|
+
const years = Math.floor(days / 365);
|
|
132
|
+
if (years === 1) return "1 year ago";
|
|
133
|
+
return `${years} years ago`;
|
|
134
|
+
}
|
|
135
|
+
function formatDelta(n) {
|
|
136
|
+
if (n > 0) return `+${n.toFixed(1)}`;
|
|
137
|
+
if (n < 0) return n.toFixed(1);
|
|
138
|
+
return "0";
|
|
139
|
+
}
|
|
140
|
+
function formatDuration(ms) {
|
|
141
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
142
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
143
|
+
const min = Math.floor(ms / 6e4);
|
|
144
|
+
const sec = Math.round(ms % 6e4 / 1e3);
|
|
145
|
+
return `${min}m ${sec}s`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// src/actions/RunTaskEvaluationAction.tsx
|
|
149
|
+
var EVAL_REQUEST_TYPE = "ailf.evalRequest";
|
|
150
|
+
var POLL_INTERVAL_MS = 15e3;
|
|
151
|
+
var MAX_POLL_MS = 30 * 60 * 1e3;
|
|
152
|
+
var EVAL_REQUEST_STATUS_QUERY = (
|
|
153
|
+
/* groq */
|
|
154
|
+
`
|
|
155
|
+
*[_type == "${EVAL_REQUEST_TYPE}" && _id == $id][0] {
|
|
156
|
+
status,
|
|
157
|
+
error,
|
|
158
|
+
reportId
|
|
159
|
+
}
|
|
160
|
+
`
|
|
161
|
+
);
|
|
162
|
+
var TASK_REPORT_QUERY = (
|
|
163
|
+
/* groq */
|
|
164
|
+
`
|
|
165
|
+
*[_type == "ailf.report"
|
|
166
|
+
&& $taskId in provenance.taskIds
|
|
167
|
+
] | order(completedAt desc) [0] {
|
|
168
|
+
reportId,
|
|
169
|
+
completedAt,
|
|
170
|
+
"overall": summary.overall.avgScore,
|
|
171
|
+
"taskScore": summary.scores[feature == $area][0].totalScore
|
|
172
|
+
}
|
|
173
|
+
`
|
|
174
|
+
);
|
|
175
|
+
function slugify(s) {
|
|
176
|
+
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
|
|
177
|
+
}
|
|
178
|
+
function dateStamp() {
|
|
179
|
+
const d = /* @__PURE__ */ new Date();
|
|
180
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
181
|
+
}
|
|
182
|
+
var RunTaskEvaluationAction = (props) => {
|
|
183
|
+
const { type, draft, published } = props;
|
|
184
|
+
const client = useClient2({ apiVersion: API_VERSION });
|
|
185
|
+
const dataset = useDataset();
|
|
186
|
+
const projectId = useProjectId();
|
|
187
|
+
const currentUser = useCurrentUser();
|
|
188
|
+
const toast = useToast();
|
|
189
|
+
const [state, setState] = useState2({ status: "idle" });
|
|
190
|
+
const requestedAtRef = useRef(null);
|
|
191
|
+
const doc = draft ?? published;
|
|
192
|
+
const taskIdSlug = doc?.id;
|
|
193
|
+
const taskId = taskIdSlug?.current;
|
|
194
|
+
const featureAreaRef = doc?.featureArea;
|
|
195
|
+
const taskDescription = doc?.description ?? taskId ?? "this task";
|
|
196
|
+
const [areaId, setAreaId] = useState2(null);
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
if (!featureAreaRef?._ref) return;
|
|
199
|
+
let cancelled = false;
|
|
200
|
+
client.fetch(`*[_id == $id][0].areaId`, {
|
|
201
|
+
id: featureAreaRef._ref
|
|
202
|
+
}).then((result) => {
|
|
203
|
+
if (!cancelled && result?.current) {
|
|
204
|
+
setAreaId(result.current);
|
|
205
|
+
}
|
|
206
|
+
}).catch(() => {
|
|
207
|
+
});
|
|
208
|
+
return () => {
|
|
209
|
+
cancelled = true;
|
|
210
|
+
};
|
|
211
|
+
}, [client, featureAreaRef?._ref]);
|
|
212
|
+
useEffect(() => {
|
|
213
|
+
if (!taskId || !areaId) return;
|
|
214
|
+
let cancelled = false;
|
|
215
|
+
client.fetch(TASK_REPORT_QUERY, {
|
|
216
|
+
taskId,
|
|
217
|
+
area: areaId
|
|
218
|
+
}).then((result) => {
|
|
219
|
+
if (cancelled || !result) return;
|
|
220
|
+
const score = result.taskScore ?? Math.round(result.overall);
|
|
221
|
+
setState({
|
|
222
|
+
completedAt: result.completedAt,
|
|
223
|
+
reportId: result.reportId,
|
|
224
|
+
score: Math.round(score),
|
|
225
|
+
status: "ready"
|
|
226
|
+
});
|
|
227
|
+
}).catch(() => {
|
|
228
|
+
});
|
|
229
|
+
return () => {
|
|
230
|
+
cancelled = true;
|
|
231
|
+
};
|
|
232
|
+
}, [client, taskId, areaId]);
|
|
233
|
+
useEffect(() => {
|
|
234
|
+
if (state.status !== "requested" && state.status !== "polling") return;
|
|
235
|
+
const { requestId, startedAt } = state;
|
|
236
|
+
if (state.status === "requested") {
|
|
237
|
+
setState({ requestId, startedAt, status: "polling" });
|
|
238
|
+
}
|
|
239
|
+
const interval = setInterval(async () => {
|
|
240
|
+
if (Date.now() - startedAt > MAX_POLL_MS) {
|
|
241
|
+
clearInterval(interval);
|
|
242
|
+
setState({
|
|
243
|
+
message: "Evaluation is still running. Check the AI Literacy dashboard for results.",
|
|
244
|
+
status: "error"
|
|
245
|
+
});
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
const reqStatus = await client.fetch(EVAL_REQUEST_STATUS_QUERY, {
|
|
250
|
+
id: requestId
|
|
251
|
+
});
|
|
252
|
+
if (reqStatus?.status === "failed") {
|
|
253
|
+
clearInterval(interval);
|
|
254
|
+
setState({
|
|
255
|
+
message: reqStatus.error ?? "Evaluation dispatch failed.",
|
|
256
|
+
status: "error"
|
|
257
|
+
});
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (!taskId) return;
|
|
261
|
+
const result = await client.fetch(TASK_REPORT_QUERY, {
|
|
262
|
+
taskId,
|
|
263
|
+
area: areaId ?? ""
|
|
264
|
+
});
|
|
265
|
+
if (result) {
|
|
266
|
+
const reportTime = new Date(result.completedAt).getTime();
|
|
267
|
+
if (reportTime > startedAt) {
|
|
268
|
+
clearInterval(interval);
|
|
269
|
+
const score = result.taskScore ?? Math.round(result.overall);
|
|
270
|
+
setState({
|
|
271
|
+
completedAt: result.completedAt,
|
|
272
|
+
reportId: result.reportId,
|
|
273
|
+
score: Math.round(score),
|
|
274
|
+
status: "ready"
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
} catch {
|
|
279
|
+
}
|
|
280
|
+
}, POLL_INTERVAL_MS);
|
|
281
|
+
return () => clearInterval(interval);
|
|
282
|
+
}, [client, taskId, areaId, state]);
|
|
283
|
+
useEffect(() => {
|
|
284
|
+
if (state.status !== "error") return;
|
|
285
|
+
const timer = setTimeout(() => {
|
|
286
|
+
setState({ status: "idle" });
|
|
287
|
+
}, 15e3);
|
|
288
|
+
return () => clearTimeout(timer);
|
|
289
|
+
}, [state]);
|
|
290
|
+
const handleRequest = useCallback2(async () => {
|
|
291
|
+
if (!taskId) return;
|
|
292
|
+
const tag = `task-${slugify(taskId)}-${dateStamp()}`;
|
|
293
|
+
const now = Date.now();
|
|
294
|
+
try {
|
|
295
|
+
const evalRequest = await client.create({
|
|
296
|
+
_type: EVAL_REQUEST_TYPE,
|
|
297
|
+
dataset,
|
|
298
|
+
mode: "full",
|
|
299
|
+
projectId,
|
|
300
|
+
requestedAt: new Date(now).toISOString(),
|
|
301
|
+
requestedBy: currentUser?.id ?? "unknown",
|
|
302
|
+
status: "pending",
|
|
303
|
+
tag,
|
|
304
|
+
tasks: [taskId],
|
|
305
|
+
...areaId ? { areas: [areaId] } : {}
|
|
306
|
+
});
|
|
307
|
+
requestedAtRef.current = now;
|
|
308
|
+
setState({
|
|
309
|
+
requestId: evalRequest._id,
|
|
310
|
+
startedAt: now,
|
|
311
|
+
status: "requested"
|
|
312
|
+
});
|
|
313
|
+
toast.push({
|
|
314
|
+
closable: true,
|
|
315
|
+
description: `Evaluating "${taskDescription}". Results will appear here when the pipeline completes.`,
|
|
316
|
+
status: "info",
|
|
317
|
+
title: "Task evaluation started"
|
|
318
|
+
});
|
|
319
|
+
} catch (err) {
|
|
320
|
+
const message = err instanceof Error ? err.message : "Failed to create evaluation request";
|
|
321
|
+
setState({ message, status: "error" });
|
|
322
|
+
toast.push({
|
|
323
|
+
closable: true,
|
|
324
|
+
description: message,
|
|
325
|
+
status: "error",
|
|
326
|
+
title: "Task evaluation failed"
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
}, [
|
|
330
|
+
client,
|
|
331
|
+
currentUser?.id,
|
|
332
|
+
dataset,
|
|
333
|
+
projectId,
|
|
334
|
+
taskId,
|
|
335
|
+
taskDescription,
|
|
336
|
+
areaId
|
|
337
|
+
]);
|
|
338
|
+
if (type !== "ailf.task" || !taskId) return null;
|
|
339
|
+
return {
|
|
340
|
+
disabled: state.status === "requested" || state.status === "polling",
|
|
341
|
+
icon: PlayIcon,
|
|
342
|
+
label: getLabel(state),
|
|
343
|
+
onHandle: handleRequest,
|
|
344
|
+
title: getTitle(state, taskId)
|
|
345
|
+
};
|
|
346
|
+
};
|
|
347
|
+
RunTaskEvaluationAction.displayName = "RunTaskEvaluationAction";
|
|
348
|
+
function getLabel(state) {
|
|
349
|
+
switch (state.status) {
|
|
350
|
+
case "idle":
|
|
351
|
+
return "Run Task Eval";
|
|
352
|
+
case "requested":
|
|
353
|
+
return "Requesting\u2026";
|
|
354
|
+
case "polling":
|
|
355
|
+
return "Evaluating\u2026";
|
|
356
|
+
case "ready":
|
|
357
|
+
return `Score: ${state.score}`;
|
|
358
|
+
case "error":
|
|
359
|
+
return "Eval Failed";
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
function getTitle(state, taskId) {
|
|
363
|
+
switch (state.status) {
|
|
364
|
+
case "idle":
|
|
365
|
+
return `Run an AI Literacy evaluation for this task (${taskId}). Runs all test cases against the current documentation.`;
|
|
366
|
+
case "requested":
|
|
367
|
+
return "Creating evaluation request\u2026";
|
|
368
|
+
case "polling":
|
|
369
|
+
return "Evaluation is running. The score will appear here when complete. You can navigate away \u2014 the result will show next time you open this task.";
|
|
370
|
+
case "ready": {
|
|
371
|
+
const when = formatRelativeTime(state.completedAt);
|
|
372
|
+
return `Task Score: ${state.score}/100 (evaluated ${when}). Click to re-run.`;
|
|
373
|
+
}
|
|
374
|
+
case "error":
|
|
375
|
+
return `${state.message} Click to try again.`;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
71
379
|
// src/schema/eval-request.ts
|
|
72
380
|
import { ALL_FIELDS_GROUP, defineField, defineType } from "sanity";
|
|
73
381
|
var evalRequestSchema = defineType({
|
|
@@ -128,13 +436,38 @@ var evalRequestSchema = defineType({
|
|
|
128
436
|
type: "string"
|
|
129
437
|
}),
|
|
130
438
|
defineField({
|
|
131
|
-
description: "Content release perspective ID",
|
|
439
|
+
description: "Content release perspective ID (required for release evals)",
|
|
132
440
|
group: ["main", "all-fields"],
|
|
133
441
|
name: "perspective",
|
|
134
442
|
readOnly: true,
|
|
135
443
|
title: "Perspective",
|
|
136
|
-
type: "string"
|
|
137
|
-
|
|
444
|
+
type: "string"
|
|
445
|
+
}),
|
|
446
|
+
defineField({
|
|
447
|
+
description: "Specific task IDs to evaluate (for task-scoped evals). When set, the pipeline only runs these tasks instead of the full suite.",
|
|
448
|
+
group: ["optional", "all-fields"],
|
|
449
|
+
name: "tasks",
|
|
450
|
+
of: [{ type: "string" }],
|
|
451
|
+
readOnly: true,
|
|
452
|
+
title: "Tasks",
|
|
453
|
+
type: "array"
|
|
454
|
+
}),
|
|
455
|
+
defineField({
|
|
456
|
+
description: "Feature areas to scope the evaluation. When set together with tasks, provides additional context for the pipeline.",
|
|
457
|
+
group: ["optional", "all-fields"],
|
|
458
|
+
name: "areas",
|
|
459
|
+
of: [{ type: "string" }],
|
|
460
|
+
readOnly: true,
|
|
461
|
+
title: "Areas",
|
|
462
|
+
type: "array"
|
|
463
|
+
}),
|
|
464
|
+
defineField({
|
|
465
|
+
description: "Run in debug mode (limits to a subset of test cases for fast feedback).",
|
|
466
|
+
group: ["optional", "all-fields"],
|
|
467
|
+
name: "debug",
|
|
468
|
+
readOnly: true,
|
|
469
|
+
title: "Debug",
|
|
470
|
+
type: "boolean"
|
|
138
471
|
}),
|
|
139
472
|
defineField({
|
|
140
473
|
description: "Sanity project ID",
|
|
@@ -199,15 +532,22 @@ var evalRequestSchema = defineType({
|
|
|
199
532
|
],
|
|
200
533
|
name: "ailf.evalRequest",
|
|
201
534
|
preview: {
|
|
202
|
-
prepare({ perspective, status }) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
535
|
+
prepare({ perspective, status, tasks }) {
|
|
536
|
+
const statusStr = typeof status === "string" ? status : "unknown";
|
|
537
|
+
let title;
|
|
538
|
+
if (typeof perspective === "string") {
|
|
539
|
+
title = perspective;
|
|
540
|
+
} else if (Array.isArray(tasks) && tasks.length > 0) {
|
|
541
|
+
title = tasks.length === 1 ? `Task: ${tasks[0]}` : `Tasks: ${tasks.slice(0, 3).join(", ")}${tasks.length > 3 ? "\u2026" : ""}`;
|
|
542
|
+
} else {
|
|
543
|
+
title = "Evaluation Request";
|
|
544
|
+
}
|
|
545
|
+
return { subtitle: statusStr, title };
|
|
207
546
|
},
|
|
208
547
|
select: {
|
|
209
548
|
perspective: "perspective",
|
|
210
|
-
status: "status"
|
|
549
|
+
status: "status",
|
|
550
|
+
tasks: "tasks"
|
|
211
551
|
}
|
|
212
552
|
},
|
|
213
553
|
title: "AILF Evaluation Request",
|
|
@@ -1218,7 +1558,7 @@ import { ALL_FIELDS_GROUP as ALL_FIELDS_GROUP5, defineField as defineField5, def
|
|
|
1218
1558
|
// src/components/AssertionInput.tsx
|
|
1219
1559
|
import { HelpCircleIcon } from "@sanity/icons";
|
|
1220
1560
|
import { Box as Box2, Card, Flex, Stack as Stack2, Text as Text2 } from "@sanity/ui";
|
|
1221
|
-
import { useCallback as
|
|
1561
|
+
import { useCallback as useCallback3 } from "react";
|
|
1222
1562
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1223
1563
|
var TYPE_HELP = {
|
|
1224
1564
|
"llm-rubric": {
|
|
@@ -1372,7 +1712,7 @@ function AssertionInput(props) {
|
|
|
1372
1712
|
const templateHelp = selectedTemplate ? TEMPLATE_HELP[selectedTemplate] : null;
|
|
1373
1713
|
const isMonospace = selectedType ? MONOSPACE_TYPES.has(selectedType) : false;
|
|
1374
1714
|
const { renderField: parentRenderField } = props;
|
|
1375
|
-
const renderField =
|
|
1715
|
+
const renderField = useCallback3(
|
|
1376
1716
|
(fieldProps) => {
|
|
1377
1717
|
const rendered = parentRenderField(fieldProps);
|
|
1378
1718
|
if (fieldProps.name === "type" && typeHelp) {
|
|
@@ -1400,7 +1740,7 @@ function AssertionInput(props) {
|
|
|
1400
1740
|
// src/components/CanonicalDocInput.tsx
|
|
1401
1741
|
import { HelpCircleIcon as HelpCircleIcon2 } from "@sanity/icons";
|
|
1402
1742
|
import { Box as Box3, Card as Card2, Flex as Flex2, Stack as Stack3, Text as Text3 } from "@sanity/ui";
|
|
1403
|
-
import { useCallback as
|
|
1743
|
+
import { useCallback as useCallback4 } from "react";
|
|
1404
1744
|
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1405
1745
|
var REF_TYPE_HELP = {
|
|
1406
1746
|
slug: {
|
|
@@ -1423,7 +1763,7 @@ function CanonicalDocInput(props) {
|
|
|
1423
1763
|
const selectedType = typeof value?.refType === "string" ? value.refType : null;
|
|
1424
1764
|
const help = selectedType ? REF_TYPE_HELP[selectedType] : null;
|
|
1425
1765
|
const { renderField: parentRenderField } = props;
|
|
1426
|
-
const renderField =
|
|
1766
|
+
const renderField = useCallback4(
|
|
1427
1767
|
(fieldProps) => {
|
|
1428
1768
|
const rendered = parentRenderField(fieldProps);
|
|
1429
1769
|
if (fieldProps.name === "refType" && help) {
|
|
@@ -1616,7 +1956,7 @@ function OriginInput(props) {
|
|
|
1616
1956
|
// src/components/ReleasePicker.tsx
|
|
1617
1957
|
import { SearchIcon } from "@sanity/icons";
|
|
1618
1958
|
import { Autocomplete, Badge as Badge2, Card as Card4, Flex as Flex5, Stack as Stack6, Text as Text7 } from "@sanity/ui";
|
|
1619
|
-
import { useCallback as
|
|
1959
|
+
import { useCallback as useCallback5, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2 } from "react";
|
|
1620
1960
|
import {
|
|
1621
1961
|
getReleaseIdFromReleaseDocumentId as getReleaseIdFromReleaseDocumentId2,
|
|
1622
1962
|
PatchEvent,
|
|
@@ -1662,8 +2002,8 @@ function ReleasePicker(props) {
|
|
|
1662
2002
|
});
|
|
1663
2003
|
return result;
|
|
1664
2004
|
}, [activeReleases, archivedReleases]);
|
|
1665
|
-
const hasSynced =
|
|
1666
|
-
|
|
2005
|
+
const hasSynced = useRef2(false);
|
|
2006
|
+
useEffect2(() => {
|
|
1667
2007
|
if (hasSynced.current || !value || options.length === 0) return;
|
|
1668
2008
|
const match = options.find((o) => o.value === value);
|
|
1669
2009
|
if (match && match.payload.title !== value) {
|
|
@@ -1671,7 +2011,7 @@ function ReleasePicker(props) {
|
|
|
1671
2011
|
formOnChange(PatchEvent.from(set(match.payload.title, titlePath)));
|
|
1672
2012
|
}
|
|
1673
2013
|
}, [value, options, formOnChange, titlePath]);
|
|
1674
|
-
const handleChange =
|
|
2014
|
+
const handleChange = useCallback5(
|
|
1675
2015
|
(newValue) => {
|
|
1676
2016
|
if (newValue) {
|
|
1677
2017
|
onChange(set(newValue));
|
|
@@ -2448,8 +2788,8 @@ import {
|
|
|
2448
2788
|
TabPanel as TabPanel2,
|
|
2449
2789
|
Text as Text34
|
|
2450
2790
|
} from "@sanity/ui";
|
|
2451
|
-
import { useCallback as
|
|
2452
|
-
import { useClient as
|
|
2791
|
+
import { useCallback as useCallback15, useEffect as useEffect10, useState as useState12 } from "react";
|
|
2792
|
+
import { useClient as useClient9 } from "sanity";
|
|
2453
2793
|
import { useRouter } from "sanity/router";
|
|
2454
2794
|
|
|
2455
2795
|
// src/queries.ts
|
|
@@ -2694,8 +3034,8 @@ function filterSourceClause(param) {
|
|
|
2694
3034
|
|
|
2695
3035
|
// src/components/ComparisonView.tsx
|
|
2696
3036
|
import { Badge as Badge3, Box as Box7, Card as Card6, Flex as Flex7, Grid, Select, Stack as Stack8, Text as Text11 } from "@sanity/ui";
|
|
2697
|
-
import { useCallback as
|
|
2698
|
-
import { useClient as
|
|
3037
|
+
import { useCallback as useCallback6, useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
|
|
3038
|
+
import { useClient as useClient3 } from "sanity";
|
|
2699
3039
|
|
|
2700
3040
|
// src/glossary.ts
|
|
2701
3041
|
var GLOSSARY = {
|
|
@@ -2753,32 +3093,6 @@ var GLOSSARY = {
|
|
|
2753
3093
|
dimDocCoverage: "Change in doc coverage between runs. Positive means the docs are providing more useful information."
|
|
2754
3094
|
};
|
|
2755
3095
|
|
|
2756
|
-
// ../shared/dist/score-grades.js
|
|
2757
|
-
var GRADE_BOUNDARIES = {
|
|
2758
|
-
good: 80,
|
|
2759
|
-
warning: 70,
|
|
2760
|
-
critical: 50
|
|
2761
|
-
};
|
|
2762
|
-
function scoreGrade(score) {
|
|
2763
|
-
if (score >= GRADE_BOUNDARIES.good)
|
|
2764
|
-
return "good";
|
|
2765
|
-
if (score >= GRADE_BOUNDARIES.warning)
|
|
2766
|
-
return "warning";
|
|
2767
|
-
if (score >= GRADE_BOUNDARIES.critical)
|
|
2768
|
-
return "needs-work";
|
|
2769
|
-
return "critical";
|
|
2770
|
-
}
|
|
2771
|
-
|
|
2772
|
-
// ../shared/dist/noise-threshold.js
|
|
2773
|
-
var NOISE_THRESHOLD = 2;
|
|
2774
|
-
|
|
2775
|
-
// ../shared/dist/dimension-names.js
|
|
2776
|
-
var DIMENSION_LABELS_KEBAB = {
|
|
2777
|
-
"code-correctness": "Code Correctness",
|
|
2778
|
-
"doc-coverage": "Doc Coverage",
|
|
2779
|
-
"task-completion": "Task Completion"
|
|
2780
|
-
};
|
|
2781
|
-
|
|
2782
3096
|
// src/lib/comparison.ts
|
|
2783
3097
|
function scoreMap(summary) {
|
|
2784
3098
|
return new Map(summary.scores.map((s) => [s.feature, s]));
|
|
@@ -2857,46 +3171,6 @@ function computeDimensionDeltas(baseline, experiment) {
|
|
|
2857
3171
|
});
|
|
2858
3172
|
}
|
|
2859
3173
|
|
|
2860
|
-
// src/types.ts
|
|
2861
|
-
function formatPercent(n) {
|
|
2862
|
-
if (n == null) return "\u2014";
|
|
2863
|
-
return `${(n * 100).toFixed(0)}%`;
|
|
2864
|
-
}
|
|
2865
|
-
function formatRelativeTime(iso) {
|
|
2866
|
-
const diff = Date.now() - new Date(iso).getTime();
|
|
2867
|
-
const minutes = Math.floor(diff / 6e4);
|
|
2868
|
-
if (minutes < 1) return "just now";
|
|
2869
|
-
if (minutes === 1) return "1 minute ago";
|
|
2870
|
-
if (minutes < 60) return `${minutes} minutes ago`;
|
|
2871
|
-
const hours = Math.floor(minutes / 60);
|
|
2872
|
-
if (hours === 1) return "1 hour ago";
|
|
2873
|
-
if (hours < 24) return `${hours} hours ago`;
|
|
2874
|
-
const days = Math.floor(hours / 24);
|
|
2875
|
-
if (days === 1) return "yesterday";
|
|
2876
|
-
if (days < 7) return `${days} days ago`;
|
|
2877
|
-
const weeks = Math.floor(days / 7);
|
|
2878
|
-
if (weeks === 1) return "1 week ago";
|
|
2879
|
-
if (weeks < 5) return `${weeks} weeks ago`;
|
|
2880
|
-
const months = Math.floor(days / 30);
|
|
2881
|
-
if (months === 1) return "1 month ago";
|
|
2882
|
-
if (months < 12) return `${months} months ago`;
|
|
2883
|
-
const years = Math.floor(days / 365);
|
|
2884
|
-
if (years === 1) return "1 year ago";
|
|
2885
|
-
return `${years} years ago`;
|
|
2886
|
-
}
|
|
2887
|
-
function formatDelta(n) {
|
|
2888
|
-
if (n > 0) return `+${n.toFixed(1)}`;
|
|
2889
|
-
if (n < 0) return n.toFixed(1);
|
|
2890
|
-
return "0";
|
|
2891
|
-
}
|
|
2892
|
-
function formatDuration(ms) {
|
|
2893
|
-
if (ms < 1e3) return `${ms}ms`;
|
|
2894
|
-
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
2895
|
-
const min = Math.floor(ms / 6e4);
|
|
2896
|
-
const sec = Math.round(ms % 6e4 / 1e3);
|
|
2897
|
-
return `${min}m ${sec}s`;
|
|
2898
|
-
}
|
|
2899
|
-
|
|
2900
3174
|
// src/components/PageBlurb.tsx
|
|
2901
3175
|
import { Card as Card5, Stack as Stack7, Text as Text8 } from "@sanity/ui";
|
|
2902
3176
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
@@ -2949,23 +3223,23 @@ function LoadingState({ message = "Loading\u2026" }) {
|
|
|
2949
3223
|
// src/components/ComparisonView.tsx
|
|
2950
3224
|
import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2951
3225
|
function ComparisonView() {
|
|
2952
|
-
const client =
|
|
2953
|
-
const [baselineId, setBaselineId] =
|
|
2954
|
-
const [baselineSummary, setBaselineSummary] =
|
|
3226
|
+
const client = useClient3({ apiVersion: API_VERSION });
|
|
3227
|
+
const [baselineId, setBaselineId] = useState3(null);
|
|
3228
|
+
const [baselineSummary, setBaselineSummary] = useState3(
|
|
2955
3229
|
null
|
|
2956
3230
|
);
|
|
2957
|
-
const [experimentId, setExperimentId] =
|
|
2958
|
-
const [experimentSummary, setExperimentSummary] =
|
|
2959
|
-
const [loading, setLoading] =
|
|
2960
|
-
const [reports, setReports] =
|
|
2961
|
-
|
|
3231
|
+
const [experimentId, setExperimentId] = useState3(null);
|
|
3232
|
+
const [experimentSummary, setExperimentSummary] = useState3(null);
|
|
3233
|
+
const [loading, setLoading] = useState3(false);
|
|
3234
|
+
const [reports, setReports] = useState3([]);
|
|
3235
|
+
useEffect3(() => {
|
|
2962
3236
|
client.fetch(latestReportsQuery, {
|
|
2963
3237
|
limit: 50,
|
|
2964
3238
|
mode: null,
|
|
2965
3239
|
source: null
|
|
2966
3240
|
}).then((data) => setReports(data ?? [])).catch(() => setReports([]));
|
|
2967
3241
|
}, [client]);
|
|
2968
|
-
|
|
3242
|
+
useEffect3(() => {
|
|
2969
3243
|
if (!baselineId || !experimentId) {
|
|
2970
3244
|
setBaselineSummary(null);
|
|
2971
3245
|
setExperimentSummary(null);
|
|
@@ -3015,11 +3289,11 @@ function ComparisonView() {
|
|
|
3015
3289
|
const e = experimentSummary.overall.avgScore;
|
|
3016
3290
|
return { baseline: b, delta: e - b, experiment: e };
|
|
3017
3291
|
}, [baselineSummary, experimentSummary]);
|
|
3018
|
-
const onBaseline =
|
|
3292
|
+
const onBaseline = useCallback6(
|
|
3019
3293
|
(e) => setBaselineId(e.currentTarget.value || null),
|
|
3020
3294
|
[]
|
|
3021
3295
|
);
|
|
3022
|
-
const onExperiment =
|
|
3296
|
+
const onExperiment = useCallback6(
|
|
3023
3297
|
(e) => setExperimentId(e.currentTarget.value || null),
|
|
3024
3298
|
[]
|
|
3025
3299
|
);
|
|
@@ -3192,14 +3466,14 @@ import {
|
|
|
3192
3466
|
Stack as Stack13,
|
|
3193
3467
|
Text as Text21
|
|
3194
3468
|
} from "@sanity/ui";
|
|
3195
|
-
import { useCallback as
|
|
3196
|
-
import { useClient as
|
|
3469
|
+
import { useCallback as useCallback12, useEffect as useEffect7, useMemo as useMemo5, useState as useState7 } from "react";
|
|
3470
|
+
import { useClient as useClient6 } from "sanity";
|
|
3197
3471
|
|
|
3198
3472
|
// src/components/content-filters/DocumentFilter.tsx
|
|
3199
3473
|
import { SearchIcon as SearchIcon2 } from "@sanity/icons";
|
|
3200
3474
|
import { Autocomplete as Autocomplete2, Badge as Badge4, Card as Card7, Flex as Flex8, Stack as Stack9, Text as Text12 } from "@sanity/ui";
|
|
3201
|
-
import { useCallback as
|
|
3202
|
-
import { useClient as
|
|
3475
|
+
import { useCallback as useCallback7, useEffect as useEffect4, useRef as useRef3, useState as useState4 } from "react";
|
|
3476
|
+
import { useClient as useClient4 } from "sanity";
|
|
3203
3477
|
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3204
3478
|
var SEARCH_DEBOUNCE_MS = 300;
|
|
3205
3479
|
function DocumentFilter({
|
|
@@ -3207,16 +3481,16 @@ function DocumentFilter({
|
|
|
3207
3481
|
onChange,
|
|
3208
3482
|
onPerspectiveHint
|
|
3209
3483
|
}) {
|
|
3210
|
-
const client =
|
|
3211
|
-
const [options, setOptions] =
|
|
3212
|
-
const [loading, setLoading] =
|
|
3213
|
-
const timer =
|
|
3214
|
-
|
|
3484
|
+
const client = useClient4({ apiVersion: API_VERSION });
|
|
3485
|
+
const [options, setOptions] = useState4([]);
|
|
3486
|
+
const [loading, setLoading] = useState4(false);
|
|
3487
|
+
const timer = useRef3(null);
|
|
3488
|
+
useEffect4(() => {
|
|
3215
3489
|
return () => {
|
|
3216
3490
|
if (timer.current) clearTimeout(timer.current);
|
|
3217
3491
|
};
|
|
3218
3492
|
}, []);
|
|
3219
|
-
const handleQueryChange =
|
|
3493
|
+
const handleQueryChange = useCallback7(
|
|
3220
3494
|
(query) => {
|
|
3221
3495
|
if (timer.current) clearTimeout(timer.current);
|
|
3222
3496
|
const trimmed = (query ?? "").trim();
|
|
@@ -3260,7 +3534,7 @@ function DocumentFilter({
|
|
|
3260
3534
|
},
|
|
3261
3535
|
[client]
|
|
3262
3536
|
);
|
|
3263
|
-
const handleSelect =
|
|
3537
|
+
const handleSelect = useCallback7(
|
|
3264
3538
|
(selected) => {
|
|
3265
3539
|
const option = options.find((o) => o.value === selected);
|
|
3266
3540
|
const slug = option?.payload.slug ?? selected;
|
|
@@ -3271,7 +3545,7 @@ function DocumentFilter({
|
|
|
3271
3545
|
},
|
|
3272
3546
|
[options, onChange, onPerspectiveHint]
|
|
3273
3547
|
);
|
|
3274
|
-
const renderOption =
|
|
3548
|
+
const renderOption = useCallback7((option) => {
|
|
3275
3549
|
const { provenance, releaseId } = option.payload;
|
|
3276
3550
|
const badgeTone = provenance === "published" ? "positive" : provenance === "release" ? "primary" : "caution";
|
|
3277
3551
|
const badgeLabel = provenance === "published" ? "Published" : provenance === "release" ? releaseId ?? "Release" : "Draft";
|
|
@@ -3283,7 +3557,7 @@ function DocumentFilter({
|
|
|
3283
3557
|
/* @__PURE__ */ jsx13(Badge4, { fontSize: 0, tone: badgeTone, children: badgeLabel })
|
|
3284
3558
|
] }) });
|
|
3285
3559
|
}, []);
|
|
3286
|
-
const renderValue =
|
|
3560
|
+
const renderValue = useCallback7((_value, option) => {
|
|
3287
3561
|
if (option?.payload.title) {
|
|
3288
3562
|
return `${option.payload.title} (${option.payload.slug})`;
|
|
3289
3563
|
}
|
|
@@ -3321,20 +3595,20 @@ function classifyDocId(id) {
|
|
|
3321
3595
|
// src/components/content-filters/PerspectiveFilter.tsx
|
|
3322
3596
|
import { SearchIcon as SearchIcon3 } from "@sanity/icons";
|
|
3323
3597
|
import { Autocomplete as Autocomplete3, Badge as Badge5, Card as Card8, Flex as Flex9, Stack as Stack10, Text as Text13 } from "@sanity/ui";
|
|
3324
|
-
import { useEffect as
|
|
3598
|
+
import { useEffect as useEffect5, useMemo as useMemo4, useState as useState5 } from "react";
|
|
3325
3599
|
import {
|
|
3326
3600
|
getReleaseIdFromReleaseDocumentId as getReleaseIdFromReleaseDocumentId3,
|
|
3327
3601
|
useActiveReleases as useActiveReleases3,
|
|
3328
3602
|
useArchivedReleases as useArchivedReleases3,
|
|
3329
|
-
useClient as
|
|
3603
|
+
useClient as useClient5
|
|
3330
3604
|
} from "sanity";
|
|
3331
3605
|
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3332
3606
|
function PerspectiveFilter({ value, onChange }) {
|
|
3333
|
-
const client =
|
|
3334
|
-
const [reportPerspectives, setReportPerspectives] =
|
|
3607
|
+
const client = useClient5({ apiVersion: API_VERSION });
|
|
3608
|
+
const [reportPerspectives, setReportPerspectives] = useState5([]);
|
|
3335
3609
|
const { data: activeReleases } = useActiveReleases3();
|
|
3336
3610
|
const { data: archivedReleases } = useArchivedReleases3();
|
|
3337
|
-
|
|
3611
|
+
useEffect5(() => {
|
|
3338
3612
|
client.fetch(distinctPerspectivesQuery).then(
|
|
3339
3613
|
(data) => setReportPerspectives((data ?? []).filter(Boolean).sort())
|
|
3340
3614
|
).catch(() => setReportPerspectives([]));
|
|
@@ -3402,7 +3676,7 @@ function PerspectiveFilter({ value, onChange }) {
|
|
|
3402
3676
|
|
|
3403
3677
|
// src/components/report-card/ReportCard.tsx
|
|
3404
3678
|
import { Badge as Badge10, Card as Card9, Flex as Flex13, Text as Text17 } from "@sanity/ui";
|
|
3405
|
-
import { useCallback as
|
|
3679
|
+
import { useCallback as useCallback8 } from "react";
|
|
3406
3680
|
|
|
3407
3681
|
// src/components/primitives/DeltaIndicator.tsx
|
|
3408
3682
|
import { Text as Text14 } from "@sanity/ui";
|
|
@@ -3609,7 +3883,7 @@ function StatusBadges({ regressed, improved }) {
|
|
|
3609
3883
|
// src/components/report-card/ReportCard.tsx
|
|
3610
3884
|
import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3611
3885
|
function ReportCard({ data, onSelectReport }) {
|
|
3612
|
-
const handleClick =
|
|
3886
|
+
const handleClick = useCallback8(() => {
|
|
3613
3887
|
onSelectReport(data.reportId);
|
|
3614
3888
|
}, [data.reportId, onSelectReport]);
|
|
3615
3889
|
return /* @__PURE__ */ jsx20(
|
|
@@ -3649,10 +3923,10 @@ function ReportCard({ data, onSelectReport }) {
|
|
|
3649
3923
|
import { SearchIcon as SearchIcon4 } from "@sanity/icons";
|
|
3650
3924
|
import { Card as Card11, Flex as Flex16, Text as Text20 } from "@sanity/ui";
|
|
3651
3925
|
import {
|
|
3652
|
-
useCallback as
|
|
3653
|
-
useEffect as
|
|
3654
|
-
useRef as
|
|
3655
|
-
useState as
|
|
3926
|
+
useCallback as useCallback11,
|
|
3927
|
+
useEffect as useEffect6,
|
|
3928
|
+
useRef as useRef4,
|
|
3929
|
+
useState as useState6
|
|
3656
3930
|
} from "react";
|
|
3657
3931
|
|
|
3658
3932
|
// src/components/search-bar/types.ts
|
|
@@ -3793,12 +4067,12 @@ function filterAndExclude(values, query, dim, activeTokens) {
|
|
|
3793
4067
|
// src/components/search-bar/FilterBadge.tsx
|
|
3794
4068
|
import { CloseIcon } from "@sanity/icons";
|
|
3795
4069
|
import { Badge as Badge11, Flex as Flex14, Text as Text18 } from "@sanity/ui";
|
|
3796
|
-
import { useCallback as
|
|
4070
|
+
import { useCallback as useCallback9 } from "react";
|
|
3797
4071
|
import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
3798
4072
|
function FilterBadge({ token, onRemove }) {
|
|
3799
4073
|
const dim = DIMENSIONS.find((d) => d.key === token.dimension);
|
|
3800
4074
|
const tone = dim?.tone ?? "default";
|
|
3801
|
-
const handleRemove =
|
|
4075
|
+
const handleRemove = useCallback9(
|
|
3802
4076
|
(e) => {
|
|
3803
4077
|
e.stopPropagation();
|
|
3804
4078
|
onRemove(token.id);
|
|
@@ -3838,7 +4112,7 @@ function FilterBadge({ token, onRemove }) {
|
|
|
3838
4112
|
|
|
3839
4113
|
// src/components/search-bar/SuggestionList.tsx
|
|
3840
4114
|
import { Badge as Badge12, Card as Card10, Flex as Flex15, Stack as Stack12, Text as Text19 } from "@sanity/ui";
|
|
3841
|
-
import { useCallback as
|
|
4115
|
+
import { useCallback as useCallback10 } from "react";
|
|
3842
4116
|
import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3843
4117
|
function SuggestionList({
|
|
3844
4118
|
suggestions,
|
|
@@ -3902,7 +4176,7 @@ function SuggestionItem({
|
|
|
3902
4176
|
const dim = DIMENSIONS.find((d) => d.key === suggestion.dimension);
|
|
3903
4177
|
const tone = dim?.tone ?? "default";
|
|
3904
4178
|
const isHint = suggestion.category === "Filters";
|
|
3905
|
-
const handleClick =
|
|
4179
|
+
const handleClick = useCallback10(() => {
|
|
3906
4180
|
onSelect(suggestion);
|
|
3907
4181
|
}, [onSelect, suggestion]);
|
|
3908
4182
|
return /* @__PURE__ */ jsx22(
|
|
@@ -3940,11 +4214,11 @@ function SearchBar({
|
|
|
3940
4214
|
onTokenAdd,
|
|
3941
4215
|
onTokenRemove
|
|
3942
4216
|
}) {
|
|
3943
|
-
const [focused, setFocused] =
|
|
3944
|
-
const [activeIndex, setActiveIndex] =
|
|
3945
|
-
const inputRef =
|
|
3946
|
-
const blurTimerRef =
|
|
3947
|
-
|
|
4217
|
+
const [focused, setFocused] = useState6(false);
|
|
4218
|
+
const [activeIndex, setActiveIndex] = useState6(-1);
|
|
4219
|
+
const inputRef = useRef4(null);
|
|
4220
|
+
const blurTimerRef = useRef4(null);
|
|
4221
|
+
useEffect6(() => {
|
|
3948
4222
|
return () => {
|
|
3949
4223
|
if (blurTimerRef.current) {
|
|
3950
4224
|
clearTimeout(blurTimerRef.current);
|
|
@@ -3952,10 +4226,10 @@ function SearchBar({
|
|
|
3952
4226
|
};
|
|
3953
4227
|
}, []);
|
|
3954
4228
|
const suggestions = focused ? computeSuggestions({ query, activeTokens: tokens, models, areas }) : [];
|
|
3955
|
-
|
|
4229
|
+
useEffect6(() => {
|
|
3956
4230
|
setActiveIndex(-1);
|
|
3957
4231
|
}, [query, tokens.length]);
|
|
3958
|
-
const handleTokenRemove =
|
|
4232
|
+
const handleTokenRemove = useCallback11(
|
|
3959
4233
|
(id) => {
|
|
3960
4234
|
onTokenRemove(id);
|
|
3961
4235
|
requestAnimationFrame(() => {
|
|
@@ -3964,7 +4238,7 @@ function SearchBar({
|
|
|
3964
4238
|
},
|
|
3965
4239
|
[onTokenRemove]
|
|
3966
4240
|
);
|
|
3967
|
-
const handleSuggestionSelect =
|
|
4241
|
+
const handleSuggestionSelect = useCallback11(
|
|
3968
4242
|
(suggestion) => {
|
|
3969
4243
|
if (suggestion.category === "Filters") {
|
|
3970
4244
|
onQueryChange(suggestion.value);
|
|
@@ -3983,7 +4257,7 @@ function SearchBar({
|
|
|
3983
4257
|
},
|
|
3984
4258
|
[onTokenAdd, onQueryChange]
|
|
3985
4259
|
);
|
|
3986
|
-
const handleKeyDown =
|
|
4260
|
+
const handleKeyDown = useCallback11(
|
|
3987
4261
|
(e) => {
|
|
3988
4262
|
if (e.key === "ArrowDown") {
|
|
3989
4263
|
e.preventDefault();
|
|
@@ -4011,27 +4285,27 @@ function SearchBar({
|
|
|
4011
4285
|
handleSuggestionSelect
|
|
4012
4286
|
]
|
|
4013
4287
|
);
|
|
4014
|
-
const handleInputChange =
|
|
4288
|
+
const handleInputChange = useCallback11(
|
|
4015
4289
|
(e) => {
|
|
4016
4290
|
const value = e.target.value;
|
|
4017
4291
|
onQueryChange(value);
|
|
4018
4292
|
},
|
|
4019
4293
|
[onQueryChange]
|
|
4020
4294
|
);
|
|
4021
|
-
const handleBlur =
|
|
4295
|
+
const handleBlur = useCallback11(() => {
|
|
4022
4296
|
blurTimerRef.current = setTimeout(() => {
|
|
4023
4297
|
blurTimerRef.current = null;
|
|
4024
4298
|
setFocused(false);
|
|
4025
4299
|
}, 200);
|
|
4026
4300
|
}, []);
|
|
4027
|
-
const handleFocus =
|
|
4301
|
+
const handleFocus = useCallback11(() => {
|
|
4028
4302
|
if (blurTimerRef.current) {
|
|
4029
4303
|
clearTimeout(blurTimerRef.current);
|
|
4030
4304
|
blurTimerRef.current = null;
|
|
4031
4305
|
}
|
|
4032
4306
|
setFocused(true);
|
|
4033
4307
|
}, []);
|
|
4034
|
-
const handleBarClick =
|
|
4308
|
+
const handleBarClick = useCallback11(() => {
|
|
4035
4309
|
inputRef.current?.focus();
|
|
4036
4310
|
}, []);
|
|
4037
4311
|
return /* @__PURE__ */ jsxs20("div", { style: { position: "relative" }, children: [
|
|
@@ -4104,22 +4378,22 @@ function LatestReports({
|
|
|
4104
4378
|
pageSize = 20,
|
|
4105
4379
|
source = null
|
|
4106
4380
|
}) {
|
|
4107
|
-
const client =
|
|
4108
|
-
const [initialLoading, setInitialLoading] =
|
|
4109
|
-
const [loadingMore, setLoadingMore] =
|
|
4110
|
-
const [reports, setReports] =
|
|
4111
|
-
const [hasMore, setHasMore] =
|
|
4112
|
-
const [searchQuery, setSearchQuery] =
|
|
4113
|
-
const [filterTokens, setFilterTokens] =
|
|
4114
|
-
const [documentSlug, setDocumentSlug] =
|
|
4115
|
-
const [perspective, setPerspective] =
|
|
4116
|
-
const [sort, setSort] =
|
|
4381
|
+
const client = useClient6({ apiVersion: API_VERSION });
|
|
4382
|
+
const [initialLoading, setInitialLoading] = useState7(true);
|
|
4383
|
+
const [loadingMore, setLoadingMore] = useState7(false);
|
|
4384
|
+
const [reports, setReports] = useState7([]);
|
|
4385
|
+
const [hasMore, setHasMore] = useState7(true);
|
|
4386
|
+
const [searchQuery, setSearchQuery] = useState7("");
|
|
4387
|
+
const [filterTokens, setFilterTokens] = useState7([]);
|
|
4388
|
+
const [documentSlug, setDocumentSlug] = useState7("");
|
|
4389
|
+
const [perspective, setPerspective] = useState7("");
|
|
4390
|
+
const [sort, setSort] = useState7({
|
|
4117
4391
|
direction: "desc",
|
|
4118
4392
|
field: "date"
|
|
4119
4393
|
});
|
|
4120
|
-
const [availableModels, setAvailableModels] =
|
|
4121
|
-
const [availableAreas, setAvailableAreas] =
|
|
4122
|
-
|
|
4394
|
+
const [availableModels, setAvailableModels] = useState7([]);
|
|
4395
|
+
const [availableAreas, setAvailableAreas] = useState7([]);
|
|
4396
|
+
useEffect7(() => {
|
|
4123
4397
|
setInitialLoading(true);
|
|
4124
4398
|
setHasMore(true);
|
|
4125
4399
|
client.fetch(latestReportsQuery, {
|
|
@@ -4137,7 +4411,7 @@ function LatestReports({
|
|
|
4137
4411
|
setInitialLoading(false);
|
|
4138
4412
|
});
|
|
4139
4413
|
}, [client, pageSize, mode, source]);
|
|
4140
|
-
const handleLoadMore =
|
|
4414
|
+
const handleLoadMore = useCallback12(() => {
|
|
4141
4415
|
if (loadingMore || !hasMore) return;
|
|
4142
4416
|
setLoadingMore(true);
|
|
4143
4417
|
const nextLimit = reports.length + pageSize;
|
|
@@ -4154,7 +4428,7 @@ function LatestReports({
|
|
|
4154
4428
|
setLoadingMore(false);
|
|
4155
4429
|
});
|
|
4156
4430
|
}, [client, hasMore, loadingMore, mode, pageSize, reports.length, source]);
|
|
4157
|
-
|
|
4431
|
+
useEffect7(() => {
|
|
4158
4432
|
client.fetch(distinctModelsQuery).then((data) => setAvailableModels((data ?? []).sort())).catch(() => setAvailableModels([]));
|
|
4159
4433
|
client.fetch(distinctAreasQuery).then((data) => setAvailableAreas((data ?? []).sort())).catch(() => setAvailableAreas([]));
|
|
4160
4434
|
}, [client]);
|
|
@@ -4238,7 +4512,7 @@ function LatestReports({
|
|
|
4238
4512
|
});
|
|
4239
4513
|
return result;
|
|
4240
4514
|
}, [reports, searchQuery, activeFilters, documentSlug, perspective, sort]);
|
|
4241
|
-
const handleTokenAdd =
|
|
4515
|
+
const handleTokenAdd = useCallback12((token) => {
|
|
4242
4516
|
setFilterTokens((prev) => {
|
|
4243
4517
|
const dim = token.dimension;
|
|
4244
4518
|
const isMulti = dim === "area";
|
|
@@ -4248,22 +4522,22 @@ function LatestReports({
|
|
|
4248
4522
|
return [...prev, token];
|
|
4249
4523
|
});
|
|
4250
4524
|
}, []);
|
|
4251
|
-
const handleTokenRemove =
|
|
4525
|
+
const handleTokenRemove = useCallback12((id) => {
|
|
4252
4526
|
setFilterTokens((prev) => prev.filter((t) => t.id !== id));
|
|
4253
4527
|
}, []);
|
|
4254
|
-
const toggleSortDirection =
|
|
4528
|
+
const toggleSortDirection = useCallback12(() => {
|
|
4255
4529
|
setSort((prev) => ({
|
|
4256
4530
|
...prev,
|
|
4257
4531
|
direction: prev.direction === "asc" ? "desc" : "asc"
|
|
4258
4532
|
}));
|
|
4259
4533
|
}, []);
|
|
4260
|
-
const handleSortFieldChange =
|
|
4534
|
+
const handleSortFieldChange = useCallback12((field) => {
|
|
4261
4535
|
setSort(
|
|
4262
4536
|
(prev) => prev.field === field ? { ...prev, direction: prev.direction === "asc" ? "desc" : "asc" } : { direction: "desc", field }
|
|
4263
4537
|
);
|
|
4264
4538
|
}, []);
|
|
4265
4539
|
const hasActiveFilters = searchQuery.trim() !== "" || filterTokens.length > 0 || documentSlug.trim() !== "" || perspective.trim() !== "";
|
|
4266
|
-
const handleClearFilters =
|
|
4540
|
+
const handleClearFilters = useCallback12(() => {
|
|
4267
4541
|
setSearchQuery("");
|
|
4268
4542
|
setFilterTokens([]);
|
|
4269
4543
|
setDocumentSlug("");
|
|
@@ -4460,12 +4734,26 @@ function getDateThreshold(preset) {
|
|
|
4460
4734
|
|
|
4461
4735
|
// src/components/report-detail/ReportDetail.tsx
|
|
4462
4736
|
import { ArrowLeftIcon as ArrowLeftIcon2 } from "@sanity/icons";
|
|
4463
|
-
import {
|
|
4464
|
-
|
|
4465
|
-
|
|
4737
|
+
import {
|
|
4738
|
+
Box as Box15,
|
|
4739
|
+
Button as Button3,
|
|
4740
|
+
Stack as Stack23,
|
|
4741
|
+
Tab,
|
|
4742
|
+
TabList,
|
|
4743
|
+
TabPanel,
|
|
4744
|
+
Text as Text32,
|
|
4745
|
+
Tooltip as Tooltip9
|
|
4746
|
+
} from "@sanity/ui";
|
|
4747
|
+
import {
|
|
4748
|
+
useCallback as useCallback13,
|
|
4749
|
+
useEffect as useEffect8,
|
|
4750
|
+
useMemo as useMemo7,
|
|
4751
|
+
useState as useState10
|
|
4752
|
+
} from "react";
|
|
4753
|
+
import { useClient as useClient7 } from "sanity";
|
|
4466
4754
|
|
|
4467
4755
|
// src/components/report-detail/AgentActivitySection.tsx
|
|
4468
|
-
import { useMemo as useMemo6, useState as
|
|
4756
|
+
import { useMemo as useMemo6, useState as useState8 } from "react";
|
|
4469
4757
|
import { HelpCircleIcon as HelpCircleIcon5, SearchIcon as SearchIcon5 } from "@sanity/icons";
|
|
4470
4758
|
import {
|
|
4471
4759
|
Badge as Badge14,
|
|
@@ -4640,7 +4928,7 @@ function FeatureActivityCard({
|
|
|
4640
4928
|
] }) });
|
|
4641
4929
|
}
|
|
4642
4930
|
function SearchQueryList({ queries }) {
|
|
4643
|
-
const [filter, setFilter] =
|
|
4931
|
+
const [filter, setFilter] = useState8("");
|
|
4644
4932
|
const filtered = useMemo6(() => {
|
|
4645
4933
|
if (!filter) return queries;
|
|
4646
4934
|
const lower = filter.toLowerCase();
|
|
@@ -4944,7 +5232,7 @@ function AreaBadgeGroup({
|
|
|
4944
5232
|
}
|
|
4945
5233
|
|
|
4946
5234
|
// src/components/report-detail/JudgmentList.tsx
|
|
4947
|
-
import { useState as
|
|
5235
|
+
import { useState as useState9 } from "react";
|
|
4948
5236
|
import { HelpCircleIcon as HelpCircleIcon6 } from "@sanity/icons";
|
|
4949
5237
|
import { Badge as Badge16, Box as Box12, Card as Card18, Flex as Flex20, Stack as Stack18, Text as Text27, Tooltip as Tooltip6 } from "@sanity/ui";
|
|
4950
5238
|
|
|
@@ -5019,7 +5307,7 @@ function JudgmentList({ judgments }) {
|
|
|
5019
5307
|
] }) });
|
|
5020
5308
|
}
|
|
5021
5309
|
function JudgmentCard({ judgment }) {
|
|
5022
|
-
const [expanded, setExpanded] =
|
|
5310
|
+
const [expanded, setExpanded] = useState9(false);
|
|
5023
5311
|
const dimLabel = DIMENSION_LABELS[judgment.dimension] ?? judgment.dimension;
|
|
5024
5312
|
const sep = judgment.taskId.indexOf(" - ");
|
|
5025
5313
|
const taskName = sep > 0 ? judgment.taskId.substring(sep + 3) : judgment.taskId;
|
|
@@ -5060,33 +5348,49 @@ function JudgmentCard({ judgment }) {
|
|
|
5060
5348
|
) }),
|
|
5061
5349
|
judgment.canonicalDocs && judgment.canonicalDocs.length > 0 && /* @__PURE__ */ jsxs26(Flex20, { align: "center", gap: 2, wrap: "wrap", children: [
|
|
5062
5350
|
/* @__PURE__ */ jsx31(Text27, { muted: true, size: 0, children: "Docs:" }),
|
|
5063
|
-
judgment.canonicalDocs.map((doc) => {
|
|
5064
|
-
const badge = /* @__PURE__ */ jsx31(Badge16, { mode: "outline", tone: "primary", children: doc.slug });
|
|
5065
|
-
return /* @__PURE__ */ jsx31(
|
|
5066
|
-
Tooltip6,
|
|
5067
|
-
{
|
|
5068
|
-
content: /* @__PURE__ */ jsx31(Box12, { padding: 2, children: /* @__PURE__ */ jsx31(Text27, { size: 1, children: doc.title || doc.slug }) }),
|
|
5069
|
-
placement: "bottom",
|
|
5070
|
-
portal: true,
|
|
5071
|
-
children: doc.documentId ? /* @__PURE__ */ jsx31(
|
|
5072
|
-
"a",
|
|
5073
|
-
{
|
|
5074
|
-
href: `/intent/edit/id=${doc.documentId}`,
|
|
5075
|
-
onClick: (e) => e.stopPropagation(),
|
|
5076
|
-
style: { textDecoration: "none" },
|
|
5077
|
-
children: badge
|
|
5078
|
-
}
|
|
5079
|
-
) : badge
|
|
5080
|
-
},
|
|
5081
|
-
doc.slug
|
|
5082
|
-
);
|
|
5083
|
-
})
|
|
5351
|
+
judgment.canonicalDocs.map((doc) => /* @__PURE__ */ jsx31(DocBadge, { doc }, doc.slug))
|
|
5084
5352
|
] })
|
|
5085
5353
|
] })
|
|
5086
5354
|
] })
|
|
5087
5355
|
}
|
|
5088
5356
|
);
|
|
5089
5357
|
}
|
|
5358
|
+
var editLinkStyle = {
|
|
5359
|
+
cursor: "pointer",
|
|
5360
|
+
display: "inline-block",
|
|
5361
|
+
textDecoration: "none",
|
|
5362
|
+
transition: "opacity 150ms ease"
|
|
5363
|
+
};
|
|
5364
|
+
function DocBadge({
|
|
5365
|
+
doc
|
|
5366
|
+
}) {
|
|
5367
|
+
const [hovered, setHovered] = useState9(false);
|
|
5368
|
+
const isLinked = Boolean(doc.documentId);
|
|
5369
|
+
const tooltipLabel = isLinked ? `Edit "${doc.title || doc.slug}"` : doc.title || doc.slug;
|
|
5370
|
+
const badge = /* @__PURE__ */ jsx31(Badge16, { mode: "outline", tone: isLinked && hovered ? "caution" : "primary", children: doc.slug });
|
|
5371
|
+
return /* @__PURE__ */ jsx31(
|
|
5372
|
+
Tooltip6,
|
|
5373
|
+
{
|
|
5374
|
+
content: /* @__PURE__ */ jsx31(Box12, { padding: 2, children: /* @__PURE__ */ jsx31(Text27, { size: 1, children: tooltipLabel }) }),
|
|
5375
|
+
placement: "bottom",
|
|
5376
|
+
portal: true,
|
|
5377
|
+
children: isLinked ? /* @__PURE__ */ jsx31(
|
|
5378
|
+
"a",
|
|
5379
|
+
{
|
|
5380
|
+
href: `/intent/edit/id=${doc.documentId}`,
|
|
5381
|
+
onClick: (e) => e.stopPropagation(),
|
|
5382
|
+
onMouseEnter: () => setHovered(true),
|
|
5383
|
+
onMouseLeave: () => setHovered(false),
|
|
5384
|
+
style: {
|
|
5385
|
+
...editLinkStyle,
|
|
5386
|
+
opacity: hovered ? 0.8 : 1
|
|
5387
|
+
},
|
|
5388
|
+
children: badge
|
|
5389
|
+
}
|
|
5390
|
+
) : /* @__PURE__ */ jsx31("span", { children: badge })
|
|
5391
|
+
}
|
|
5392
|
+
);
|
|
5393
|
+
}
|
|
5090
5394
|
|
|
5091
5395
|
// src/components/report-detail/OverviewStats.tsx
|
|
5092
5396
|
import { Grid as Grid4 } from "@sanity/ui";
|
|
@@ -5642,10 +5946,10 @@ function ReportDetail({
|
|
|
5642
5946
|
onTabChange,
|
|
5643
5947
|
reportId
|
|
5644
5948
|
}) {
|
|
5645
|
-
const client =
|
|
5646
|
-
const [loading, setLoading] =
|
|
5647
|
-
const [report, setReport] =
|
|
5648
|
-
|
|
5949
|
+
const client = useClient7({ apiVersion: API_VERSION });
|
|
5950
|
+
const [loading, setLoading] = useState10(true);
|
|
5951
|
+
const [report, setReport] = useState10(null);
|
|
5952
|
+
useEffect8(() => {
|
|
5649
5953
|
let cancelled = false;
|
|
5650
5954
|
setLoading(true);
|
|
5651
5955
|
client.fetch(reportDetailQuery, { reportId }).then((data) => {
|
|
@@ -5660,7 +5964,7 @@ function ReportDetail({
|
|
|
5660
5964
|
cancelled = true;
|
|
5661
5965
|
};
|
|
5662
5966
|
}, [client, reportId]);
|
|
5663
|
-
const handleCopyReportId =
|
|
5967
|
+
const handleCopyReportId = useCallback13(() => {
|
|
5664
5968
|
if (!report) return;
|
|
5665
5969
|
navigator.clipboard.writeText(report.reportId).catch(() => {
|
|
5666
5970
|
});
|
|
@@ -5672,17 +5976,22 @@ function ReportDetail({
|
|
|
5672
5976
|
const hasAgentActivity = Boolean(
|
|
5673
5977
|
summary?.agentBehavior && summary.agentBehavior.length > 0
|
|
5674
5978
|
);
|
|
5675
|
-
const tabs = useMemo7(
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5979
|
+
const tabs = useMemo7(
|
|
5980
|
+
() => [OVERVIEW_TAB, DIAGNOSTICS_TAB, ACTIVITY_TAB],
|
|
5981
|
+
[]
|
|
5982
|
+
);
|
|
5983
|
+
const disabledTabs = useMemo7(() => {
|
|
5984
|
+
const set2 = /* @__PURE__ */ new Set();
|
|
5985
|
+
if (!hasDiagnostics) set2.add("diagnostics");
|
|
5986
|
+
if (!hasAgentActivity) set2.add("activity");
|
|
5987
|
+
return set2;
|
|
5680
5988
|
}, [hasDiagnostics, hasAgentActivity]);
|
|
5681
5989
|
const currentTab = useMemo7(() => {
|
|
5682
5990
|
const parsed = parseTab(activeTab);
|
|
5991
|
+
if (disabledTabs.has(parsed)) return "overview";
|
|
5683
5992
|
return tabs.some((t) => t.id === parsed) ? parsed : "overview";
|
|
5684
|
-
}, [activeTab, tabs]);
|
|
5685
|
-
const handleTabClick =
|
|
5993
|
+
}, [activeTab, disabledTabs, tabs]);
|
|
5994
|
+
const handleTabClick = useCallback13(
|
|
5686
5995
|
(tabId) => {
|
|
5687
5996
|
onTabChange(tabId === "overview" ? null : tabId);
|
|
5688
5997
|
},
|
|
@@ -5721,17 +6030,31 @@ function ReportDetail({
|
|
|
5721
6030
|
tag: report.tag
|
|
5722
6031
|
}
|
|
5723
6032
|
),
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
6033
|
+
/* @__PURE__ */ jsx37(TabList, { space: 1, children: tabs.map((tab) => {
|
|
6034
|
+
const isDisabled = disabledTabs.has(tab.id);
|
|
6035
|
+
const tooltip = getDisabledTabTooltip(tab.id, summary);
|
|
6036
|
+
const tabElement = /* @__PURE__ */ jsx37(
|
|
6037
|
+
Tab,
|
|
6038
|
+
{
|
|
6039
|
+
"aria-controls": `panel-${tab.id}`,
|
|
6040
|
+
disabled: isDisabled,
|
|
6041
|
+
id: `tab-${tab.id}`,
|
|
6042
|
+
label: tab.label,
|
|
6043
|
+
onClick: () => handleTabClick(tab.id),
|
|
6044
|
+
selected: currentTab === tab.id
|
|
6045
|
+
}
|
|
6046
|
+
);
|
|
6047
|
+
return isDisabled && tooltip ? /* @__PURE__ */ jsx37(
|
|
6048
|
+
Tooltip9,
|
|
6049
|
+
{
|
|
6050
|
+
content: /* @__PURE__ */ jsx37(Box15, { padding: 2, style: { maxWidth: 280 }, children: tooltip }),
|
|
6051
|
+
placement: "bottom",
|
|
6052
|
+
portal: true,
|
|
6053
|
+
children: /* @__PURE__ */ jsx37("span", { style: { display: "inline-block" }, children: tabElement })
|
|
6054
|
+
},
|
|
6055
|
+
tab.id
|
|
6056
|
+
) : /* @__PURE__ */ jsx37("span", { children: tabElement }, tab.id);
|
|
6057
|
+
}) }),
|
|
5735
6058
|
currentTab === "overview" && /* @__PURE__ */ jsx37(
|
|
5736
6059
|
TabPanel,
|
|
5737
6060
|
{
|
|
@@ -5789,11 +6112,37 @@ function ReportDetail({
|
|
|
5789
6112
|
)
|
|
5790
6113
|
] }) });
|
|
5791
6114
|
}
|
|
6115
|
+
var inlineCodeStyle = {
|
|
6116
|
+
background: "var(--card-code-bg-color, rgba(255,255,255,0.06))",
|
|
6117
|
+
borderRadius: 3,
|
|
6118
|
+
fontFamily: "var(--card-code-font-family, monospace)",
|
|
6119
|
+
fontSize: "0.9em",
|
|
6120
|
+
padding: "0.15em 0.35em"
|
|
6121
|
+
};
|
|
6122
|
+
function getDisabledTabTooltip(tabId, summary) {
|
|
6123
|
+
if (!summary) return null;
|
|
6124
|
+
switch (tabId) {
|
|
6125
|
+
case "diagnostics":
|
|
6126
|
+
return /* @__PURE__ */ jsx37(Text32, { muted: true, size: 1, children: "No diagnostic data available. Diagnostics require low-scoring judgments or gap analysis recommendations." });
|
|
6127
|
+
case "activity":
|
|
6128
|
+
return summary.evaluationMode === "baseline" ? /* @__PURE__ */ jsxs32(Text32, { muted: true, size: 1, children: [
|
|
6129
|
+
"Not available for baseline-only evaluations. Run with",
|
|
6130
|
+
" ",
|
|
6131
|
+
/* @__PURE__ */ jsx37("code", { style: inlineCodeStyle, children: "--mode full" }),
|
|
6132
|
+
" or",
|
|
6133
|
+
" ",
|
|
6134
|
+
/* @__PURE__ */ jsx37("code", { style: inlineCodeStyle, children: "--mode agentic" }),
|
|
6135
|
+
" to capture agent browsing behavior."
|
|
6136
|
+
] }) : /* @__PURE__ */ jsx37(Text32, { muted: true, size: 1, children: "No agent activity data was recorded for this evaluation." });
|
|
6137
|
+
default:
|
|
6138
|
+
return null;
|
|
6139
|
+
}
|
|
6140
|
+
}
|
|
5792
6141
|
|
|
5793
6142
|
// src/components/ScoreTimeline.tsx
|
|
5794
6143
|
import { Card as Card23, Flex as Flex25, Select as Select2, Stack as Stack24, Text as Text33 } from "@sanity/ui";
|
|
5795
|
-
import { useCallback as
|
|
5796
|
-
import { useClient as
|
|
6144
|
+
import { useCallback as useCallback14, useEffect as useEffect9, useMemo as useMemo8, useState as useState11 } from "react";
|
|
6145
|
+
import { useClient as useClient8 } from "sanity";
|
|
5797
6146
|
import { jsx as jsx38, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
5798
6147
|
var CHART_HEIGHT = 220;
|
|
5799
6148
|
var CHART_WIDTH = 800;
|
|
@@ -5828,11 +6177,11 @@ function scoreForPoint(point, area) {
|
|
|
5828
6177
|
return match?.totalScore ?? null;
|
|
5829
6178
|
}
|
|
5830
6179
|
function ScoreTimeline({ mode = null, source = null }) {
|
|
5831
|
-
const client =
|
|
5832
|
-
const [dataPoints, setDataPoints] =
|
|
5833
|
-
const [loading, setLoading] =
|
|
5834
|
-
const [rangeDays, setRangeDays] =
|
|
5835
|
-
const [selectedArea, setSelectedArea] =
|
|
6180
|
+
const client = useClient8({ apiVersion: API_VERSION });
|
|
6181
|
+
const [dataPoints, setDataPoints] = useState11([]);
|
|
6182
|
+
const [loading, setLoading] = useState11(true);
|
|
6183
|
+
const [rangeDays, setRangeDays] = useState11(30);
|
|
6184
|
+
const [selectedArea, setSelectedArea] = useState11(null);
|
|
5836
6185
|
const areaNames = useMemo8(() => {
|
|
5837
6186
|
const names = /* @__PURE__ */ new Set();
|
|
5838
6187
|
for (const dp of dataPoints) {
|
|
@@ -5842,7 +6191,7 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
5842
6191
|
}
|
|
5843
6192
|
return Array.from(names).sort();
|
|
5844
6193
|
}, [dataPoints]);
|
|
5845
|
-
const fetchData =
|
|
6194
|
+
const fetchData = useCallback14(async () => {
|
|
5846
6195
|
setLoading(true);
|
|
5847
6196
|
try {
|
|
5848
6197
|
const startDate = rangeDays ? daysAgo(rangeDays) : "1970-01-01T00:00:00Z";
|
|
@@ -5857,7 +6206,7 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
5857
6206
|
setLoading(false);
|
|
5858
6207
|
}
|
|
5859
6208
|
}, [client, mode, rangeDays, source]);
|
|
5860
|
-
|
|
6209
|
+
useEffect9(() => {
|
|
5861
6210
|
void fetchData();
|
|
5862
6211
|
}, [fetchData]);
|
|
5863
6212
|
const chartPoints = useMemo8(() => {
|
|
@@ -5878,14 +6227,14 @@ function ScoreTimeline({ mode = null, source = null }) {
|
|
|
5878
6227
|
if (chartPoints.length === 0) return 0;
|
|
5879
6228
|
return chartPoints.reduce((sum, p) => sum + p.score, 0) / chartPoints.length;
|
|
5880
6229
|
}, [chartPoints]);
|
|
5881
|
-
const handleRangeChange =
|
|
6230
|
+
const handleRangeChange = useCallback14(
|
|
5882
6231
|
(e) => {
|
|
5883
6232
|
const val = e.currentTarget.value;
|
|
5884
6233
|
setRangeDays(val === "all" ? null : Number(val));
|
|
5885
6234
|
},
|
|
5886
6235
|
[]
|
|
5887
6236
|
);
|
|
5888
|
-
const handleAreaChange =
|
|
6237
|
+
const handleAreaChange = useCallback14(
|
|
5889
6238
|
(e) => {
|
|
5890
6239
|
const val = e.currentTarget.value;
|
|
5891
6240
|
setSelectedArea(val || null);
|
|
@@ -6018,13 +6367,13 @@ var VIEW_PARAM_MAP = {
|
|
|
6018
6367
|
timeline: "timeline"
|
|
6019
6368
|
};
|
|
6020
6369
|
function Dashboard() {
|
|
6021
|
-
const client =
|
|
6370
|
+
const client = useClient9({ apiVersion: API_VERSION });
|
|
6022
6371
|
const router = useRouter();
|
|
6023
6372
|
const routerState = router.state;
|
|
6024
6373
|
const reportId = routerState.reportId ?? null;
|
|
6025
6374
|
const isDetail = reportId !== null;
|
|
6026
6375
|
const activeTab = isDetail ? "latest" : VIEW_PARAM_MAP[routerState.view ?? ""] ?? "latest";
|
|
6027
|
-
const navigateToTab =
|
|
6376
|
+
const navigateToTab = useCallback15(
|
|
6028
6377
|
(tab) => {
|
|
6029
6378
|
if (tab === "latest") {
|
|
6030
6379
|
router.navigate({});
|
|
@@ -6034,13 +6383,13 @@ function Dashboard() {
|
|
|
6034
6383
|
},
|
|
6035
6384
|
[router]
|
|
6036
6385
|
);
|
|
6037
|
-
const handleSelectReport =
|
|
6386
|
+
const handleSelectReport = useCallback15(
|
|
6038
6387
|
(id) => {
|
|
6039
6388
|
router.navigate({ reportId: id });
|
|
6040
6389
|
},
|
|
6041
6390
|
[router]
|
|
6042
6391
|
);
|
|
6043
|
-
const handleTabChange =
|
|
6392
|
+
const handleTabChange = useCallback15(
|
|
6044
6393
|
(tab) => {
|
|
6045
6394
|
if (!routerState.reportId) return;
|
|
6046
6395
|
if (tab) {
|
|
@@ -6051,14 +6400,14 @@ function Dashboard() {
|
|
|
6051
6400
|
},
|
|
6052
6401
|
[router, routerState.reportId]
|
|
6053
6402
|
);
|
|
6054
|
-
const handleBack =
|
|
6403
|
+
const handleBack = useCallback15(() => {
|
|
6055
6404
|
router.navigate({});
|
|
6056
6405
|
}, [router]);
|
|
6057
|
-
const [source, setSource] =
|
|
6058
|
-
const [mode, setMode] =
|
|
6059
|
-
const [sources, setSources] =
|
|
6060
|
-
const [modes, setModes] =
|
|
6061
|
-
|
|
6406
|
+
const [source, setSource] = useState12(null);
|
|
6407
|
+
const [mode, setMode] = useState12(null);
|
|
6408
|
+
const [sources, setSources] = useState12([]);
|
|
6409
|
+
const [modes, setModes] = useState12([]);
|
|
6410
|
+
useEffect10(() => {
|
|
6062
6411
|
client.fetch(distinctSourcesQuery).then((data) => setSources(data ?? [])).catch(() => setSources([]));
|
|
6063
6412
|
client.fetch(distinctModesQuery).then((data) => setModes(data ?? [])).catch(() => setModes([]));
|
|
6064
6413
|
}, [client]);
|
|
@@ -6166,23 +6515,23 @@ function ailfTool(options = {}) {
|
|
|
6166
6515
|
|
|
6167
6516
|
// src/actions/RunEvaluationAction.tsx
|
|
6168
6517
|
import { BarChartIcon as BarChartIcon2 } from "@sanity/icons";
|
|
6169
|
-
import { useToast } from "@sanity/ui";
|
|
6170
|
-
import { useCallback as
|
|
6518
|
+
import { useToast as useToast2 } from "@sanity/ui";
|
|
6519
|
+
import { useCallback as useCallback16, useEffect as useEffect11, useRef as useRef5, useState as useState13 } from "react";
|
|
6171
6520
|
import {
|
|
6172
6521
|
getReleaseIdFromReleaseDocumentId as getReleaseIdFromReleaseDocumentId4,
|
|
6173
|
-
useClient as
|
|
6174
|
-
useCurrentUser,
|
|
6175
|
-
useDataset,
|
|
6176
|
-
useProjectId
|
|
6522
|
+
useClient as useClient10,
|
|
6523
|
+
useCurrentUser as useCurrentUser2,
|
|
6524
|
+
useDataset as useDataset2,
|
|
6525
|
+
useProjectId as useProjectId2
|
|
6177
6526
|
} from "sanity";
|
|
6178
6527
|
var API_VERSION2 = "2026-03-11";
|
|
6179
|
-
var
|
|
6180
|
-
var
|
|
6181
|
-
var
|
|
6182
|
-
var
|
|
6528
|
+
var EVAL_REQUEST_TYPE2 = "ailf.evalRequest";
|
|
6529
|
+
var POLL_INTERVAL_MS2 = 3e4;
|
|
6530
|
+
var MAX_POLL_MS2 = 30 * 60 * 1e3;
|
|
6531
|
+
var EVAL_REQUEST_STATUS_QUERY2 = (
|
|
6183
6532
|
/* groq */
|
|
6184
6533
|
`
|
|
6185
|
-
*[_type == "${
|
|
6534
|
+
*[_type == "${EVAL_REQUEST_TYPE2}" && _id == $id][0] {
|
|
6186
6535
|
status,
|
|
6187
6536
|
error,
|
|
6188
6537
|
reportId
|
|
@@ -6193,15 +6542,15 @@ function createRunEvaluationAction(options = {}) {
|
|
|
6193
6542
|
const { mode = "baseline" } = options;
|
|
6194
6543
|
const RunEvaluationAction = (props) => {
|
|
6195
6544
|
const { release } = props;
|
|
6196
|
-
const client =
|
|
6197
|
-
const dataset =
|
|
6198
|
-
const projectId =
|
|
6199
|
-
const currentUser =
|
|
6200
|
-
const toast =
|
|
6201
|
-
const [state, setState] =
|
|
6202
|
-
const requestedAtRef =
|
|
6545
|
+
const client = useClient10({ apiVersion: API_VERSION2 });
|
|
6546
|
+
const dataset = useDataset2();
|
|
6547
|
+
const projectId = useProjectId2();
|
|
6548
|
+
const currentUser = useCurrentUser2();
|
|
6549
|
+
const toast = useToast2();
|
|
6550
|
+
const [state, setState] = useState13({ status: "loading" });
|
|
6551
|
+
const requestedAtRef = useRef5(null);
|
|
6203
6552
|
const perspectiveId = getReleaseIdFromReleaseDocumentId4(release._id);
|
|
6204
|
-
|
|
6553
|
+
useEffect11(() => {
|
|
6205
6554
|
let cancelled = false;
|
|
6206
6555
|
client.fetch(contentImpactQuery, buildReportQueryParams(perspectiveId)).then((results) => {
|
|
6207
6556
|
if (cancelled) return;
|
|
@@ -6224,14 +6573,14 @@ function createRunEvaluationAction(options = {}) {
|
|
|
6224
6573
|
cancelled = true;
|
|
6225
6574
|
};
|
|
6226
6575
|
}, [client, perspectiveId]);
|
|
6227
|
-
|
|
6576
|
+
useEffect11(() => {
|
|
6228
6577
|
if (state.status !== "requested" && state.status !== "polling") return;
|
|
6229
6578
|
const { requestId, startedAt } = state;
|
|
6230
6579
|
if (state.status === "requested") {
|
|
6231
6580
|
setState({ requestId, startedAt, status: "polling" });
|
|
6232
6581
|
}
|
|
6233
6582
|
const interval = setInterval(async () => {
|
|
6234
|
-
if (Date.now() - startedAt >
|
|
6583
|
+
if (Date.now() - startedAt > MAX_POLL_MS2) {
|
|
6235
6584
|
clearInterval(interval);
|
|
6236
6585
|
setState({
|
|
6237
6586
|
message: "Evaluation is still running. Check the AI Literacy dashboard for results.",
|
|
@@ -6240,7 +6589,7 @@ function createRunEvaluationAction(options = {}) {
|
|
|
6240
6589
|
return;
|
|
6241
6590
|
}
|
|
6242
6591
|
try {
|
|
6243
|
-
const reqStatus = await client.fetch(
|
|
6592
|
+
const reqStatus = await client.fetch(EVAL_REQUEST_STATUS_QUERY2, {
|
|
6244
6593
|
id: requestId
|
|
6245
6594
|
});
|
|
6246
6595
|
if (reqStatus?.status === "failed") {
|
|
@@ -6271,10 +6620,10 @@ function createRunEvaluationAction(options = {}) {
|
|
|
6271
6620
|
}
|
|
6272
6621
|
} catch {
|
|
6273
6622
|
}
|
|
6274
|
-
},
|
|
6623
|
+
}, POLL_INTERVAL_MS2);
|
|
6275
6624
|
return () => clearInterval(interval);
|
|
6276
6625
|
}, [client, perspectiveId, state]);
|
|
6277
|
-
|
|
6626
|
+
useEffect11(() => {
|
|
6278
6627
|
if (state.status !== "error") return;
|
|
6279
6628
|
const timer = setTimeout(() => {
|
|
6280
6629
|
client.fetch(contentImpactQuery, buildReportQueryParams(perspectiveId)).then((results) => {
|
|
@@ -6294,13 +6643,13 @@ function createRunEvaluationAction(options = {}) {
|
|
|
6294
6643
|
}, 15e3);
|
|
6295
6644
|
return () => clearTimeout(timer);
|
|
6296
6645
|
}, [client, perspectiveId, state]);
|
|
6297
|
-
const handleRequest =
|
|
6646
|
+
const handleRequest = useCallback16(async () => {
|
|
6298
6647
|
const releaseTitle = release.metadata?.title ?? perspectiveId ?? "release";
|
|
6299
|
-
const tag = `release-${
|
|
6648
|
+
const tag = `release-${slugify2(releaseTitle)}-${dateStamp2()}`;
|
|
6300
6649
|
const now = Date.now();
|
|
6301
6650
|
try {
|
|
6302
6651
|
const doc = await client.create({
|
|
6303
|
-
_type:
|
|
6652
|
+
_type: EVAL_REQUEST_TYPE2,
|
|
6304
6653
|
dataset,
|
|
6305
6654
|
mode,
|
|
6306
6655
|
perspective: perspectiveId,
|
|
@@ -6340,15 +6689,15 @@ function createRunEvaluationAction(options = {}) {
|
|
|
6340
6689
|
return {
|
|
6341
6690
|
disabled: state.status === "loading" || state.status === "requested" || state.status === "polling",
|
|
6342
6691
|
icon: BarChartIcon2,
|
|
6343
|
-
label:
|
|
6692
|
+
label: getLabel2(state),
|
|
6344
6693
|
onHandle: handleRequest,
|
|
6345
|
-
title:
|
|
6694
|
+
title: getTitle2(state, perspectiveId)
|
|
6346
6695
|
};
|
|
6347
6696
|
};
|
|
6348
6697
|
RunEvaluationAction.displayName = "RunEvaluationAction";
|
|
6349
6698
|
return RunEvaluationAction;
|
|
6350
6699
|
}
|
|
6351
|
-
function
|
|
6700
|
+
function getLabel2(state) {
|
|
6352
6701
|
switch (state.status) {
|
|
6353
6702
|
case "loading":
|
|
6354
6703
|
return "AI Eval";
|
|
@@ -6366,7 +6715,7 @@ function getLabel(state) {
|
|
|
6366
6715
|
return "Eval Failed";
|
|
6367
6716
|
}
|
|
6368
6717
|
}
|
|
6369
|
-
function
|
|
6718
|
+
function getTitle2(state, perspectiveId) {
|
|
6370
6719
|
switch (state.status) {
|
|
6371
6720
|
case "loading":
|
|
6372
6721
|
return "Checking for existing evaluation results\u2026";
|
|
@@ -6394,10 +6743,10 @@ function buildReportQueryParams(perspectiveId) {
|
|
|
6394
6743
|
source: null
|
|
6395
6744
|
};
|
|
6396
6745
|
}
|
|
6397
|
-
function
|
|
6746
|
+
function slugify2(s) {
|
|
6398
6747
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
|
|
6399
6748
|
}
|
|
6400
|
-
function
|
|
6749
|
+
function dateStamp2() {
|
|
6401
6750
|
const d = /* @__PURE__ */ new Date();
|
|
6402
6751
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
6403
6752
|
}
|
|
@@ -6408,7 +6757,7 @@ var ailfPlugin = definePlugin({
|
|
|
6408
6757
|
document: {
|
|
6409
6758
|
actions: (prev, context) => {
|
|
6410
6759
|
if (context.schemaType === "ailf.task") {
|
|
6411
|
-
return [...prev, GraduateToNativeAction];
|
|
6760
|
+
return [...prev, GraduateToNativeAction, RunTaskEvaluationAction];
|
|
6412
6761
|
}
|
|
6413
6762
|
return prev;
|
|
6414
6763
|
}
|
|
@@ -6432,6 +6781,7 @@ export {
|
|
|
6432
6781
|
GraduateToNativeAction,
|
|
6433
6782
|
MirrorBanner,
|
|
6434
6783
|
ReleasePicker,
|
|
6784
|
+
RunTaskEvaluationAction,
|
|
6435
6785
|
SyncStatusBadge,
|
|
6436
6786
|
ailfPlugin,
|
|
6437
6787
|
ailfTool,
|