inspect-ai 0.3.108__py3-none-any.whl → 0.3.109__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/_eval/task/log.py +1 -1
- inspect_ai/_eval/task/run.py +1 -1
- inspect_ai/_util/dateutil.py +40 -0
- inspect_ai/_view/schema.py +11 -0
- inspect_ai/_view/www/CLAUDE.md +1 -1
- inspect_ai/_view/www/dist/assets/index.css +2068 -1796
- inspect_ai/_view/www/dist/assets/index.js +7951 -3643
- inspect_ai/_view/www/package.json +3 -2
- inspect_ai/_view/www/src/@types/log.d.ts +5 -5
- inspect_ai/_view/www/src/app/App.css +71 -4
- inspect_ai/_view/www/src/app/App.tsx +7 -0
- inspect_ai/_view/www/src/app/appearance/icons.ts +18 -2
- inspect_ai/_view/www/src/app/content/RenderedContent.tsx +7 -9
- inspect_ai/_view/www/src/app/log-list/LogItem.ts +18 -0
- inspect_ai/_view/www/src/app/log-list/LogListFooter.module.css +55 -0
- inspect_ai/_view/www/src/app/log-list/LogListFooter.tsx +67 -0
- inspect_ai/_view/www/src/app/log-list/LogPager.module.css +29 -0
- inspect_ai/_view/www/src/app/log-list/LogPager.tsx +134 -0
- inspect_ai/_view/www/src/app/log-list/LogsFilterInput.module.css +5 -0
- inspect_ai/_view/www/src/app/log-list/LogsFilterInput.tsx +31 -0
- inspect_ai/_view/www/src/app/log-list/LogsPanel.module.css +12 -0
- inspect_ai/_view/www/src/app/log-list/LogsPanel.tsx +178 -0
- inspect_ai/_view/www/src/app/log-list/grid/LogListGrid.module.css +115 -0
- inspect_ai/_view/www/src/app/log-list/grid/LogListGrid.tsx +304 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/CompletedDate.module.css +6 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/CompletedDate.tsx +64 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/EmptyCell.module.css +3 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/EmptyCell.tsx +7 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/FileName.module.css +20 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/FileName.tsx +52 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/Icon.module.css +11 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/Icon.tsx +35 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/Model.module.css +6 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/Model.tsx +34 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/Score.module.css +6 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/Score.tsx +61 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/Status.module.css +15 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/Status.tsx +95 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/Task.module.css +20 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/Task.tsx +50 -0
- inspect_ai/_view/www/src/app/log-list/grid/columns/columns.ts +27 -0
- inspect_ai/_view/www/src/app/log-view/LogView.tsx +2 -5
- inspect_ai/_view/www/src/app/log-view/LogViewContainer.tsx +4 -30
- inspect_ai/_view/www/src/app/log-view/LogViewLayout.tsx +5 -30
- inspect_ai/_view/www/src/app/log-view/tabs/TaskTab.tsx +4 -7
- inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/PrimaryBar.module.css +2 -0
- inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/PrimaryBar.tsx +3 -31
- inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ResultsPanel.tsx +7 -57
- inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ScoreGrid.tsx +2 -2
- inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/SecondaryBar.tsx +7 -1
- inspect_ai/_view/www/src/app/log-view/{navbar/Navbar.tsx → title-view/TitleView.tsx} +3 -6
- inspect_ai/_view/www/src/app/navbar/Navbar.module.css +57 -0
- inspect_ai/_view/www/src/app/navbar/Navbar.tsx +117 -0
- inspect_ai/_view/www/src/app/navbar/useBreadcrumbTruncation.ts +128 -0
- inspect_ai/_view/www/src/app/plan/DatasetDetailView.tsx +3 -3
- inspect_ai/_view/www/src/app/plan/DetailStep.tsx +6 -6
- inspect_ai/_view/www/src/app/plan/PlanDetailView.module.css +1 -0
- inspect_ai/_view/www/src/app/plan/ScorerDetailView.tsx +1 -1
- inspect_ai/_view/www/src/app/routing/AppRouter.tsx +28 -4
- inspect_ai/_view/www/src/app/routing/RouteDispatcher.tsx +28 -0
- inspect_ai/_view/www/src/app/routing/sampleNavigation.ts +76 -7
- inspect_ai/_view/www/src/app/routing/url.ts +193 -20
- inspect_ai/_view/www/src/app/samples/SampleDisplay.tsx +3 -17
- inspect_ai/_view/www/src/app/samples/descriptor/score/ScoreDescriptor.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/SubtaskEventView.tsx +2 -2
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptPanel.tsx +2 -2
- inspect_ai/_view/www/src/app/samples/transcript/outline/tree-visitors.ts +5 -0
- inspect_ai/_view/www/src/app/samples/transcript/transform/treeify.ts +26 -10
- inspect_ai/_view/www/src/app/types.ts +21 -1
- inspect_ai/_view/www/src/client/api/api-http.ts +2 -1
- inspect_ai/_view/www/src/client/api/api-shared.ts +0 -32
- inspect_ai/_view/www/src/client/api/client-api.ts +1 -1
- inspect_ai/_view/www/src/client/remote/remoteLogFile.ts +38 -6
- inspect_ai/_view/www/src/components/TextInput.module.css +45 -0
- inspect_ai/_view/www/src/components/TextInput.tsx +52 -0
- inspect_ai/_view/www/src/constants.ts +18 -0
- inspect_ai/_view/www/src/img/inspect-16.svg +10 -0
- inspect_ai/_view/www/src/img/inspect-back.svg +5 -0
- inspect_ai/_view/www/src/img/inspect-file.svg +26 -0
- inspect_ai/_view/www/src/img/inspect-forward.svg +7 -0
- inspect_ai/_view/www/src/img/inspect-home.svg +18 -0
- inspect_ai/_view/www/src/scoring/metrics.ts +75 -0
- inspect_ai/_view/www/src/scoring/scores.ts +19 -0
- inspect_ai/_view/www/src/scoring/types.ts +11 -0
- inspect_ai/_view/www/src/state/appSlice.ts +27 -7
- inspect_ai/_view/www/src/state/clientEvents.ts +73 -0
- inspect_ai/_view/www/src/state/clientEventsService.ts +105 -0
- inspect_ai/_view/www/src/state/hooks.ts +118 -1
- inspect_ai/_view/www/src/state/log.ts +19 -0
- inspect_ai/_view/www/src/state/logPolling.ts +3 -1
- inspect_ai/_view/www/src/state/logSlice.ts +9 -0
- inspect_ai/_view/www/src/state/logsSlice.ts +157 -15
- inspect_ai/_view/www/src/state/samplePolling.ts +4 -2
- inspect_ai/_view/www/src/tests/utils/path.test.ts +3 -3
- inspect_ai/_view/www/src/utils/evallog.ts +31 -0
- inspect_ai/_view/www/src/utils/path.ts +28 -0
- inspect_ai/_view/www/src/utils/uri.ts +49 -0
- inspect_ai/_view/www/yarn.lock +54 -17
- inspect_ai/analysis/beta/_dataframe/util.py +106 -10
- inspect_ai/log/_recorders/buffer/database.py +55 -16
- inspect_ai/model/_model.py +1 -1
- inspect_ai/model/_providers/providers.py +2 -2
- inspect_ai/model/_providers/vertex.py +3 -0
- inspect_ai/tool/_mcp/_mcp.py +6 -1
- inspect_ai/tool/_mcp/sampling.py +8 -1
- inspect_ai/tool/_tools/_bash_session.py +3 -6
- inspect_ai/tool/_tools/_web_browser/_web_browser.py +3 -8
- inspect_ai/util/_anyio.py +12 -3
- {inspect_ai-0.3.108.dist-info → inspect_ai-0.3.109.dist-info}/METADATA +2 -2
- {inspect_ai-0.3.108.dist-info → inspect_ai-0.3.109.dist-info}/RECORD +124 -94
- inspect_ai/_util/datetime.py +0 -10
- inspect_ai/_view/www/src/app/content/MetaDataView.module.css +0 -35
- inspect_ai/_view/www/src/app/content/MetaDataView.tsx +0 -101
- inspect_ai/_view/www/src/app/log-view/utils.ts +0 -34
- inspect_ai/_view/www/src/app/sidebar/EvalStatus.module.css +0 -15
- inspect_ai/_view/www/src/app/sidebar/EvalStatus.tsx +0 -72
- inspect_ai/_view/www/src/app/sidebar/LogDirectoryTitleView.module.css +0 -16
- inspect_ai/_view/www/src/app/sidebar/LogDirectoryTitleView.tsx +0 -70
- inspect_ai/_view/www/src/app/sidebar/Sidebar.module.css +0 -77
- inspect_ai/_view/www/src/app/sidebar/Sidebar.tsx +0 -119
- inspect_ai/_view/www/src/app/sidebar/SidebarLogEntry.module.css +0 -29
- inspect_ai/_view/www/src/app/sidebar/SidebarLogEntry.tsx +0 -96
- inspect_ai/_view/www/src/app/sidebar/SidebarScoreView.module.css +0 -23
- inspect_ai/_view/www/src/app/sidebar/SidebarScoreView.tsx +0 -44
- inspect_ai/_view/www/src/app/sidebar/SidebarScoresView.module.css +0 -35
- inspect_ai/_view/www/src/app/sidebar/SidebarScoresView.tsx +0 -63
- inspect_ai/_view/www/src/state/logsPolling.ts +0 -118
- /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ModelRolesView.module.css +0 -0
- /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ModelRolesView.tsx +0 -0
- /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ResultsPanel.module.css +0 -0
- /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/RunningStatusPanel.module.css +0 -0
- /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/RunningStatusPanel.tsx +0 -0
- /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ScoreGrid.module.css +0 -0
- /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/SecondaryBar.module.css +0 -0
- /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/StatusPanel.module.css +0 -0
- /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/StatusPanel.tsx +0 -0
- /inspect_ai/_view/www/src/app/log-view/{navbar/Navbar.module.css → title-view/TitleView.module.css} +0 -0
- {inspect_ai-0.3.108.dist-info → inspect_ai-0.3.109.dist-info}/WHEEL +0 -0
- {inspect_ai-0.3.108.dist-info → inspect_ai-0.3.109.dist-info}/entry_points.txt +0 -0
- {inspect_ai-0.3.108.dist-info → inspect_ai-0.3.109.dist-info}/licenses/LICENSE +0 -0
- {inspect_ai-0.3.108.dist-info → inspect_ai-0.3.109.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
import { Link } from "react-router-dom";
|
2
|
+
import { FileLogItem, FolderLogItem } from "../../LogItem";
|
3
|
+
import { columnHelper } from "./columns";
|
4
|
+
|
5
|
+
import { basename } from "../../../../utils/path";
|
6
|
+
import { EmptyCell } from "./EmptyCell";
|
7
|
+
import styles from "./FileName.module.css";
|
8
|
+
|
9
|
+
export const fileNameColumn = () => {
|
10
|
+
return columnHelper.accessor("name", {
|
11
|
+
id: "file_name",
|
12
|
+
header: "File Name",
|
13
|
+
cell: (info) => {
|
14
|
+
const item = info.row.original as FileLogItem | FolderLogItem;
|
15
|
+
if (item.type === "folder") {
|
16
|
+
return <EmptyCell />;
|
17
|
+
}
|
18
|
+
let value = basename(item.name);
|
19
|
+
return (
|
20
|
+
<div className={styles.nameCell}>
|
21
|
+
{item.url ? (
|
22
|
+
<Link to={item.url} className={styles.fileLink}>
|
23
|
+
{value}
|
24
|
+
</Link>
|
25
|
+
) : (
|
26
|
+
value
|
27
|
+
)}
|
28
|
+
</div>
|
29
|
+
);
|
30
|
+
},
|
31
|
+
enableSorting: true,
|
32
|
+
enableGlobalFilter: true,
|
33
|
+
size: 600,
|
34
|
+
minSize: 150,
|
35
|
+
enableResizing: true,
|
36
|
+
sortingFn: (rowA, rowB) => {
|
37
|
+
const itemA = rowA.original as FileLogItem | FolderLogItem;
|
38
|
+
const itemB = rowB.original as FileLogItem | FolderLogItem;
|
39
|
+
|
40
|
+
// Sort folders first, then files
|
41
|
+
if (itemA.type !== itemB.type) {
|
42
|
+
return itemA.type === "folder" ? -1 : 1;
|
43
|
+
}
|
44
|
+
|
45
|
+
// Within same type, sort by basename
|
46
|
+
const valueA = basename(itemA.name);
|
47
|
+
const valueB = basename(itemB.name);
|
48
|
+
|
49
|
+
return valueA.localeCompare(valueB);
|
50
|
+
},
|
51
|
+
});
|
52
|
+
};
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import clsx from "clsx";
|
2
|
+
import { ApplicationIcons } from "../../../appearance/icons";
|
3
|
+
import { columnHelper } from "./columns";
|
4
|
+
|
5
|
+
import styles from "./Icon.module.css";
|
6
|
+
|
7
|
+
export const iconColumn = () => {
|
8
|
+
return columnHelper.accessor("type", {
|
9
|
+
id: "icon",
|
10
|
+
header: "",
|
11
|
+
cell: (info) => (
|
12
|
+
<div className={styles.iconCell}>
|
13
|
+
<i
|
14
|
+
className={clsx(
|
15
|
+
info.getValue() === "file"
|
16
|
+
? ApplicationIcons.inspectFile
|
17
|
+
: ApplicationIcons.folder,
|
18
|
+
)}
|
19
|
+
/>
|
20
|
+
</div>
|
21
|
+
),
|
22
|
+
enableSorting: true,
|
23
|
+
enableGlobalFilter: false,
|
24
|
+
size: 30,
|
25
|
+
minSize: 30,
|
26
|
+
maxSize: 60,
|
27
|
+
enableResizing: false,
|
28
|
+
sortingFn: (rowA, rowB) => {
|
29
|
+
const typeA = rowA.original.type;
|
30
|
+
const typeB = rowB.original.type;
|
31
|
+
|
32
|
+
return typeA.localeCompare(typeB);
|
33
|
+
},
|
34
|
+
});
|
35
|
+
};
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import { columnHelper } from "./columns";
|
2
|
+
import { EmptyCell } from "./EmptyCell";
|
3
|
+
|
4
|
+
import styles from "./Model.module.css";
|
5
|
+
|
6
|
+
export const modelColumn = () => {
|
7
|
+
return columnHelper.accessor(
|
8
|
+
(row) => {
|
9
|
+
if (row.type !== "file") return "";
|
10
|
+
return row.header?.eval?.model || "";
|
11
|
+
},
|
12
|
+
{
|
13
|
+
id: "model",
|
14
|
+
header: "Model",
|
15
|
+
cell: (info) => {
|
16
|
+
const item = info.row.original;
|
17
|
+
if (item.type !== "file" || item.header?.eval.model === undefined) {
|
18
|
+
return <EmptyCell />;
|
19
|
+
}
|
20
|
+
return (
|
21
|
+
<div className={styles.modelCell}>
|
22
|
+
{item.header?.eval.model || ""}
|
23
|
+
</div>
|
24
|
+
);
|
25
|
+
},
|
26
|
+
enableSorting: true,
|
27
|
+
enableGlobalFilter: true,
|
28
|
+
size: 300,
|
29
|
+
minSize: 100,
|
30
|
+
maxSize: 400,
|
31
|
+
enableResizing: true,
|
32
|
+
},
|
33
|
+
);
|
34
|
+
};
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import { firstMetric } from "../../../../scoring/metrics";
|
2
|
+
import { formatPrettyDecimal } from "../../../../utils/format";
|
3
|
+
import { FileLogItem, FolderLogItem } from "../../LogItem";
|
4
|
+
import { columnHelper } from "./columns";
|
5
|
+
import { EmptyCell } from "./EmptyCell";
|
6
|
+
|
7
|
+
import styles from "./Score.module.css";
|
8
|
+
|
9
|
+
export const scoreColumn = () => {
|
10
|
+
return columnHelper.accessor(
|
11
|
+
(row) => {
|
12
|
+
const metric = itemMetric(row);
|
13
|
+
return metric?.value !== undefined
|
14
|
+
? formatPrettyDecimal(metric.value)
|
15
|
+
: "";
|
16
|
+
},
|
17
|
+
{
|
18
|
+
id: "score",
|
19
|
+
header: "Score",
|
20
|
+
cell: (info) => {
|
21
|
+
const metric = itemMetric(info.row.original);
|
22
|
+
if (metric === undefined) {
|
23
|
+
return <EmptyCell />;
|
24
|
+
}
|
25
|
+
return (
|
26
|
+
<div className={styles.scoreCell}>
|
27
|
+
{formatPrettyDecimal(metric.value)}
|
28
|
+
</div>
|
29
|
+
);
|
30
|
+
},
|
31
|
+
sortingFn: (rowA, rowB) => {
|
32
|
+
const itemA = rowA.original;
|
33
|
+
const itemB = rowB.original;
|
34
|
+
|
35
|
+
const metricA = itemMetric(itemA);
|
36
|
+
const metricB = itemMetric(itemB);
|
37
|
+
|
38
|
+
if (!metricA && !metricB) return 0;
|
39
|
+
if (!metricA) return -1;
|
40
|
+
if (!metricB) return 1;
|
41
|
+
|
42
|
+
return (metricA.value || 0) - (metricB.value || 0);
|
43
|
+
},
|
44
|
+
enableSorting: true,
|
45
|
+
enableGlobalFilter: true,
|
46
|
+
size: 80,
|
47
|
+
minSize: 60,
|
48
|
+
maxSize: 120,
|
49
|
+
enableResizing: true,
|
50
|
+
},
|
51
|
+
);
|
52
|
+
};
|
53
|
+
|
54
|
+
const itemMetric = (item: FileLogItem | FolderLogItem) => {
|
55
|
+
if (item.type !== "file") {
|
56
|
+
return undefined;
|
57
|
+
}
|
58
|
+
|
59
|
+
const header = item.header;
|
60
|
+
return header?.results ? firstMetric(header.results) : undefined;
|
61
|
+
};
|
@@ -0,0 +1,95 @@
|
|
1
|
+
import clsx from "clsx";
|
2
|
+
import { FileLogItem, FolderLogItem } from "../../LogItem";
|
3
|
+
import { columnHelper } from "./columns";
|
4
|
+
import { EmptyCell } from "./EmptyCell";
|
5
|
+
|
6
|
+
import { ApplicationIcons } from "../../../appearance/icons";
|
7
|
+
import styles from "./Status.module.css";
|
8
|
+
|
9
|
+
export const statusColumn = () => {
|
10
|
+
return columnHelper.accessor((row) => itemStatusLabel(row), {
|
11
|
+
id: "status",
|
12
|
+
header: "Status",
|
13
|
+
cell: (info) => {
|
14
|
+
const item = info.row.original;
|
15
|
+
const status = itemStatus(item);
|
16
|
+
|
17
|
+
if (!status) {
|
18
|
+
return <EmptyCell />;
|
19
|
+
}
|
20
|
+
|
21
|
+
const icon =
|
22
|
+
status === "error"
|
23
|
+
? ApplicationIcons.error
|
24
|
+
: status === "started"
|
25
|
+
? ApplicationIcons.running
|
26
|
+
: status === "cancelled"
|
27
|
+
? ApplicationIcons.cancelled
|
28
|
+
: ApplicationIcons.success;
|
29
|
+
|
30
|
+
const clz =
|
31
|
+
status === "error"
|
32
|
+
? styles.error
|
33
|
+
: status === "started"
|
34
|
+
? styles.started
|
35
|
+
: status === "cancelled"
|
36
|
+
? styles.cancelled
|
37
|
+
: styles.success;
|
38
|
+
|
39
|
+
return (
|
40
|
+
<div className={styles.statusCell}>
|
41
|
+
<i className={clsx(icon, clz)} />
|
42
|
+
</div>
|
43
|
+
);
|
44
|
+
},
|
45
|
+
sortingFn: (rowA, rowB) => {
|
46
|
+
const itemA = rowA.original as FileLogItem | FolderLogItem;
|
47
|
+
const itemB = rowB.original as FileLogItem | FolderLogItem;
|
48
|
+
|
49
|
+
const statusA = itemStatus(itemA) || "";
|
50
|
+
const statusB = itemStatus(itemB) || "";
|
51
|
+
|
52
|
+
// If A is empty, goes to bottom
|
53
|
+
if (!statusA && statusB) {
|
54
|
+
return 1;
|
55
|
+
}
|
56
|
+
// If B is empty, goes to bottom
|
57
|
+
if (statusA && !statusB) {
|
58
|
+
return -1;
|
59
|
+
}
|
60
|
+
|
61
|
+
return statusA.localeCompare(statusB);
|
62
|
+
},
|
63
|
+
enableSorting: true,
|
64
|
+
enableGlobalFilter: true,
|
65
|
+
size: 80,
|
66
|
+
minSize: 60,
|
67
|
+
maxSize: 120,
|
68
|
+
enableResizing: true,
|
69
|
+
});
|
70
|
+
};
|
71
|
+
|
72
|
+
const itemStatus = (item: FileLogItem | FolderLogItem) => {
|
73
|
+
if (item.type !== "file") {
|
74
|
+
return undefined;
|
75
|
+
}
|
76
|
+
const header = item.header;
|
77
|
+
return header?.status;
|
78
|
+
};
|
79
|
+
|
80
|
+
const itemStatusLabel = (item: FileLogItem | FolderLogItem) => {
|
81
|
+
const status = itemStatus(item);
|
82
|
+
if (!status) return "";
|
83
|
+
|
84
|
+
// Return multiple searchable terms for filtering
|
85
|
+
switch (status) {
|
86
|
+
case "error":
|
87
|
+
return "error failed failure";
|
88
|
+
case "started":
|
89
|
+
return "running started in-progress active";
|
90
|
+
case "cancelled":
|
91
|
+
return "cancelled canceled stopped aborted";
|
92
|
+
default:
|
93
|
+
return "success done complete finished completed";
|
94
|
+
}
|
95
|
+
};
|
@@ -0,0 +1,20 @@
|
|
1
|
+
.nameCell {
|
2
|
+
display: flex;
|
3
|
+
align-items: center;
|
4
|
+
min-width: 0;
|
5
|
+
flex: 1;
|
6
|
+
}
|
7
|
+
|
8
|
+
.logLink {
|
9
|
+
color: var(--bs-link-color);
|
10
|
+
text-decoration: none;
|
11
|
+
overflow: hidden;
|
12
|
+
text-overflow: ellipsis;
|
13
|
+
white-space: nowrap;
|
14
|
+
max-width: 100%;
|
15
|
+
}
|
16
|
+
|
17
|
+
.logLink:hover {
|
18
|
+
color: var(--bs-link-hover-color);
|
19
|
+
text-decoration: underline;
|
20
|
+
}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import { Link } from "react-router-dom";
|
2
|
+
import { FileLogItem, FolderLogItem } from "../../LogItem";
|
3
|
+
import { columnHelper } from "./columns";
|
4
|
+
|
5
|
+
import { parseLogFileName } from "../../../../utils/evallog";
|
6
|
+
import styles from "./Task.module.css";
|
7
|
+
|
8
|
+
export const taskColumn = () => {
|
9
|
+
return columnHelper.accessor((row) => itemName(row), {
|
10
|
+
id: "task",
|
11
|
+
header: "Task",
|
12
|
+
cell: (info) => {
|
13
|
+
const item = info.row.original as FileLogItem | FolderLogItem;
|
14
|
+
let value = itemName(item);
|
15
|
+
return (
|
16
|
+
<div className={styles.nameCell}>
|
17
|
+
{item.url ? (
|
18
|
+
<Link to={item.url} className={styles.logLink}>
|
19
|
+
{value}
|
20
|
+
</Link>
|
21
|
+
) : (
|
22
|
+
value
|
23
|
+
)}
|
24
|
+
</div>
|
25
|
+
);
|
26
|
+
},
|
27
|
+
enableSorting: true,
|
28
|
+
enableGlobalFilter: true,
|
29
|
+
size: 250,
|
30
|
+
minSize: 150,
|
31
|
+
enableResizing: true,
|
32
|
+
sortingFn: (rowA, rowB) => {
|
33
|
+
const itemA = rowA.original as FileLogItem | FolderLogItem;
|
34
|
+
const itemB = rowB.original as FileLogItem | FolderLogItem;
|
35
|
+
|
36
|
+
const valueA = itemName(itemA);
|
37
|
+
const valueB = itemName(itemB);
|
38
|
+
|
39
|
+
return valueA.localeCompare(valueB);
|
40
|
+
},
|
41
|
+
});
|
42
|
+
};
|
43
|
+
|
44
|
+
const itemName = (item: FileLogItem | FolderLogItem) => {
|
45
|
+
let value = item.name;
|
46
|
+
if (item.type === "file") {
|
47
|
+
return item.header?.eval?.task || parseLogFileName(item.name).name;
|
48
|
+
}
|
49
|
+
return value;
|
50
|
+
};
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import { createColumnHelper } from "@tanstack/react-table";
|
2
|
+
import { FileLogItem, FolderLogItem } from "../../LogItem";
|
3
|
+
import { completedDateColumn } from "./CompletedDate";
|
4
|
+
import { fileNameColumn } from "./FileName";
|
5
|
+
import { iconColumn } from "./Icon";
|
6
|
+
import { modelColumn } from "./Model";
|
7
|
+
import { scoreColumn } from "./Score";
|
8
|
+
import { statusColumn } from "./Status";
|
9
|
+
import { taskColumn } from "./Task";
|
10
|
+
|
11
|
+
export const columnHelper = createColumnHelper<FileLogItem | FolderLogItem>();
|
12
|
+
|
13
|
+
export const getColumns = (columnIds?: string[]) => {
|
14
|
+
const allColumns = [
|
15
|
+
iconColumn(),
|
16
|
+
taskColumn(),
|
17
|
+
fileNameColumn(),
|
18
|
+
completedDateColumn(),
|
19
|
+
modelColumn(),
|
20
|
+
scoreColumn(),
|
21
|
+
statusColumn(),
|
22
|
+
];
|
23
|
+
if (columnIds) {
|
24
|
+
return allColumns.filter((col) => columnIds.includes(col.id || ""));
|
25
|
+
}
|
26
|
+
return allColumns;
|
27
|
+
};
|
@@ -9,7 +9,6 @@ import {
|
|
9
9
|
} from "react";
|
10
10
|
import { EmptyPanel } from "../../components/EmptyPanel";
|
11
11
|
import { TabPanel, TabSet } from "../../components/TabSet";
|
12
|
-
import { Navbar } from "./navbar/Navbar";
|
13
12
|
|
14
13
|
import { useEvalSpec, useRefreshLog } from "../../state/hooks";
|
15
14
|
import { useStore } from "../../state/store";
|
@@ -20,6 +19,7 @@ import { useJsonTabConfig } from "./tabs/JsonTab";
|
|
20
19
|
import { useModelsTab } from "./tabs/ModelsTab";
|
21
20
|
import { useSamplesTabConfig } from "./tabs/SamplesTab";
|
22
21
|
import { useTaskTabConfig } from "./tabs/TaskTab";
|
22
|
+
import { TitleView } from "./title-view/TitleView";
|
23
23
|
import { TabDescriptor } from "./types";
|
24
24
|
|
25
25
|
export const LogView: FC = () => {
|
@@ -33,8 +33,6 @@ export const LogView: FC = () => {
|
|
33
33
|
const runningMetrics = useStore(
|
34
34
|
(state) => state.log.pendingSampleSummaries?.metrics,
|
35
35
|
);
|
36
|
-
const logs = useStore((state) => state.logs.logs);
|
37
|
-
const showToggle = logs.files.length > 1 || !!logs.log_dir || false;
|
38
36
|
|
39
37
|
// Use individual tab config hooks
|
40
38
|
const samplesTabConfig = useSamplesTabConfig(
|
@@ -111,14 +109,13 @@ export const LogView: FC = () => {
|
|
111
109
|
|
112
110
|
return (
|
113
111
|
<Fragment>
|
114
|
-
<
|
112
|
+
<TitleView
|
115
113
|
evalSpec={evalSpec}
|
116
114
|
evalPlan={selectedLogSummary?.plan}
|
117
115
|
evalResults={selectedLogSummary?.results}
|
118
116
|
runningMetrics={runningMetrics}
|
119
117
|
evalStats={selectedLogSummary?.stats}
|
120
118
|
status={selectedLogSummary?.status}
|
121
|
-
showToggle={showToggle}
|
122
119
|
/>
|
123
120
|
<div ref={divRef} className={clsx("workspace", styles.workspace)}>
|
124
121
|
<div className={clsx("log-detail", styles.tabContainer)}>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { FC, useEffect } from "react";
|
2
|
-
import { useNavigate
|
2
|
+
import { useNavigate } from "react-router-dom";
|
3
3
|
import { kLogViewSamplesTabId } from "../../constants";
|
4
4
|
import {
|
5
5
|
useFilteredSamples,
|
@@ -7,20 +7,14 @@ import {
|
|
7
7
|
useTotalSampleCount,
|
8
8
|
} from "../../state/hooks";
|
9
9
|
import { useStore } from "../../state/store";
|
10
|
-
import { baseUrl } from "../routing/url";
|
10
|
+
import { baseUrl, useLogRouteParams } from "../routing/url";
|
11
11
|
import { LogViewLayout } from "./LogViewLayout";
|
12
12
|
|
13
13
|
/**
|
14
14
|
* LogContainer component that handles routing to specific logs, tabs, and samples
|
15
15
|
*/
|
16
16
|
export const LogViewContainer: FC = () => {
|
17
|
-
const { logPath, tabId, sampleId, epoch, sampleTabId } =
|
18
|
-
logPath?: string;
|
19
|
-
tabId?: string;
|
20
|
-
sampleId?: string;
|
21
|
-
epoch?: string;
|
22
|
-
sampleTabId?: string;
|
23
|
-
}>();
|
17
|
+
const { logPath, tabId, sampleId, epoch, sampleTabId } = useLogRouteParams();
|
24
18
|
|
25
19
|
const initialState = useStore((state) => state.app.initialState);
|
26
20
|
const clearInitialState = useStore(
|
@@ -69,7 +63,7 @@ export const LogViewContainer: FC = () => {
|
|
69
63
|
useEffect(() => {
|
70
64
|
const loadLogFromPath = async () => {
|
71
65
|
if (logPath) {
|
72
|
-
await selectLogFile(
|
66
|
+
await selectLogFile(logPath);
|
73
67
|
|
74
68
|
// Set the tab if specified in the URL
|
75
69
|
if (tabId) {
|
@@ -86,26 +80,6 @@ export const LogViewContainer: FC = () => {
|
|
86
80
|
|
87
81
|
clearSelectedLogSummary();
|
88
82
|
}
|
89
|
-
} else {
|
90
|
-
setStatus({
|
91
|
-
loading: true,
|
92
|
-
error: undefined,
|
93
|
-
});
|
94
|
-
|
95
|
-
// Reset the log/task tab
|
96
|
-
setSelectedLogIndex(-1);
|
97
|
-
setWorkspaceTab(kLogViewSamplesTabId);
|
98
|
-
|
99
|
-
// Refresh the list of logs
|
100
|
-
await refreshLogs();
|
101
|
-
|
102
|
-
// Select the first log in the list
|
103
|
-
setSelectedLogIndex(0);
|
104
|
-
|
105
|
-
setStatus({
|
106
|
-
loading: false,
|
107
|
-
error: undefined,
|
108
|
-
});
|
109
83
|
}
|
110
84
|
};
|
111
85
|
|
@@ -4,7 +4,7 @@ import { ErrorPanel } from "../../components/ErrorPanel";
|
|
4
4
|
import { FindBand } from "../../components/FindBand";
|
5
5
|
import { ProgressBar } from "../../components/ProgressBar";
|
6
6
|
import { useStore } from "../../state/store";
|
7
|
-
import {
|
7
|
+
import { Navbar } from "../navbar/Navbar";
|
8
8
|
import { LogView } from "./LogView";
|
9
9
|
|
10
10
|
/**
|
@@ -13,28 +13,16 @@ import { LogView } from "./LogView";
|
|
13
13
|
export const LogViewLayout: FC = () => {
|
14
14
|
// App layout and state
|
15
15
|
const appStatus = useStore((state) => state.app.status);
|
16
|
-
const offCanvas = useStore((state) => state.app.offcanvas);
|
17
|
-
const setOffCanvas = useStore((state) => state.appActions.setOffcanvas);
|
18
|
-
const clearWorkspaceTab = useStore(
|
19
|
-
(state) => state.appActions.clearWorkspaceTab,
|
20
|
-
);
|
21
|
-
const clearSampleTab = useStore((state) => state.appActions.clearSampleTab);
|
22
16
|
|
23
17
|
// Find
|
24
18
|
const nativeFind = useStore((state) => state.capabilities.nativeFind);
|
25
19
|
const showFind = useStore((state) => state.app.showFind);
|
26
20
|
const setShowFind = useStore((state) => state.appActions.setShowFind);
|
27
21
|
const hideFind = useStore((state) => state.appActions.hideFind);
|
22
|
+
const singleFileMode = useStore((state) => state.app.singleFileMode);
|
28
23
|
|
29
24
|
// Logs Data
|
30
25
|
const logs = useStore((state) => state.logs.logs);
|
31
|
-
const selectedLogIndex = useStore((state) => state.logs.selectedLogIndex);
|
32
|
-
const logHeaders = useStore((state) => state.logs.logHeaders);
|
33
|
-
const headersLoading = useStore((state) => state.logs.headersLoading);
|
34
|
-
|
35
|
-
// Log Data
|
36
|
-
const selectedLogSummary = useStore((state) => state.log.selectedLogSummary);
|
37
|
-
const resetFiltering = useStore((state) => state.logActions.resetFiltering);
|
38
26
|
|
39
27
|
// The main application reference
|
40
28
|
const mainAppRef = useRef<HTMLDivElement>(null);
|
@@ -43,13 +31,6 @@ export const LogViewLayout: FC = () => {
|
|
43
31
|
// if there are no log files, then don't show sidebar
|
44
32
|
const fullScreen = logs.files.length === 1 && !logs.log_dir;
|
45
33
|
|
46
|
-
const handleSelectedIndexChanged = useCallback(() => {
|
47
|
-
setOffCanvas(false);
|
48
|
-
resetFiltering();
|
49
|
-
clearSampleTab();
|
50
|
-
clearWorkspaceTab();
|
51
|
-
}, [setOffCanvas, resetFiltering, clearSampleTab, clearWorkspaceTab]);
|
52
|
-
|
53
34
|
const handleKeyboard = useCallback(
|
54
35
|
(e: KeyboardEvent) => {
|
55
36
|
// Add keyboard shortcuts for find, if needed
|
@@ -68,25 +49,19 @@ export const LogViewLayout: FC = () => {
|
|
68
49
|
|
69
50
|
return (
|
70
51
|
<>
|
71
|
-
{!fullScreen && selectedLogSummary ? (
|
72
|
-
<Sidebar
|
73
|
-
logHeaders={logHeaders}
|
74
|
-
loading={headersLoading}
|
75
|
-
selectedIndex={selectedLogIndex}
|
76
|
-
onSelectedIndexChanged={handleSelectedIndexChanged}
|
77
|
-
/>
|
78
|
-
) : undefined}
|
79
52
|
<div
|
80
53
|
ref={mainAppRef}
|
81
54
|
className={clsx(
|
82
55
|
"app-main-grid",
|
83
56
|
fullScreen ? "full-screen" : undefined,
|
84
|
-
|
57
|
+
singleFileMode ? "single-file-mode" : undefined,
|
58
|
+
"log-view",
|
85
59
|
)}
|
86
60
|
tabIndex={0}
|
87
61
|
onKeyDown={handleKeyboard}
|
88
62
|
>
|
89
63
|
{!nativeFind && showFind ? <FindBand /> : ""}
|
64
|
+
{!singleFileMode ? <Navbar /> : ""}
|
90
65
|
<ProgressBar animating={appStatus.loading} />
|
91
66
|
{appStatus.error ? (
|
92
67
|
<ErrorPanel
|
@@ -5,8 +5,8 @@ import { Card, CardBody, CardHeader } from "../../../components/Card";
|
|
5
5
|
import { kLogViewTaskTabId } from "../../../constants";
|
6
6
|
import { formatDuration, toTitleCase } from "../../../utils/format";
|
7
7
|
import { ghCommitUrl } from "../../../utils/git";
|
8
|
-
import { MetaDataView } from "../../content/MetaDataView";
|
9
8
|
|
9
|
+
import { MetaDataGrid } from "../../content/MetaDataGrid";
|
10
10
|
import styles from "./TaskTab.module.css";
|
11
11
|
|
12
12
|
// Individual hook for Info tab
|
@@ -101,14 +101,13 @@ export const TaskTab: FC<TaskTabProps> = ({ evalSpec, evalStats }) => {
|
|
101
101
|
<CardHeader label="Task Info" />
|
102
102
|
<CardBody id={"task-card-config"}>
|
103
103
|
<div className={clsx(styles.grid)}>
|
104
|
-
<
|
104
|
+
<MetaDataGrid
|
105
105
|
key={`plan-md-task`}
|
106
106
|
className={"text-size-small"}
|
107
107
|
entries={taskInformation}
|
108
|
-
tableOptions="sm"
|
109
108
|
/>
|
110
109
|
|
111
|
-
<
|
110
|
+
<MetaDataGrid
|
112
111
|
entries={{
|
113
112
|
["Start"]: new Date(
|
114
113
|
evalStats?.started_at || 0,
|
@@ -118,7 +117,6 @@ export const TaskTab: FC<TaskTabProps> = ({ evalSpec, evalStats }) => {
|
|
118
117
|
).toLocaleString(),
|
119
118
|
["Duration"]: totalDuration,
|
120
119
|
}}
|
121
|
-
tableOptions="sm"
|
122
120
|
/>
|
123
121
|
</div>
|
124
122
|
</CardBody>
|
@@ -128,11 +126,10 @@ export const TaskTab: FC<TaskTabProps> = ({ evalSpec, evalStats }) => {
|
|
128
126
|
<Card>
|
129
127
|
<CardHeader label="Task Args" />
|
130
128
|
<CardBody id={"task-card-config"}>
|
131
|
-
<
|
129
|
+
<MetaDataGrid
|
132
130
|
key={`plan-md-task-args`}
|
133
131
|
className={"text-size-small"}
|
134
132
|
entries={task_args as Record<string, unknown>}
|
135
|
-
tableOptions="sm"
|
136
133
|
/>
|
137
134
|
</CardBody>
|
138
135
|
</Card>
|