inspect-ai 0.3.80__py3-none-any.whl → 0.3.82__py3-none-any.whl
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.
- inspect_ai/_cli/eval.py +35 -2
- inspect_ai/_cli/util.py +44 -1
- inspect_ai/_display/core/config.py +1 -1
- inspect_ai/_display/core/display.py +13 -4
- inspect_ai/_display/core/results.py +1 -1
- inspect_ai/_display/textual/widgets/task_detail.py +5 -4
- inspect_ai/_eval/eval.py +38 -1
- inspect_ai/_eval/evalset.py +5 -0
- inspect_ai/_eval/run.py +5 -2
- inspect_ai/_eval/task/log.py +53 -6
- inspect_ai/_eval/task/run.py +51 -10
- inspect_ai/_util/constants.py +2 -0
- inspect_ai/_util/file.py +17 -1
- inspect_ai/_util/json.py +36 -1
- inspect_ai/_view/server.py +113 -1
- inspect_ai/_view/www/App.css +1 -1
- inspect_ai/_view/www/dist/assets/index.css +518 -296
- inspect_ai/_view/www/dist/assets/index.js +38803 -36307
- inspect_ai/_view/www/eslint.config.mjs +1 -1
- inspect_ai/_view/www/log-schema.json +13 -0
- inspect_ai/_view/www/node_modules/flatted/python/flatted.py +149 -0
- inspect_ai/_view/www/package.json +8 -2
- inspect_ai/_view/www/src/App.tsx +151 -855
- inspect_ai/_view/www/src/api/api-browser.ts +176 -5
- inspect_ai/_view/www/src/api/api-vscode.ts +75 -1
- inspect_ai/_view/www/src/api/client-api.ts +66 -10
- inspect_ai/_view/www/src/api/jsonrpc.ts +2 -0
- inspect_ai/_view/www/src/api/types.ts +107 -2
- inspect_ai/_view/www/src/appearance/icons.ts +1 -0
- inspect_ai/_view/www/src/components/AsciinemaPlayer.tsx +3 -3
- inspect_ai/_view/www/src/components/DownloadPanel.tsx +2 -2
- inspect_ai/_view/www/src/components/ExpandablePanel.tsx +56 -61
- inspect_ai/_view/www/src/components/FindBand.tsx +17 -9
- inspect_ai/_view/www/src/components/HumanBaselineView.tsx +1 -1
- inspect_ai/_view/www/src/components/JsonPanel.tsx +14 -24
- inspect_ai/_view/www/src/components/LargeModal.tsx +2 -35
- inspect_ai/_view/www/src/components/LightboxCarousel.tsx +27 -11
- inspect_ai/_view/www/src/components/LiveVirtualList.module.css +11 -0
- inspect_ai/_view/www/src/components/LiveVirtualList.tsx +177 -0
- inspect_ai/_view/www/src/components/MarkdownDiv.tsx +3 -3
- inspect_ai/_view/www/src/components/MessageBand.tsx +14 -9
- inspect_ai/_view/www/src/components/MorePopOver.tsx +3 -3
- inspect_ai/_view/www/src/components/NavPills.tsx +20 -8
- inspect_ai/_view/www/src/components/NoContentsPanel.module.css +12 -0
- inspect_ai/_view/www/src/components/NoContentsPanel.tsx +20 -0
- inspect_ai/_view/www/src/components/ProgressBar.module.css +5 -4
- inspect_ai/_view/www/src/components/ProgressBar.tsx +3 -2
- inspect_ai/_view/www/src/components/PulsingDots.module.css +81 -0
- inspect_ai/_view/www/src/components/PulsingDots.tsx +45 -0
- inspect_ai/_view/www/src/components/TabSet.tsx +4 -37
- inspect_ai/_view/www/src/components/ToolButton.tsx +3 -4
- inspect_ai/_view/www/src/index.tsx +26 -94
- inspect_ai/_view/www/src/logfile/remoteLogFile.ts +9 -1
- inspect_ai/_view/www/src/logfile/remoteZipFile.ts +30 -4
- inspect_ai/_view/www/src/metadata/RenderedContent.tsx +4 -6
- inspect_ai/_view/www/src/plan/ScorerDetailView.tsx +1 -1
- inspect_ai/_view/www/src/samples/InlineSampleDisplay.module.css +9 -1
- inspect_ai/_view/www/src/samples/InlineSampleDisplay.tsx +67 -28
- inspect_ai/_view/www/src/samples/SampleDialog.tsx +51 -22
- inspect_ai/_view/www/src/samples/SampleDisplay.module.css +4 -0
- inspect_ai/_view/www/src/samples/SampleDisplay.tsx +144 -90
- inspect_ai/_view/www/src/samples/SampleSummaryView.module.css +4 -0
- inspect_ai/_view/www/src/samples/SampleSummaryView.tsx +82 -35
- inspect_ai/_view/www/src/samples/SamplesTools.tsx +23 -30
- inspect_ai/_view/www/src/samples/chat/ChatMessage.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatMessageRenderer.tsx +1 -1
- inspect_ai/_view/www/src/samples/chat/ChatViewVirtualList.tsx +45 -53
- inspect_ai/_view/www/src/samples/chat/MessageContent.tsx +4 -1
- inspect_ai/_view/www/src/samples/chat/MessageContents.tsx +3 -0
- inspect_ai/_view/www/src/samples/chat/messages.ts +34 -0
- inspect_ai/_view/www/src/samples/chat/tools/ToolCallView.module.css +3 -0
- inspect_ai/_view/www/src/samples/chat/tools/ToolCallView.tsx +10 -1
- inspect_ai/_view/www/src/samples/chat/tools/ToolInput.tsx +22 -46
- inspect_ai/_view/www/src/samples/descriptor/samplesDescriptor.tsx +25 -17
- inspect_ai/_view/www/src/samples/descriptor/score/ObjectScoreDescriptor.tsx +2 -1
- inspect_ai/_view/www/src/samples/descriptor/types.ts +6 -5
- inspect_ai/_view/www/src/samples/list/SampleFooter.module.css +21 -3
- inspect_ai/_view/www/src/samples/list/SampleFooter.tsx +20 -1
- inspect_ai/_view/www/src/samples/list/SampleList.tsx +105 -85
- inspect_ai/_view/www/src/samples/list/SampleRow.module.css +6 -0
- inspect_ai/_view/www/src/samples/list/SampleRow.tsx +27 -14
- inspect_ai/_view/www/src/samples/sample-tools/SelectScorer.tsx +29 -18
- inspect_ai/_view/www/src/samples/sample-tools/SortFilter.tsx +28 -28
- inspect_ai/_view/www/src/samples/sample-tools/sample-filter/SampleFilter.tsx +19 -9
- inspect_ai/_view/www/src/samples/sampleDataAdapter.ts +33 -0
- inspect_ai/_view/www/src/samples/sampleLimit.ts +2 -2
- inspect_ai/_view/www/src/samples/scores/SampleScoreView.tsx +7 -9
- inspect_ai/_view/www/src/samples/scores/SampleScores.tsx +7 -11
- inspect_ai/_view/www/src/samples/transcript/ErrorEventView.tsx +0 -13
- inspect_ai/_view/www/src/samples/transcript/InfoEventView.tsx +0 -13
- inspect_ai/_view/www/src/samples/transcript/InputEventView.tsx +0 -13
- inspect_ai/_view/www/src/samples/transcript/ModelEventView.module.css +4 -0
- inspect_ai/_view/www/src/samples/transcript/ModelEventView.tsx +10 -24
- inspect_ai/_view/www/src/samples/transcript/SampleInitEventView.tsx +0 -13
- inspect_ai/_view/www/src/samples/transcript/SampleLimitEventView.tsx +4 -22
- inspect_ai/_view/www/src/samples/transcript/SandboxEventView.tsx +15 -24
- inspect_ai/_view/www/src/samples/transcript/ScoreEventView.tsx +0 -13
- inspect_ai/_view/www/src/samples/transcript/StepEventView.tsx +6 -28
- inspect_ai/_view/www/src/samples/transcript/SubtaskEventView.tsx +24 -34
- inspect_ai/_view/www/src/samples/transcript/ToolEventView.module.css +4 -0
- inspect_ai/_view/www/src/samples/transcript/ToolEventView.tsx +8 -13
- inspect_ai/_view/www/src/samples/transcript/TranscriptView.tsx +197 -338
- inspect_ai/_view/www/src/samples/transcript/TranscriptVirtualListComponent.module.css +16 -0
- inspect_ai/_view/www/src/samples/transcript/TranscriptVirtualListComponent.tsx +44 -0
- inspect_ai/_view/www/src/samples/transcript/event/EventNav.tsx +7 -4
- inspect_ai/_view/www/src/samples/transcript/event/EventPanel.tsx +52 -58
- inspect_ai/_view/www/src/samples/transcript/event/EventProgressPanel.module.css +23 -0
- inspect_ai/_view/www/src/samples/transcript/event/EventProgressPanel.tsx +27 -0
- inspect_ai/_view/www/src/samples/transcript/state/StateEventRenderers.tsx +30 -1
- inspect_ai/_view/www/src/samples/transcript/state/StateEventView.tsx +102 -72
- inspect_ai/_view/www/src/scoring/utils.ts +87 -0
- inspect_ai/_view/www/src/state/appSlice.ts +244 -0
- inspect_ai/_view/www/src/state/hooks.ts +397 -0
- inspect_ai/_view/www/src/state/logPolling.ts +196 -0
- inspect_ai/_view/www/src/state/logSlice.ts +214 -0
- inspect_ai/_view/www/src/state/logsPolling.ts +118 -0
- inspect_ai/_view/www/src/state/logsSlice.ts +181 -0
- inspect_ai/_view/www/src/state/samplePolling.ts +311 -0
- inspect_ai/_view/www/src/state/sampleSlice.ts +127 -0
- inspect_ai/_view/www/src/state/sampleUtils.ts +21 -0
- inspect_ai/_view/www/src/state/scrolling.ts +206 -0
- inspect_ai/_view/www/src/state/store.ts +168 -0
- inspect_ai/_view/www/src/state/store_filter.ts +84 -0
- inspect_ai/_view/www/src/state/utils.ts +23 -0
- inspect_ai/_view/www/src/storage/index.ts +26 -0
- inspect_ai/_view/www/src/types/log.d.ts +2 -0
- inspect_ai/_view/www/src/types.ts +94 -32
- inspect_ai/_view/www/src/utils/attachments.ts +58 -23
- inspect_ai/_view/www/src/utils/logger.ts +52 -0
- inspect_ai/_view/www/src/utils/polling.ts +100 -0
- inspect_ai/_view/www/src/utils/react.ts +30 -0
- inspect_ai/_view/www/src/utils/vscode.ts +1 -1
- inspect_ai/_view/www/src/workspace/WorkSpace.tsx +181 -216
- inspect_ai/_view/www/src/workspace/WorkSpaceView.tsx +11 -53
- inspect_ai/_view/www/src/workspace/navbar/Navbar.tsx +8 -18
- inspect_ai/_view/www/src/workspace/navbar/PrimaryBar.module.css +1 -0
- inspect_ai/_view/www/src/workspace/navbar/PrimaryBar.tsx +40 -22
- inspect_ai/_view/www/src/workspace/navbar/ResultsPanel.module.css +0 -1
- inspect_ai/_view/www/src/workspace/navbar/ResultsPanel.tsx +98 -39
- inspect_ai/_view/www/src/workspace/navbar/RunningStatusPanel.module.css +32 -0
- inspect_ai/_view/www/src/workspace/navbar/RunningStatusPanel.tsx +32 -0
- inspect_ai/_view/www/src/workspace/navbar/SecondaryBar.tsx +11 -13
- inspect_ai/_view/www/src/workspace/navbar/StatusPanel.tsx +6 -2
- inspect_ai/_view/www/src/workspace/sidebar/LogDirectoryTitleView.tsx +4 -4
- inspect_ai/_view/www/src/workspace/sidebar/Sidebar.tsx +28 -13
- inspect_ai/_view/www/src/workspace/tabs/InfoTab.tsx +5 -10
- inspect_ai/_view/www/src/workspace/tabs/JsonTab.tsx +4 -4
- inspect_ai/_view/www/src/workspace/tabs/RunningNoSamples.module.css +22 -0
- inspect_ai/_view/www/src/workspace/tabs/RunningNoSamples.tsx +19 -0
- inspect_ai/_view/www/src/workspace/tabs/SamplesTab.tsx +110 -115
- inspect_ai/_view/www/src/workspace/tabs/grouping.ts +37 -5
- inspect_ai/_view/www/src/workspace/tabs/types.ts +4 -0
- inspect_ai/_view/www/src/workspace/types.ts +4 -3
- inspect_ai/_view/www/src/workspace/utils.ts +4 -4
- inspect_ai/_view/www/vite.config.js +6 -0
- inspect_ai/_view/www/yarn.lock +370 -354
- inspect_ai/log/_condense.py +26 -0
- inspect_ai/log/_log.py +6 -3
- inspect_ai/log/_recorders/buffer/__init__.py +14 -0
- inspect_ai/log/_recorders/buffer/buffer.py +30 -0
- inspect_ai/log/_recorders/buffer/database.py +685 -0
- inspect_ai/log/_recorders/buffer/filestore.py +259 -0
- inspect_ai/log/_recorders/buffer/types.py +84 -0
- inspect_ai/log/_recorders/eval.py +2 -11
- inspect_ai/log/_recorders/types.py +30 -0
- inspect_ai/log/_transcript.py +27 -1
- inspect_ai/model/_call_tools.py +1 -0
- inspect_ai/model/_generate_config.py +2 -2
- inspect_ai/model/_model.py +1 -0
- inspect_ai/tool/_tool_support_helpers.py +4 -4
- inspect_ai/tool/_tools/_web_browser/_web_browser.py +3 -1
- inspect_ai/util/_subtask.py +1 -0
- {inspect_ai-0.3.80.dist-info → inspect_ai-0.3.82.dist-info}/METADATA +2 -2
- {inspect_ai-0.3.80.dist-info → inspect_ai-0.3.82.dist-info}/RECORD +178 -138
- inspect_ai/_view/www/src/samples/transcript/SampleTranscript.tsx +0 -22
- {inspect_ai-0.3.80.dist-info → inspect_ai-0.3.82.dist-info}/WHEEL +0 -0
- {inspect_ai-0.3.80.dist-info → inspect_ai-0.3.82.dist-info}/entry_points.txt +0 -0
- {inspect_ai-0.3.80.dist-info → inspect_ai-0.3.82.dist-info}/licenses/LICENSE +0 -0
- {inspect_ai-0.3.80.dist-info → inspect_ai-0.3.82.dist-info}/top_level.txt +0 -0
@@ -1,10 +1,10 @@
|
|
1
1
|
import clsx from "clsx";
|
2
2
|
import { FC } from "react";
|
3
|
-
import { SampleSummary } from "../../api/types";
|
4
3
|
import { ExpandablePanel } from "../../components/ExpandablePanel";
|
5
4
|
import { LabeledValue } from "../../components/LabeledValue";
|
6
5
|
import { EvalDescriptor } from "../../samples/descriptor/types";
|
7
6
|
import { scoreFilterItems } from "../../samples/sample-tools/filters";
|
7
|
+
import { useEvalDescriptor } from "../../state/hooks";
|
8
8
|
import {
|
9
9
|
EvalDataset,
|
10
10
|
EvalPlan,
|
@@ -20,9 +20,8 @@ interface SecondaryBarProps {
|
|
20
20
|
evalPlan?: EvalPlan;
|
21
21
|
evalResults?: EvalResults;
|
22
22
|
evalStats?: EvalStats;
|
23
|
-
evalDescriptor?: EvalDescriptor;
|
24
|
-
samples?: SampleSummary[];
|
25
23
|
status?: string;
|
24
|
+
sampleCount?: number;
|
26
25
|
}
|
27
26
|
|
28
27
|
/**
|
@@ -33,10 +32,10 @@ export const SecondaryBar: FC<SecondaryBarProps> = ({
|
|
33
32
|
evalPlan,
|
34
33
|
evalResults,
|
35
34
|
evalStats,
|
36
|
-
samples,
|
37
|
-
evalDescriptor,
|
38
35
|
status,
|
36
|
+
sampleCount,
|
39
37
|
}) => {
|
38
|
+
const evalDescriptor = useEvalDescriptor();
|
40
39
|
if (!evalSpec || status !== "success") {
|
41
40
|
return null;
|
42
41
|
}
|
@@ -56,11 +55,11 @@ export const SecondaryBar: FC<SecondaryBarProps> = ({
|
|
56
55
|
<LabeledValue
|
57
56
|
key="sb-dataset"
|
58
57
|
label="Dataset"
|
59
|
-
className={(styles.staticCol, "text-size-small")}
|
58
|
+
className={clsx(styles.staticCol, "text-size-small")}
|
60
59
|
>
|
61
60
|
<DatasetSummary
|
62
61
|
dataset={evalSpec.dataset}
|
63
|
-
|
62
|
+
sampleCount={sampleCount}
|
64
63
|
epochs={epochs}
|
65
64
|
/>
|
66
65
|
</LabeledValue>
|
@@ -122,6 +121,7 @@ export const SecondaryBar: FC<SecondaryBarProps> = ({
|
|
122
121
|
|
123
122
|
return (
|
124
123
|
<ExpandablePanel
|
124
|
+
id={"secondary-nav-bar"}
|
125
125
|
className={clsx(styles.container, "text-size-small")}
|
126
126
|
collapse={true}
|
127
127
|
lines={4}
|
@@ -146,16 +146,16 @@ export const SecondaryBar: FC<SecondaryBarProps> = ({
|
|
146
146
|
|
147
147
|
interface DatasetSummaryProps {
|
148
148
|
dataset?: EvalDataset;
|
149
|
-
samples?: SampleSummary[];
|
150
149
|
epochs: number;
|
150
|
+
sampleCount?: number;
|
151
151
|
}
|
152
152
|
|
153
153
|
/**
|
154
154
|
* A component that displays the dataset
|
155
155
|
*/
|
156
156
|
const DatasetSummary: FC<DatasetSummaryProps> = ({
|
157
|
+
sampleCount,
|
157
158
|
dataset,
|
158
|
-
samples,
|
159
159
|
epochs,
|
160
160
|
}) => {
|
161
161
|
if (!dataset) {
|
@@ -164,15 +164,13 @@ const DatasetSummary: FC<DatasetSummaryProps> = ({
|
|
164
164
|
|
165
165
|
return (
|
166
166
|
<div>
|
167
|
-
{
|
168
|
-
? formatDataset(samples.length, epochs, dataset.name)
|
169
|
-
: ""}
|
167
|
+
{sampleCount ? formatDataset(sampleCount, epochs, dataset.name) : ""}
|
170
168
|
</div>
|
171
169
|
);
|
172
170
|
};
|
173
171
|
|
174
172
|
interface ScoreSummaryProps {
|
175
|
-
evalDescriptor?: EvalDescriptor;
|
173
|
+
evalDescriptor?: EvalDescriptor | null;
|
176
174
|
}
|
177
175
|
|
178
176
|
/**
|
@@ -37,13 +37,17 @@ export const RunningPanel: FC<StatusProps> = ({ sampleCount }) => {
|
|
37
37
|
);
|
38
38
|
};
|
39
39
|
|
40
|
-
interface StatusPanelProps {
|
40
|
+
export interface StatusPanelProps {
|
41
41
|
icon: string;
|
42
42
|
status: string;
|
43
43
|
sampleCount: number;
|
44
44
|
}
|
45
45
|
|
46
|
-
const StatusPanel: FC<StatusPanelProps> = ({
|
46
|
+
export const StatusPanel: FC<StatusPanelProps> = ({
|
47
|
+
icon,
|
48
|
+
status,
|
49
|
+
sampleCount,
|
50
|
+
}) => {
|
47
51
|
return (
|
48
52
|
<div className={styles.statusPanel}>
|
49
53
|
<i className={clsx(icon, styles.statusIcon)} style={{}} />
|
@@ -1,16 +1,16 @@
|
|
1
1
|
import clsx from "clsx";
|
2
2
|
import { FC } from "react";
|
3
|
+
import { useStore } from "../../state/store";
|
3
4
|
import styles from "./LogDirectoryTitleView.module.css";
|
4
5
|
|
5
6
|
interface LogDirectoryTitleViewProps {
|
6
7
|
log_dir?: string;
|
7
|
-
offcanvas: boolean;
|
8
8
|
}
|
9
9
|
|
10
10
|
export const LogDirectoryTitleView: FC<LogDirectoryTitleViewProps> = ({
|
11
11
|
log_dir,
|
12
|
-
offcanvas,
|
13
12
|
}) => {
|
13
|
+
const offCanvas = useStore((state) => state.app.offcanvas);
|
14
14
|
if (log_dir) {
|
15
15
|
const displayDir = prettyDir(log_dir);
|
16
16
|
return (
|
@@ -28,14 +28,14 @@ export const LogDirectoryTitleView: FC<LogDirectoryTitleViewProps> = ({
|
|
28
28
|
title={displayDir}
|
29
29
|
className={clsx("text-size-base", styles.dirname)}
|
30
30
|
>
|
31
|
-
{
|
31
|
+
{offCanvas ? displayDir : ""}
|
32
32
|
</span>
|
33
33
|
</div>
|
34
34
|
);
|
35
35
|
} else {
|
36
36
|
return (
|
37
37
|
<span className={clsx("text-size-title")}>
|
38
|
-
{
|
38
|
+
{offCanvas ? "Log History" : ""}
|
39
39
|
</span>
|
40
40
|
);
|
41
41
|
}
|
@@ -1,9 +1,11 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
-
import { FC } from "react";
|
2
|
+
import { FC, MouseEvent, useCallback, useRef } from "react";
|
3
3
|
import { Fragment } from "react/jsx-runtime";
|
4
4
|
import { EvalLogHeader, LogFiles } from "../../api/types";
|
5
5
|
import { ApplicationIcons } from "../../appearance/icons";
|
6
6
|
import { ProgressBar } from "../../components/ProgressBar";
|
7
|
+
import { useStatefulScrollPosition } from "../../state/scrolling";
|
8
|
+
import { useStore } from "../../state/store";
|
7
9
|
import { LogDirectoryTitleView } from "./LogDirectoryTitleView";
|
8
10
|
import styles from "./Sidebar.module.css";
|
9
11
|
import { SidebarLogEntry } from "./SidebarLogEntry";
|
@@ -11,8 +13,6 @@ import { SidebarLogEntry } from "./SidebarLogEntry";
|
|
11
13
|
interface SidebarProps {
|
12
14
|
logs: LogFiles;
|
13
15
|
logHeaders: Record<string, EvalLogHeader>;
|
14
|
-
offcanvas: boolean;
|
15
|
-
setOffcanvas: (offcanvas: boolean) => void;
|
16
16
|
loading: boolean;
|
17
17
|
selectedIndex: number;
|
18
18
|
onSelectedIndexChanged: (index: number) => void;
|
@@ -21,29 +21,40 @@ interface SidebarProps {
|
|
21
21
|
export const Sidebar: FC<SidebarProps> = ({
|
22
22
|
logs,
|
23
23
|
logHeaders,
|
24
|
-
offcanvas,
|
25
|
-
setOffcanvas,
|
26
24
|
loading,
|
27
25
|
selectedIndex,
|
28
26
|
onSelectedIndexChanged,
|
29
27
|
}) => {
|
30
|
-
const
|
31
|
-
|
32
|
-
|
28
|
+
const setOffCanvas = useStore((state) => state.appActions.setOffcanvas);
|
29
|
+
const offCanvas = useStore((state) => state.app.offcanvas);
|
30
|
+
const handleToggle = useCallback(() => {
|
31
|
+
setOffCanvas(!offCanvas);
|
32
|
+
}, [offCanvas, setOffCanvas]);
|
33
|
+
|
34
|
+
const sidebarContentsRef = useRef(null);
|
35
|
+
useStatefulScrollPosition(sidebarContentsRef, "sidebar-contents", 1000);
|
36
|
+
|
37
|
+
const handleClick = useCallback(
|
38
|
+
(e: MouseEvent<HTMLLIElement>) => {
|
39
|
+
const index = Number((e.currentTarget as HTMLLIElement).dataset.index);
|
40
|
+
onSelectedIndexChanged(index);
|
41
|
+
},
|
42
|
+
[onSelectedIndexChanged],
|
43
|
+
);
|
33
44
|
|
34
45
|
return (
|
35
46
|
<Fragment>
|
36
47
|
{/* Optional backdrop for small screens, appears only when offcanvas is open */}
|
37
|
-
{
|
48
|
+
{offCanvas && <div className={styles.backdrop} onClick={handleToggle} />}
|
38
49
|
|
39
50
|
<div
|
40
51
|
className={clsx(
|
41
52
|
styles.sidebar,
|
42
|
-
|
53
|
+
offCanvas ? styles.sidebarOpen : styles.sidebarClosed,
|
43
54
|
)}
|
44
55
|
>
|
45
56
|
<div className={styles.header}>
|
46
|
-
<LogDirectoryTitleView log_dir={logs.log_dir}
|
57
|
+
<LogDirectoryTitleView log_dir={logs.log_dir} />
|
47
58
|
<button
|
48
59
|
onClick={handleToggle}
|
49
60
|
className={clsx("btn", styles.toggle)}
|
@@ -58,7 +69,10 @@ export const Sidebar: FC<SidebarProps> = ({
|
|
58
69
|
<ProgressBar animating={loading} />
|
59
70
|
</div>
|
60
71
|
|
61
|
-
<ul
|
72
|
+
<ul
|
73
|
+
ref={sidebarContentsRef}
|
74
|
+
className={clsx("list-group", styles.list)}
|
75
|
+
>
|
62
76
|
{logs.files.map((file, index) => {
|
63
77
|
const logHeader = logHeaders[file.name];
|
64
78
|
return (
|
@@ -70,7 +84,8 @@ export const Sidebar: FC<SidebarProps> = ({
|
|
70
84
|
styles.item,
|
71
85
|
selectedIndex === index ? styles.active : undefined,
|
72
86
|
)}
|
73
|
-
|
87
|
+
data-index={index}
|
88
|
+
onClick={handleClick}
|
74
89
|
>
|
75
90
|
<SidebarLogEntry
|
76
91
|
logHeader={logHeader}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { FC
|
1
|
+
import { FC } from "react";
|
2
2
|
import { SampleSummary } from "../../api/types";
|
3
3
|
import { MessageBand } from "../../components/MessageBand";
|
4
4
|
import { PlanCard } from "../../plan/PlanCard";
|
@@ -20,6 +20,7 @@ interface PlanTabProps {
|
|
20
20
|
samples?: SampleSummary[];
|
21
21
|
evalStatus?: "started" | "error" | "cancelled" | "success";
|
22
22
|
evalError?: EvalError;
|
23
|
+
sampleCount?: number;
|
23
24
|
}
|
24
25
|
|
25
26
|
export const InfoTab: FC<PlanTabProps> = ({
|
@@ -27,17 +28,12 @@ export const InfoTab: FC<PlanTabProps> = ({
|
|
27
28
|
evalPlan,
|
28
29
|
evalResults,
|
29
30
|
evalStats,
|
30
|
-
samples,
|
31
31
|
evalStatus,
|
32
32
|
evalError,
|
33
|
+
sampleCount,
|
33
34
|
}) => {
|
34
|
-
const [hidden, setHidden] = useState(false);
|
35
|
-
useEffect(() => {
|
36
|
-
setHidden(false);
|
37
|
-
}, [evalSpec, evalPlan, evalResults, evalStats, samples]);
|
38
|
-
|
39
35
|
const showWarning =
|
40
|
-
|
36
|
+
sampleCount === 0 &&
|
41
37
|
evalStatus === "success" &&
|
42
38
|
evalSpec?.dataset.samples &&
|
43
39
|
evalSpec.dataset.samples > 0;
|
@@ -46,9 +42,8 @@ export const InfoTab: FC<PlanTabProps> = ({
|
|
46
42
|
<div style={{ width: "100%" }}>
|
47
43
|
{showWarning ? (
|
48
44
|
<MessageBand
|
45
|
+
id="sample-too-large"
|
49
46
|
message="Unable to display samples (this evaluation log may be too large)."
|
50
|
-
hidden={hidden}
|
51
|
-
setHidden={setHidden}
|
52
47
|
type="warning"
|
53
48
|
/>
|
54
49
|
) : (
|
@@ -1,16 +1,15 @@
|
|
1
1
|
import { filename } from "../../utils/path";
|
2
2
|
|
3
3
|
import { FC } from "react";
|
4
|
-
import { Capabilities } from "../../api/types";
|
5
4
|
import { DownloadPanel } from "../../components/DownloadPanel";
|
6
5
|
import { JSONPanel } from "../../components/JsonPanel";
|
6
|
+
import { useStore } from "../../state/store";
|
7
7
|
import styles from "./JsonTab.module.css";
|
8
8
|
|
9
9
|
const kJsonMaxSize = 10000000;
|
10
10
|
|
11
11
|
interface JsonTabProps {
|
12
12
|
logFile?: string;
|
13
|
-
capabilities: Capabilities;
|
14
13
|
selected: boolean;
|
15
14
|
json: string;
|
16
15
|
}
|
@@ -18,8 +17,9 @@ interface JsonTabProps {
|
|
18
17
|
/**
|
19
18
|
* Renders JSON tab
|
20
19
|
*/
|
21
|
-
export const JsonTab: FC<JsonTabProps> = ({ logFile,
|
22
|
-
|
20
|
+
export const JsonTab: FC<JsonTabProps> = ({ logFile, json }) => {
|
21
|
+
const downloadFiles = useStore((state) => state.capabilities.downloadFiles);
|
22
|
+
if (logFile && json.length > kJsonMaxSize && downloadFiles) {
|
23
23
|
// This JSON file is so large we can't really productively render it
|
24
24
|
// we should instead just provide a DL link
|
25
25
|
const file = `${filename(logFile)}.json`;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
.panel {
|
2
|
+
width: 100%;
|
3
|
+
display: flex;
|
4
|
+
justify-content: center;
|
5
|
+
}
|
6
|
+
|
7
|
+
.container {
|
8
|
+
margin-top: 3em;
|
9
|
+
display: grid;
|
10
|
+
grid-template-columns: max-content max-content;
|
11
|
+
column-gap: 0.3em;
|
12
|
+
}
|
13
|
+
|
14
|
+
.spinner {
|
15
|
+
border-width: 1px;
|
16
|
+
height: 15px;
|
17
|
+
width: 15px;
|
18
|
+
}
|
19
|
+
|
20
|
+
.text {
|
21
|
+
margin-top: -2px;
|
22
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import clsx from "clsx";
|
2
|
+
import { FC } from "react";
|
3
|
+
|
4
|
+
import styles from "./RunningNoSamples.module.css";
|
5
|
+
|
6
|
+
interface RunningNoSamplesProps {}
|
7
|
+
|
8
|
+
export const RunningNoSamples: FC<RunningNoSamplesProps> = () => {
|
9
|
+
return (
|
10
|
+
<div className={clsx(styles.panel)}>
|
11
|
+
<div className={clsx(styles.container, "text-size-smaller")}>
|
12
|
+
<div className={clsx(styles.spinner, "spinner-border")} role="status">
|
13
|
+
<span className={clsx("visually-hidden")}>starting...</span>
|
14
|
+
</div>
|
15
|
+
<div className={clsx(styles.text)}>starting....</div>
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
);
|
19
|
+
};
|
@@ -1,135 +1,136 @@
|
|
1
1
|
import {
|
2
2
|
FC,
|
3
3
|
Fragment,
|
4
|
-
RefObject,
|
5
4
|
useCallback,
|
6
5
|
useEffect,
|
6
|
+
useMemo,
|
7
7
|
useRef,
|
8
8
|
useState,
|
9
9
|
} from "react";
|
10
10
|
import { VirtuosoHandle } from "react-virtuoso";
|
11
|
-
import {
|
12
|
-
import {
|
13
|
-
import {
|
14
|
-
import {
|
15
|
-
import {
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
import { NoContentsPanel } from "../../components/NoContentsPanel.tsx";
|
12
|
+
import { InlineSampleDisplay } from "../../samples/InlineSampleDisplay.tsx";
|
13
|
+
import { SampleDialog } from "../../samples/SampleDialog.tsx";
|
14
|
+
import { SampleList } from "../../samples/list/SampleList.tsx";
|
15
|
+
import {
|
16
|
+
useFilteredSamples,
|
17
|
+
useGroupBy,
|
18
|
+
useGroupByOrder,
|
19
|
+
useSampleDescriptor,
|
20
|
+
useScore,
|
21
|
+
useTotalSampleCount,
|
22
|
+
} from "../../state/hooks.ts";
|
23
|
+
import { useStore } from "../../state/store.ts";
|
24
|
+
import { RunningNoSamples } from "./RunningNoSamples.tsx";
|
19
25
|
import { getSampleProcessor } from "./grouping.ts";
|
20
26
|
import { ListItem } from "./types.ts";
|
21
27
|
|
22
28
|
interface SamplesTabProps {
|
23
|
-
// Optional props
|
24
|
-
sample?: EvalSample;
|
25
|
-
samples?: SampleSummary[];
|
26
|
-
sampleDescriptor?: SamplesDescriptor;
|
27
|
-
sampleError?: Error;
|
28
|
-
|
29
29
|
// Required props
|
30
|
-
|
31
|
-
groupBy: "epoch" | "sample" | "none";
|
32
|
-
groupByOrder: "asc" | "desc";
|
33
|
-
sampleStatus: string;
|
34
|
-
selectedSampleIndex: number;
|
35
|
-
setSelectedSampleIndex: (index: number) => void;
|
36
|
-
showingSampleDialog: boolean;
|
37
|
-
setShowingSampleDialog: (showing: boolean) => void;
|
38
|
-
selectedSampleTab?: string;
|
39
|
-
setSelectedSampleTab: (tab: string) => void;
|
40
|
-
epoch: string;
|
41
|
-
filter: ScoreFilter;
|
42
|
-
sampleScrollPositionRef: RefObject<number>;
|
43
|
-
setSampleScrollPosition: (position: number) => void;
|
44
|
-
sampleTabScrollRef: RefObject<HTMLDivElement | null>;
|
30
|
+
running: boolean;
|
45
31
|
}
|
46
32
|
|
47
|
-
export const SamplesTab: FC<SamplesTabProps> = ({
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
sampleTabScrollRef,
|
65
|
-
}) => {
|
33
|
+
export const SamplesTab: FC<SamplesTabProps> = ({ running }) => {
|
34
|
+
const selectSample = useStore((state) => state.logActions.selectSample);
|
35
|
+
const selectedSampleIndex = useStore(
|
36
|
+
(state) => state.log.selectedSampleIndex,
|
37
|
+
);
|
38
|
+
|
39
|
+
const sampleSummaries = useFilteredSamples();
|
40
|
+
const selectedLogSummary = useStore((state) => state.log.selectedLogSummary);
|
41
|
+
const totalSampleCount = useTotalSampleCount();
|
42
|
+
|
43
|
+
const samplesDescriptor = useSampleDescriptor();
|
44
|
+
const groupBy = useGroupBy();
|
45
|
+
const groupByOrder = useGroupByOrder();
|
46
|
+
const currentScore = useScore();
|
47
|
+
|
48
|
+
const selectedSample = useStore((state) => state.sample.selectedSample);
|
49
|
+
|
66
50
|
const [items, setItems] = useState<ListItem[]>([]);
|
67
51
|
const [sampleItems, setSampleItems] = useState<ListItem[]>([]);
|
68
52
|
|
69
53
|
const sampleListHandle = useRef<VirtuosoHandle | null>(null);
|
70
54
|
const sampleDialogRef = useRef<HTMLDivElement>(null);
|
71
55
|
|
56
|
+
const selectedSampleTab = useStore((state) => state.app.tabs.sample);
|
57
|
+
const setSelectedSampleTab = useStore(
|
58
|
+
(state) => state.appActions.setSampleTab,
|
59
|
+
);
|
60
|
+
const showingSampleDialog = useStore((state) => state.app.dialogs.sample);
|
61
|
+
const setShowingSampleDialog = useStore(
|
62
|
+
(state) => state.appActions.setShowingSampleDialog,
|
63
|
+
);
|
64
|
+
|
72
65
|
// Shows the sample dialog
|
73
66
|
const showSample = useCallback(
|
74
67
|
(index: number) => {
|
75
|
-
|
68
|
+
selectSample(index);
|
76
69
|
setShowingSampleDialog(true);
|
77
70
|
},
|
78
|
-
[
|
71
|
+
[selectSample, setShowingSampleDialog],
|
79
72
|
);
|
80
73
|
|
74
|
+
// Keep the selected item scrolled into view
|
75
|
+
useEffect(() => {
|
76
|
+
setTimeout(() => {
|
77
|
+
if (sampleListHandle.current) {
|
78
|
+
sampleListHandle.current.scrollIntoView({ index: selectedSampleIndex });
|
79
|
+
}
|
80
|
+
}, 0);
|
81
|
+
}, [selectedSampleIndex]);
|
82
|
+
|
83
|
+
// Focus the dialog when it is shown
|
81
84
|
useEffect(() => {
|
82
85
|
if (showingSampleDialog) {
|
83
86
|
setTimeout(() => {
|
84
87
|
sampleDialogRef.current?.focus();
|
85
88
|
}, 0);
|
86
|
-
} else {
|
87
|
-
setTimeout(() => {
|
88
|
-
if (sampleListHandle.current) {
|
89
|
-
sampleListHandle.current.scrollToIndex(0);
|
90
|
-
}
|
91
|
-
}, 0);
|
92
89
|
}
|
93
90
|
}, [showingSampleDialog]);
|
94
91
|
|
92
|
+
const sampleProcessor = useMemo(() => {
|
93
|
+
if (!samplesDescriptor) return undefined;
|
94
|
+
|
95
|
+
return getSampleProcessor(
|
96
|
+
sampleSummaries || [],
|
97
|
+
selectedLogSummary?.eval?.config?.epochs || 1,
|
98
|
+
groupBy,
|
99
|
+
groupByOrder,
|
100
|
+
samplesDescriptor,
|
101
|
+
currentScore,
|
102
|
+
);
|
103
|
+
}, [
|
104
|
+
samplesDescriptor,
|
105
|
+
sampleSummaries,
|
106
|
+
selectedLogSummary?.eval?.config?.epochs,
|
107
|
+
groupBy,
|
108
|
+
groupByOrder,
|
109
|
+
currentScore,
|
110
|
+
]);
|
111
|
+
|
95
112
|
useEffect(() => {
|
96
|
-
const
|
97
|
-
? getSampleProcessor(
|
98
|
-
samples || [],
|
99
|
-
groupBy,
|
100
|
-
groupByOrder,
|
101
|
-
sampleDescriptor,
|
102
|
-
)
|
103
|
-
: undefined;
|
104
|
-
|
105
|
-
// Process the samples into the proper data structure
|
106
|
-
const items = samples?.flatMap((sample, index) => {
|
113
|
+
const resolvedSamples = sampleSummaries?.flatMap((sample, index) => {
|
107
114
|
const results: ListItem[] = [];
|
108
|
-
const previousSample =
|
115
|
+
const previousSample =
|
116
|
+
index !== 0 ? sampleSummaries[index - 1] : undefined;
|
109
117
|
const items = sampleProcessor
|
110
118
|
? sampleProcessor(sample, index, previousSample)
|
111
119
|
: [];
|
120
|
+
|
112
121
|
results.push(...items);
|
113
122
|
return results;
|
114
123
|
});
|
115
124
|
|
116
|
-
setItems(
|
125
|
+
setItems(resolvedSamples || []);
|
117
126
|
setSampleItems(
|
118
|
-
|
119
|
-
?
|
127
|
+
resolvedSamples
|
128
|
+
? resolvedSamples.filter((item) => {
|
120
129
|
return item.type === "sample";
|
121
130
|
})
|
122
131
|
: [],
|
123
132
|
);
|
124
|
-
}, [
|
125
|
-
|
126
|
-
const nextSampleIndex = useCallback(() => {
|
127
|
-
if (selectedSampleIndex < sampleItems.length - 1) {
|
128
|
-
return selectedSampleIndex + 1;
|
129
|
-
} else {
|
130
|
-
return -1;
|
131
|
-
}
|
132
|
-
}, [selectedSampleIndex, sampleItems.length]);
|
133
|
+
}, [sampleSummaries, sampleProcessor]);
|
133
134
|
|
134
135
|
const previousSampleIndex = useCallback(() => {
|
135
136
|
return selectedSampleIndex > 0 ? selectedSampleIndex - 1 : -1;
|
@@ -137,68 +138,62 @@ export const SamplesTab: FC<SamplesTabProps> = ({
|
|
137
138
|
|
138
139
|
// Manage the next / previous state the selected sample
|
139
140
|
const nextSample = useCallback(() => {
|
140
|
-
const next =
|
141
|
-
if (
|
142
|
-
|
141
|
+
const next = Math.min(selectedSampleIndex + 1, sampleItems.length - 1);
|
142
|
+
if (next > -1) {
|
143
|
+
selectSample(next);
|
143
144
|
}
|
144
|
-
}, [
|
145
|
+
}, [selectedSampleIndex, sampleItems, selectSample]);
|
145
146
|
|
146
147
|
const previousSample = useCallback(() => {
|
147
148
|
const prev = previousSampleIndex();
|
148
|
-
if (
|
149
|
-
|
149
|
+
if (prev > -1) {
|
150
|
+
selectSample(prev);
|
150
151
|
}
|
151
|
-
}, [previousSampleIndex,
|
152
|
+
}, [previousSampleIndex, selectSample]);
|
152
153
|
|
153
154
|
const title =
|
154
155
|
selectedSampleIndex > -1 && sampleItems.length > selectedSampleIndex
|
155
156
|
? sampleItems[selectedSampleIndex].label
|
156
157
|
: "";
|
157
158
|
|
158
|
-
if (
|
159
|
-
|
159
|
+
if (totalSampleCount === 0) {
|
160
|
+
if (running) {
|
161
|
+
return <RunningNoSamples />;
|
162
|
+
} else {
|
163
|
+
return <NoContentsPanel text="No samples" />;
|
164
|
+
}
|
160
165
|
} else {
|
161
166
|
return (
|
162
167
|
<Fragment>
|
163
|
-
{
|
168
|
+
{samplesDescriptor && totalSampleCount === 1 ? (
|
164
169
|
<InlineSampleDisplay
|
165
170
|
id="sample-display"
|
166
|
-
sample={sample}
|
167
|
-
sampleStatus={sampleStatus}
|
168
|
-
sampleError={sampleError}
|
169
|
-
sampleDescriptor={sampleDescriptor}
|
170
171
|
selectedTab={selectedSampleTab}
|
171
172
|
setSelectedTab={setSelectedSampleTab}
|
172
|
-
scrollRef={sampleTabScrollRef}
|
173
173
|
/>
|
174
174
|
) : undefined}
|
175
|
-
{
|
175
|
+
{samplesDescriptor && totalSampleCount > 1 ? (
|
176
176
|
<SampleList
|
177
177
|
listHandle={sampleListHandle}
|
178
178
|
items={items}
|
179
|
-
|
180
|
-
selectedIndex={selectedSampleIndex}
|
179
|
+
running={running}
|
181
180
|
nextSample={nextSample}
|
182
181
|
prevSample={previousSample}
|
183
182
|
showSample={showSample}
|
184
183
|
/>
|
185
184
|
) : undefined}
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
prevSample={previousSample}
|
199
|
-
sampleScrollPositionRef={sampleScrollPositionRef}
|
200
|
-
setSampleScrollPosition={setSampleScrollPosition}
|
201
|
-
/>
|
185
|
+
{showingSampleDialog ? (
|
186
|
+
<SampleDialog
|
187
|
+
id={String(selectedSample?.id || "")}
|
188
|
+
title={title}
|
189
|
+
showingSampleDialog={showingSampleDialog}
|
190
|
+
setShowingSampleDialog={setShowingSampleDialog}
|
191
|
+
selectedTab={selectedSampleTab}
|
192
|
+
setSelectedTab={setSelectedSampleTab}
|
193
|
+
nextSample={nextSample}
|
194
|
+
prevSample={previousSample}
|
195
|
+
/>
|
196
|
+
) : undefined}
|
202
197
|
</Fragment>
|
203
198
|
);
|
204
199
|
}
|