@sanity/ailf-studio 1.7.0 → 1.7.1
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/index.d.ts +9 -0
- package/dist/index.js +141 -43
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -521,6 +521,15 @@ interface JudgmentData {
|
|
|
521
521
|
/** Docs the task expected the model to use */
|
|
522
522
|
canonicalDocs?: DocumentRef[];
|
|
523
523
|
dimension: string;
|
|
524
|
+
/**
|
|
525
|
+
* `graderJudgments` manifest entry key = `formatEntryKey({mode, task,
|
|
526
|
+
* model, grader})` from the slim-report publisher. Present on reports
|
|
527
|
+
* published under W0051+. Consumed by `useArtifactDetail` in
|
|
528
|
+
* `JudgmentDetailDrawer` to hydrate the full reasoning from GCS, and by
|
|
529
|
+
* `JudgmentList` to drive hover-prefetch and the list row's data hook.
|
|
530
|
+
* Optional so legacy reports (pre-W0051) still type-check.
|
|
531
|
+
*/
|
|
532
|
+
id?: string;
|
|
524
533
|
modelId: string;
|
|
525
534
|
/** True when the model failed to produce output (empty response, API error, refusal) */
|
|
526
535
|
outputFailure?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -3280,7 +3280,7 @@ import {
|
|
|
3280
3280
|
TabPanel as TabPanel3,
|
|
3281
3281
|
Text as Text46
|
|
3282
3282
|
} from "@sanity/ui";
|
|
3283
|
-
import { useCallback as useCallback36 } from "react";
|
|
3283
|
+
import { useCallback as useCallback36, useEffect as useEffect15 } from "react";
|
|
3284
3284
|
import { useRouter as useRouter3 } from "sanity/router";
|
|
3285
3285
|
|
|
3286
3286
|
// src/lib/help-context.ts
|
|
@@ -7157,6 +7157,7 @@ function cacheKey({ runId, type, key }) {
|
|
|
7157
7157
|
}
|
|
7158
7158
|
var hydratedEntries = /* @__PURE__ */ new Map();
|
|
7159
7159
|
var inFlight = /* @__PURE__ */ new Map();
|
|
7160
|
+
var knownNotFound = /* @__PURE__ */ new Set();
|
|
7160
7161
|
var subscribers = /* @__PURE__ */ new Map();
|
|
7161
7162
|
function getCached(k) {
|
|
7162
7163
|
const hit = hydratedEntries.get(cacheKey(k));
|
|
@@ -7190,6 +7191,12 @@ function recordInFlight(k, start) {
|
|
|
7190
7191
|
inFlight.set(composite, p);
|
|
7191
7192
|
return p;
|
|
7192
7193
|
}
|
|
7194
|
+
function markNotFound(k) {
|
|
7195
|
+
knownNotFound.add(cacheKey(k));
|
|
7196
|
+
}
|
|
7197
|
+
function isKnownNotFound(k) {
|
|
7198
|
+
return knownNotFound.has(cacheKey(k));
|
|
7199
|
+
}
|
|
7193
7200
|
function notify(composite) {
|
|
7194
7201
|
const set2 = subscribers.get(composite);
|
|
7195
7202
|
if (!set2) return;
|
|
@@ -7197,6 +7204,14 @@ function notify(composite) {
|
|
|
7197
7204
|
}
|
|
7198
7205
|
|
|
7199
7206
|
// src/lib/artifact-fetch.ts
|
|
7207
|
+
var ArtifactHttpError = class extends Error {
|
|
7208
|
+
status;
|
|
7209
|
+
constructor(message, status) {
|
|
7210
|
+
super(message);
|
|
7211
|
+
this.name = "ArtifactHttpError";
|
|
7212
|
+
this.status = status;
|
|
7213
|
+
}
|
|
7214
|
+
};
|
|
7200
7215
|
function buildSigningUrl(runId, type, entryKey) {
|
|
7201
7216
|
const base = `${ARTIFACT_API_BASE_URL}/runs/${encodeURIComponent(runId)}/artifacts/${encodeURIComponent(type)}`;
|
|
7202
7217
|
return entryKey === void 0 ? base : `${base}/${encodeURIComponent(entryKey)}`;
|
|
@@ -7205,8 +7220,9 @@ async function signAndFetchJson(signingUrl) {
|
|
|
7205
7220
|
const signed = await exchangeSigningUrl(signingUrl);
|
|
7206
7221
|
const res = await fetch(signed, { credentials: "omit" });
|
|
7207
7222
|
if (!res.ok) {
|
|
7208
|
-
throw new
|
|
7209
|
-
`GCS artifact fetch failed: ${res.status} ${res.statusText}
|
|
7223
|
+
throw new ArtifactHttpError(
|
|
7224
|
+
`GCS artifact fetch failed: ${res.status} ${res.statusText}`,
|
|
7225
|
+
res.status
|
|
7210
7226
|
);
|
|
7211
7227
|
}
|
|
7212
7228
|
return await res.json();
|
|
@@ -7215,8 +7231,9 @@ async function signAndFetchNdjson(signingUrl) {
|
|
|
7215
7231
|
const signed = await exchangeSigningUrl(signingUrl);
|
|
7216
7232
|
const res = await fetch(signed, { credentials: "omit" });
|
|
7217
7233
|
if (!res.ok) {
|
|
7218
|
-
throw new
|
|
7219
|
-
`GCS artifact fetch failed: ${res.status} ${res.statusText}
|
|
7234
|
+
throw new ArtifactHttpError(
|
|
7235
|
+
`GCS artifact fetch failed: ${res.status} ${res.statusText}`,
|
|
7236
|
+
res.status
|
|
7220
7237
|
);
|
|
7221
7238
|
}
|
|
7222
7239
|
const body = await res.text();
|
|
@@ -7271,8 +7288,9 @@ async function exchangeSigningUrl(signingUrl) {
|
|
|
7271
7288
|
});
|
|
7272
7289
|
if (!res.ok) {
|
|
7273
7290
|
const body = await res.text().catch(() => "");
|
|
7274
|
-
throw new
|
|
7275
|
-
`Artifact signing failed: ${res.status} ${res.statusText}${body ? ` \u2014 ${body.slice(0, 200)}` : ""}
|
|
7291
|
+
throw new ArtifactHttpError(
|
|
7292
|
+
`Artifact signing failed: ${res.status} ${res.statusText}${body ? ` \u2014 ${body.slice(0, 200)}` : ""}`,
|
|
7293
|
+
res.status
|
|
7276
7294
|
);
|
|
7277
7295
|
}
|
|
7278
7296
|
const envelope = await res.json();
|
|
@@ -7304,21 +7322,29 @@ function useArtifactDetail(type, key) {
|
|
|
7304
7322
|
}, [runId, type, key]);
|
|
7305
7323
|
const request = useCallback16(async () => {
|
|
7306
7324
|
if (!runId || !ref || !key) return;
|
|
7307
|
-
const
|
|
7325
|
+
const cacheId = { runId, type, key };
|
|
7326
|
+
if (isKnownNotFound(cacheId)) {
|
|
7327
|
+
setStatus("error");
|
|
7328
|
+
return;
|
|
7329
|
+
}
|
|
7330
|
+
const hit = getCached(cacheId);
|
|
7308
7331
|
if (hit !== null) {
|
|
7309
7332
|
setStatus("ready");
|
|
7310
7333
|
return;
|
|
7311
7334
|
}
|
|
7312
7335
|
setStatus("loading");
|
|
7313
7336
|
try {
|
|
7314
|
-
await recordInFlight(
|
|
7337
|
+
await recordInFlight(cacheId, async () => {
|
|
7315
7338
|
const url = buildSigningUrl(runId, type, key);
|
|
7316
7339
|
const body = NDJSON_TYPES.has(type) ? await signAndFetchNdjson(url) : await signAndFetchJson(url);
|
|
7317
|
-
setCached(
|
|
7340
|
+
setCached(cacheId, body);
|
|
7318
7341
|
return body;
|
|
7319
7342
|
});
|
|
7320
7343
|
setStatus("ready");
|
|
7321
|
-
} catch {
|
|
7344
|
+
} catch (err) {
|
|
7345
|
+
if (err instanceof ArtifactHttpError && err.status === 404) {
|
|
7346
|
+
markNotFound(cacheId);
|
|
7347
|
+
}
|
|
7322
7348
|
setStatus("error");
|
|
7323
7349
|
}
|
|
7324
7350
|
}, [runId, ref, type, key]);
|
|
@@ -7353,33 +7379,73 @@ import { useCallback as useCallback17, useMemo as useMemo7 } from "react";
|
|
|
7353
7379
|
var NDJSON_TYPES2 = /* @__PURE__ */ new Set([
|
|
7354
7380
|
"traces"
|
|
7355
7381
|
]);
|
|
7382
|
+
var HOVER_DEBOUNCE_MS = 200;
|
|
7383
|
+
var MAX_CONCURRENT_PREFETCHES = 4;
|
|
7384
|
+
var pendingHoverTimers = /* @__PURE__ */ new Map();
|
|
7385
|
+
var activePrefetches = 0;
|
|
7386
|
+
var prefetchWaitQueue = [];
|
|
7387
|
+
async function withPrefetchSlot(run) {
|
|
7388
|
+
if (activePrefetches >= MAX_CONCURRENT_PREFETCHES) {
|
|
7389
|
+
await new Promise((resolve) => prefetchWaitQueue.push(resolve));
|
|
7390
|
+
}
|
|
7391
|
+
activePrefetches++;
|
|
7392
|
+
try {
|
|
7393
|
+
return await run();
|
|
7394
|
+
} finally {
|
|
7395
|
+
activePrefetches--;
|
|
7396
|
+
const next = prefetchWaitQueue.shift();
|
|
7397
|
+
if (next) next();
|
|
7398
|
+
}
|
|
7399
|
+
}
|
|
7400
|
+
async function prefetchArtifactCore(args) {
|
|
7401
|
+
const { runId, type, key } = args;
|
|
7402
|
+
if (!runId || !key) return;
|
|
7403
|
+
const cacheId = { runId, type, key };
|
|
7404
|
+
if (isKnownNotFound(cacheId)) return;
|
|
7405
|
+
if (getCached(cacheId) !== null) return;
|
|
7406
|
+
try {
|
|
7407
|
+
await recordInFlight(
|
|
7408
|
+
cacheId,
|
|
7409
|
+
() => withPrefetchSlot(async () => {
|
|
7410
|
+
const url = buildSigningUrl(runId, type, key);
|
|
7411
|
+
const body = NDJSON_TYPES2.has(type) ? await signAndFetchNdjson(url) : await signAndFetchJson(url);
|
|
7412
|
+
setCached(cacheId, body);
|
|
7413
|
+
return body;
|
|
7414
|
+
})
|
|
7415
|
+
);
|
|
7416
|
+
} catch (err) {
|
|
7417
|
+
if (err instanceof ArtifactHttpError && err.status === 404) {
|
|
7418
|
+
markNotFound(cacheId);
|
|
7419
|
+
}
|
|
7420
|
+
}
|
|
7421
|
+
}
|
|
7422
|
+
function scheduleHoverPrefetch(type, run, debounceMs = HOVER_DEBOUNCE_MS) {
|
|
7423
|
+
const existing = pendingHoverTimers.get(type);
|
|
7424
|
+
if (existing) clearTimeout(existing);
|
|
7425
|
+
const timer = setTimeout(() => {
|
|
7426
|
+
pendingHoverTimers.delete(type);
|
|
7427
|
+
run();
|
|
7428
|
+
}, debounceMs);
|
|
7429
|
+
pendingHoverTimers.set(type, timer);
|
|
7430
|
+
}
|
|
7356
7431
|
function useArtifactPrefetch(type) {
|
|
7357
7432
|
const { runId } = useReportArtifactContext();
|
|
7358
7433
|
const ref = useArtifactRef(type);
|
|
7359
7434
|
const prefetch = useCallback17(
|
|
7360
7435
|
async (key) => {
|
|
7361
7436
|
if (!runId || !ref || !key) return;
|
|
7362
|
-
|
|
7363
|
-
if (cached !== null) return;
|
|
7364
|
-
try {
|
|
7365
|
-
await recordInFlight({ runId, type, key }, async () => {
|
|
7366
|
-
const url = buildSigningUrl(runId, type, key);
|
|
7367
|
-
const body = NDJSON_TYPES2.has(type) ? await signAndFetchNdjson(url) : await signAndFetchJson(url);
|
|
7368
|
-
setCached({ runId, type, key }, body);
|
|
7369
|
-
return body;
|
|
7370
|
-
});
|
|
7371
|
-
} catch {
|
|
7372
|
-
}
|
|
7437
|
+
await prefetchArtifactCore({ runId, type, key });
|
|
7373
7438
|
},
|
|
7374
7439
|
[runId, ref, type]
|
|
7375
7440
|
);
|
|
7376
7441
|
const onHover = useCallback17(
|
|
7377
7442
|
(key) => {
|
|
7378
7443
|
return () => {
|
|
7379
|
-
|
|
7444
|
+
if (!runId || !ref || !key) return;
|
|
7445
|
+
scheduleHoverPrefetch(type, () => void prefetch(key));
|
|
7380
7446
|
};
|
|
7381
7447
|
},
|
|
7382
|
-
[prefetch]
|
|
7448
|
+
[runId, ref, type, prefetch]
|
|
7383
7449
|
);
|
|
7384
7450
|
const prefetchWindow = useCallback17(
|
|
7385
7451
|
async (keys, centerIndex, radius = 5) => {
|
|
@@ -8194,12 +8260,15 @@ function JudgmentList({
|
|
|
8194
8260
|
}
|
|
8195
8261
|
}, [flatSlugs, activeRowSlug]);
|
|
8196
8262
|
const { close: closeDrawer, open: openDrawer } = useJudgmentDrawer();
|
|
8263
|
+
const { runId: artifactRunId, manifest: artifactManifest } = useReportArtifactContext();
|
|
8197
8264
|
useEffect9(() => {
|
|
8198
8265
|
if (focus && focusedJudgment) {
|
|
8199
8266
|
openDrawer({
|
|
8200
8267
|
artifactCache,
|
|
8201
8268
|
judgment: focusedJudgment,
|
|
8202
|
-
testResult: focusedTestResult
|
|
8269
|
+
testResult: focusedTestResult,
|
|
8270
|
+
runId: artifactRunId,
|
|
8271
|
+
manifest: artifactManifest
|
|
8203
8272
|
});
|
|
8204
8273
|
} else if (!focus) {
|
|
8205
8274
|
closeDrawer();
|
|
@@ -8210,7 +8279,9 @@ function JudgmentList({
|
|
|
8210
8279
|
focusedTestResult,
|
|
8211
8280
|
artifactCache,
|
|
8212
8281
|
openDrawer,
|
|
8213
|
-
closeDrawer
|
|
8282
|
+
closeDrawer,
|
|
8283
|
+
artifactRunId,
|
|
8284
|
+
artifactManifest
|
|
8214
8285
|
]);
|
|
8215
8286
|
const prevFocusRef = useRef6(focus);
|
|
8216
8287
|
useEffect9(() => {
|
|
@@ -8512,14 +8583,18 @@ function JudgmentCard({
|
|
|
8512
8583
|
},
|
|
8513
8584
|
[handleClick]
|
|
8514
8585
|
);
|
|
8586
|
+
const onHoverTestOutputs = useMemo9(
|
|
8587
|
+
() => testOutputsKey ? testOutputsPrefetch.onHover(testOutputsKey) : null,
|
|
8588
|
+
[testOutputsPrefetch, testOutputsKey]
|
|
8589
|
+
);
|
|
8515
8590
|
const handleMouseEnter = useCallback21(() => {
|
|
8516
8591
|
row.handlers.onMouseEnter();
|
|
8517
|
-
|
|
8518
|
-
}, [row.handlers,
|
|
8592
|
+
onHoverTestOutputs?.();
|
|
8593
|
+
}, [row.handlers, onHoverTestOutputs]);
|
|
8519
8594
|
const handleFocusPrefetch = useCallback21(() => {
|
|
8520
8595
|
row.handlers.onFocus();
|
|
8521
|
-
|
|
8522
|
-
}, [row.handlers,
|
|
8596
|
+
onHoverTestOutputs?.();
|
|
8597
|
+
}, [row.handlers, onHoverTestOutputs]);
|
|
8523
8598
|
return /* @__PURE__ */ jsx32(
|
|
8524
8599
|
Box18,
|
|
8525
8600
|
{
|
|
@@ -11222,6 +11297,16 @@ function JudgmentDetailDrawer({
|
|
|
11222
11297
|
const rawTaskName = sep > 0 ? judgment.taskId.substring(sep + 3) : judgment.taskId;
|
|
11223
11298
|
const { name: taskName, variant } = splitVariant(rawTaskName);
|
|
11224
11299
|
const dimLabel = dimensionLabel2(judgment.dimension);
|
|
11300
|
+
const judgmentId = judgment.id ?? "";
|
|
11301
|
+
const [fullJudgment, fullStatus, requestFullJudgment] = useArtifactDetail("graderJudgments", judgmentId);
|
|
11302
|
+
useEffect12(() => {
|
|
11303
|
+
if (!judgmentId) return;
|
|
11304
|
+
if (fullStatus !== "idle") return;
|
|
11305
|
+
void requestFullJudgment();
|
|
11306
|
+
}, [judgmentId, fullStatus, requestFullJudgment]);
|
|
11307
|
+
const fullReason = typeof fullJudgment?.reason === "string" && fullJudgment.reason.length > 0 ? fullJudgment.reason : null;
|
|
11308
|
+
const reasoningText = fullReason ?? judgment.reason;
|
|
11309
|
+
const reasoningIsPreview = fullReason === null && judgmentId.length > 0 && fullStatus !== "error";
|
|
11225
11310
|
useEffect12(() => {
|
|
11226
11311
|
setTab("reasoning");
|
|
11227
11312
|
}, [judgment.taskId, judgment.dimension, judgment.modelId]);
|
|
@@ -11453,10 +11538,11 @@ function JudgmentDetailDrawer({
|
|
|
11453
11538
|
{
|
|
11454
11539
|
copiedLabel: "Reasoning copied",
|
|
11455
11540
|
label: "Copy reasoning",
|
|
11456
|
-
text:
|
|
11541
|
+
text: reasoningText
|
|
11457
11542
|
}
|
|
11458
11543
|
) }),
|
|
11459
|
-
/* @__PURE__ */ jsx59(Markdown, { content:
|
|
11544
|
+
/* @__PURE__ */ jsx59(Markdown, { content: reasoningText }),
|
|
11545
|
+
reasoningIsPreview && /* @__PURE__ */ jsx59(Text44, { muted: true, size: 1, style: { marginTop: 8 }, children: fullStatus === "loading" ? "Loading full reasoning\u2026" : "Showing preview (280 chars). Full reasoning not yet loaded." })
|
|
11460
11546
|
] })
|
|
11461
11547
|
}
|
|
11462
11548
|
),
|
|
@@ -11629,7 +11715,7 @@ function JudgmentDetailDrawerOutlet({
|
|
|
11629
11715
|
flexDirection: "column",
|
|
11630
11716
|
overflow: "hidden"
|
|
11631
11717
|
},
|
|
11632
|
-
children: /* @__PURE__ */ jsx60(
|
|
11718
|
+
children: /* @__PURE__ */ jsx60(ReportArtifactProvider, { runId: active.runId, manifest: active.manifest, children: /* @__PURE__ */ jsx60(
|
|
11633
11719
|
JudgmentDetailDrawer,
|
|
11634
11720
|
{
|
|
11635
11721
|
artifactCache: active.artifactCache,
|
|
@@ -11637,7 +11723,7 @@ function JudgmentDetailDrawerOutlet({
|
|
|
11637
11723
|
onClose,
|
|
11638
11724
|
testResult: active.testResult
|
|
11639
11725
|
}
|
|
11640
|
-
)
|
|
11726
|
+
) })
|
|
11641
11727
|
}
|
|
11642
11728
|
)
|
|
11643
11729
|
]
|
|
@@ -11873,17 +11959,29 @@ var VIEW_PARAM_MAP = {
|
|
|
11873
11959
|
timeline: "timeline"
|
|
11874
11960
|
};
|
|
11875
11961
|
function Dashboard() {
|
|
11962
|
+
return /* @__PURE__ */ jsx62(HelpProvider, { children: /* @__PURE__ */ jsx62(JudgmentDrawerProvider, { children: /* @__PURE__ */ jsx62(DashboardShell, {}) }) });
|
|
11963
|
+
}
|
|
11964
|
+
function DashboardShell() {
|
|
11876
11965
|
const router = useRouter3();
|
|
11966
|
+
const { close: closeDrawer } = useJudgmentDrawer();
|
|
11967
|
+
const routerState = router.state;
|
|
11968
|
+
const reportId = routerState.reportId ?? null;
|
|
11969
|
+
useEffect15(() => {
|
|
11970
|
+
if (!reportId) closeDrawer();
|
|
11971
|
+
}, [reportId, closeDrawer]);
|
|
11877
11972
|
const handleJudgmentDrawerClose = useCallback36(() => {
|
|
11973
|
+
closeDrawer();
|
|
11878
11974
|
const state = { ...router.state };
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
|
|
11975
|
+
if (state.focus) {
|
|
11976
|
+
delete state.focus;
|
|
11977
|
+
router.navigate(state);
|
|
11978
|
+
}
|
|
11979
|
+
}, [closeDrawer, router]);
|
|
11980
|
+
return /* @__PURE__ */ jsxs45(Flex34, { style: { height: "100%" }, children: [
|
|
11883
11981
|
/* @__PURE__ */ jsx62(Box29, { flex: 1, overflow: "auto", children: /* @__PURE__ */ jsx62(DashboardContent, {}) }),
|
|
11884
11982
|
/* @__PURE__ */ jsx62(JudgmentDetailDrawerOutlet, { onClose: handleJudgmentDrawerClose }),
|
|
11885
11983
|
/* @__PURE__ */ jsx62(HelpDrawer, {})
|
|
11886
|
-
] })
|
|
11984
|
+
] });
|
|
11887
11985
|
}
|
|
11888
11986
|
function DashboardContent() {
|
|
11889
11987
|
const router = useRouter3();
|
|
@@ -12016,7 +12114,7 @@ function ailfTool(options = {}) {
|
|
|
12016
12114
|
// src/actions/RunEvaluationAction.tsx
|
|
12017
12115
|
import { BarChartIcon as BarChartIcon2 } from "@sanity/icons";
|
|
12018
12116
|
import { useToast as useToast10 } from "@sanity/ui";
|
|
12019
|
-
import { useCallback as useCallback37, useEffect as
|
|
12117
|
+
import { useCallback as useCallback37, useEffect as useEffect16, useRef as useRef9, useState as useState27 } from "react";
|
|
12020
12118
|
import {
|
|
12021
12119
|
getReleaseIdFromReleaseDocumentId as getReleaseIdFromReleaseDocumentId3,
|
|
12022
12120
|
useClient as useClient12,
|
|
@@ -12050,7 +12148,7 @@ function createRunEvaluationAction(options = {}) {
|
|
|
12050
12148
|
const [state, setState] = useState27({ status: "loading" });
|
|
12051
12149
|
const requestedAtRef = useRef9(null);
|
|
12052
12150
|
const perspectiveId = getReleaseIdFromReleaseDocumentId3(release._id);
|
|
12053
|
-
|
|
12151
|
+
useEffect16(() => {
|
|
12054
12152
|
let cancelled = false;
|
|
12055
12153
|
client.fetch(contentImpactQuery, buildReportQueryParams(perspectiveId)).then((results) => {
|
|
12056
12154
|
if (cancelled) return;
|
|
@@ -12073,7 +12171,7 @@ function createRunEvaluationAction(options = {}) {
|
|
|
12073
12171
|
cancelled = true;
|
|
12074
12172
|
};
|
|
12075
12173
|
}, [client, perspectiveId]);
|
|
12076
|
-
|
|
12174
|
+
useEffect16(() => {
|
|
12077
12175
|
if (state.status !== "requested" && state.status !== "polling") return;
|
|
12078
12176
|
const { requestId, startedAt } = state;
|
|
12079
12177
|
if (state.status === "requested") {
|
|
@@ -12123,7 +12221,7 @@ function createRunEvaluationAction(options = {}) {
|
|
|
12123
12221
|
}, POLL_INTERVAL_MS2);
|
|
12124
12222
|
return () => clearInterval(interval);
|
|
12125
12223
|
}, [client, perspectiveId, state]);
|
|
12126
|
-
|
|
12224
|
+
useEffect16(() => {
|
|
12127
12225
|
if (state.status !== "error") return;
|
|
12128
12226
|
const timer = setTimeout(() => {
|
|
12129
12227
|
client.fetch(contentImpactQuery, buildReportQueryParams(perspectiveId)).then((results) => {
|