inspect-ai 0.3.107__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.
Files changed (142) hide show
  1. inspect_ai/_eval/task/log.py +1 -1
  2. inspect_ai/_eval/task/run.py +1 -1
  3. inspect_ai/_util/dateutil.py +40 -0
  4. inspect_ai/_view/schema.py +11 -0
  5. inspect_ai/_view/www/CLAUDE.md +1 -1
  6. inspect_ai/_view/www/dist/assets/index.css +2068 -1796
  7. inspect_ai/_view/www/dist/assets/index.js +7951 -3643
  8. inspect_ai/_view/www/package.json +3 -2
  9. inspect_ai/_view/www/src/@types/log.d.ts +5 -5
  10. inspect_ai/_view/www/src/app/App.css +71 -4
  11. inspect_ai/_view/www/src/app/App.tsx +7 -0
  12. inspect_ai/_view/www/src/app/appearance/icons.ts +18 -2
  13. inspect_ai/_view/www/src/app/content/RenderedContent.tsx +7 -9
  14. inspect_ai/_view/www/src/app/log-list/LogItem.ts +18 -0
  15. inspect_ai/_view/www/src/app/log-list/LogListFooter.module.css +55 -0
  16. inspect_ai/_view/www/src/app/log-list/LogListFooter.tsx +67 -0
  17. inspect_ai/_view/www/src/app/log-list/LogPager.module.css +29 -0
  18. inspect_ai/_view/www/src/app/log-list/LogPager.tsx +134 -0
  19. inspect_ai/_view/www/src/app/log-list/LogsFilterInput.module.css +5 -0
  20. inspect_ai/_view/www/src/app/log-list/LogsFilterInput.tsx +31 -0
  21. inspect_ai/_view/www/src/app/log-list/LogsPanel.module.css +12 -0
  22. inspect_ai/_view/www/src/app/log-list/LogsPanel.tsx +178 -0
  23. inspect_ai/_view/www/src/app/log-list/grid/LogListGrid.module.css +115 -0
  24. inspect_ai/_view/www/src/app/log-list/grid/LogListGrid.tsx +304 -0
  25. inspect_ai/_view/www/src/app/log-list/grid/columns/CompletedDate.module.css +6 -0
  26. inspect_ai/_view/www/src/app/log-list/grid/columns/CompletedDate.tsx +64 -0
  27. inspect_ai/_view/www/src/app/log-list/grid/columns/EmptyCell.module.css +3 -0
  28. inspect_ai/_view/www/src/app/log-list/grid/columns/EmptyCell.tsx +7 -0
  29. inspect_ai/_view/www/src/app/log-list/grid/columns/FileName.module.css +20 -0
  30. inspect_ai/_view/www/src/app/log-list/grid/columns/FileName.tsx +52 -0
  31. inspect_ai/_view/www/src/app/log-list/grid/columns/Icon.module.css +11 -0
  32. inspect_ai/_view/www/src/app/log-list/grid/columns/Icon.tsx +35 -0
  33. inspect_ai/_view/www/src/app/log-list/grid/columns/Model.module.css +6 -0
  34. inspect_ai/_view/www/src/app/log-list/grid/columns/Model.tsx +34 -0
  35. inspect_ai/_view/www/src/app/log-list/grid/columns/Score.module.css +6 -0
  36. inspect_ai/_view/www/src/app/log-list/grid/columns/Score.tsx +61 -0
  37. inspect_ai/_view/www/src/app/log-list/grid/columns/Status.module.css +15 -0
  38. inspect_ai/_view/www/src/app/log-list/grid/columns/Status.tsx +95 -0
  39. inspect_ai/_view/www/src/app/log-list/grid/columns/Task.module.css +20 -0
  40. inspect_ai/_view/www/src/app/log-list/grid/columns/Task.tsx +50 -0
  41. inspect_ai/_view/www/src/app/log-list/grid/columns/columns.ts +27 -0
  42. inspect_ai/_view/www/src/app/log-view/LogView.tsx +2 -5
  43. inspect_ai/_view/www/src/app/log-view/LogViewContainer.tsx +4 -30
  44. inspect_ai/_view/www/src/app/log-view/LogViewLayout.tsx +5 -30
  45. inspect_ai/_view/www/src/app/log-view/tabs/TaskTab.tsx +4 -7
  46. inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/PrimaryBar.module.css +2 -0
  47. inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/PrimaryBar.tsx +3 -31
  48. inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ResultsPanel.tsx +7 -57
  49. inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ScoreGrid.tsx +2 -2
  50. inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/SecondaryBar.tsx +7 -1
  51. inspect_ai/_view/www/src/app/log-view/{navbar/Navbar.tsx → title-view/TitleView.tsx} +3 -6
  52. inspect_ai/_view/www/src/app/navbar/Navbar.module.css +57 -0
  53. inspect_ai/_view/www/src/app/navbar/Navbar.tsx +117 -0
  54. inspect_ai/_view/www/src/app/navbar/useBreadcrumbTruncation.ts +128 -0
  55. inspect_ai/_view/www/src/app/plan/DatasetDetailView.tsx +3 -3
  56. inspect_ai/_view/www/src/app/plan/DetailStep.tsx +6 -6
  57. inspect_ai/_view/www/src/app/plan/PlanDetailView.module.css +1 -0
  58. inspect_ai/_view/www/src/app/plan/ScorerDetailView.tsx +1 -1
  59. inspect_ai/_view/www/src/app/routing/AppRouter.tsx +28 -4
  60. inspect_ai/_view/www/src/app/routing/RouteDispatcher.tsx +28 -0
  61. inspect_ai/_view/www/src/app/routing/sampleNavigation.ts +76 -7
  62. inspect_ai/_view/www/src/app/routing/url.ts +193 -20
  63. inspect_ai/_view/www/src/app/samples/SampleDisplay.tsx +3 -17
  64. inspect_ai/_view/www/src/app/samples/descriptor/score/ScoreDescriptor.tsx +1 -1
  65. inspect_ai/_view/www/src/app/samples/transcript/SubtaskEventView.tsx +2 -2
  66. inspect_ai/_view/www/src/app/samples/transcript/TranscriptPanel.tsx +2 -2
  67. inspect_ai/_view/www/src/app/samples/transcript/outline/tree-visitors.ts +5 -0
  68. inspect_ai/_view/www/src/app/samples/transcript/transform/treeify.ts +26 -10
  69. inspect_ai/_view/www/src/app/types.ts +21 -1
  70. inspect_ai/_view/www/src/client/api/api-http.ts +2 -1
  71. inspect_ai/_view/www/src/client/api/api-shared.ts +0 -32
  72. inspect_ai/_view/www/src/client/api/client-api.ts +1 -1
  73. inspect_ai/_view/www/src/client/remote/remoteLogFile.ts +38 -6
  74. inspect_ai/_view/www/src/components/TextInput.module.css +45 -0
  75. inspect_ai/_view/www/src/components/TextInput.tsx +52 -0
  76. inspect_ai/_view/www/src/constants.ts +18 -0
  77. inspect_ai/_view/www/src/img/inspect-16.svg +10 -0
  78. inspect_ai/_view/www/src/img/inspect-back.svg +5 -0
  79. inspect_ai/_view/www/src/img/inspect-file.svg +26 -0
  80. inspect_ai/_view/www/src/img/inspect-forward.svg +7 -0
  81. inspect_ai/_view/www/src/img/inspect-home.svg +18 -0
  82. inspect_ai/_view/www/src/scoring/metrics.ts +75 -0
  83. inspect_ai/_view/www/src/scoring/scores.ts +19 -0
  84. inspect_ai/_view/www/src/scoring/types.ts +11 -0
  85. inspect_ai/_view/www/src/state/appSlice.ts +27 -7
  86. inspect_ai/_view/www/src/state/clientEvents.ts +73 -0
  87. inspect_ai/_view/www/src/state/clientEventsService.ts +105 -0
  88. inspect_ai/_view/www/src/state/hooks.ts +118 -1
  89. inspect_ai/_view/www/src/state/log.ts +19 -0
  90. inspect_ai/_view/www/src/state/logPolling.ts +3 -1
  91. inspect_ai/_view/www/src/state/logSlice.ts +9 -0
  92. inspect_ai/_view/www/src/state/logsSlice.ts +157 -15
  93. inspect_ai/_view/www/src/state/samplePolling.ts +4 -2
  94. inspect_ai/_view/www/src/tests/utils/path.test.ts +3 -3
  95. inspect_ai/_view/www/src/utils/evallog.ts +31 -0
  96. inspect_ai/_view/www/src/utils/path.ts +28 -0
  97. inspect_ai/_view/www/src/utils/uri.ts +49 -0
  98. inspect_ai/_view/www/yarn.lock +54 -17
  99. inspect_ai/analysis/beta/_dataframe/util.py +106 -10
  100. inspect_ai/log/_recorders/buffer/database.py +55 -16
  101. inspect_ai/model/_model.py +1 -1
  102. inspect_ai/model/_providers/_anthropic_citations.py +1 -4
  103. inspect_ai/model/_providers/providers.py +2 -2
  104. inspect_ai/model/_providers/vertex.py +3 -0
  105. inspect_ai/tool/_mcp/_mcp.py +6 -1
  106. inspect_ai/tool/_mcp/sampling.py +8 -1
  107. inspect_ai/tool/_tools/_bash_session.py +3 -6
  108. inspect_ai/tool/_tools/_web_browser/_web_browser.py +3 -8
  109. inspect_ai/util/_anyio.py +12 -3
  110. {inspect_ai-0.3.107.dist-info → inspect_ai-0.3.109.dist-info}/METADATA +2 -2
  111. {inspect_ai-0.3.107.dist-info → inspect_ai-0.3.109.dist-info}/RECORD +125 -95
  112. inspect_ai/_util/datetime.py +0 -10
  113. inspect_ai/_view/www/src/app/content/MetaDataView.module.css +0 -35
  114. inspect_ai/_view/www/src/app/content/MetaDataView.tsx +0 -101
  115. inspect_ai/_view/www/src/app/log-view/utils.ts +0 -34
  116. inspect_ai/_view/www/src/app/sidebar/EvalStatus.module.css +0 -15
  117. inspect_ai/_view/www/src/app/sidebar/EvalStatus.tsx +0 -72
  118. inspect_ai/_view/www/src/app/sidebar/LogDirectoryTitleView.module.css +0 -16
  119. inspect_ai/_view/www/src/app/sidebar/LogDirectoryTitleView.tsx +0 -70
  120. inspect_ai/_view/www/src/app/sidebar/Sidebar.module.css +0 -77
  121. inspect_ai/_view/www/src/app/sidebar/Sidebar.tsx +0 -119
  122. inspect_ai/_view/www/src/app/sidebar/SidebarLogEntry.module.css +0 -29
  123. inspect_ai/_view/www/src/app/sidebar/SidebarLogEntry.tsx +0 -96
  124. inspect_ai/_view/www/src/app/sidebar/SidebarScoreView.module.css +0 -23
  125. inspect_ai/_view/www/src/app/sidebar/SidebarScoreView.tsx +0 -44
  126. inspect_ai/_view/www/src/app/sidebar/SidebarScoresView.module.css +0 -35
  127. inspect_ai/_view/www/src/app/sidebar/SidebarScoresView.tsx +0 -63
  128. inspect_ai/_view/www/src/state/logsPolling.ts +0 -118
  129. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ModelRolesView.module.css +0 -0
  130. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ModelRolesView.tsx +0 -0
  131. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ResultsPanel.module.css +0 -0
  132. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/RunningStatusPanel.module.css +0 -0
  133. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/RunningStatusPanel.tsx +0 -0
  134. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ScoreGrid.module.css +0 -0
  135. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/SecondaryBar.module.css +0 -0
  136. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/StatusPanel.module.css +0 -0
  137. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/StatusPanel.tsx +0 -0
  138. /inspect_ai/_view/www/src/app/log-view/{navbar/Navbar.module.css → title-view/TitleView.module.css} +0 -0
  139. {inspect_ai-0.3.107.dist-info → inspect_ai-0.3.109.dist-info}/WHEEL +0 -0
  140. {inspect_ai-0.3.107.dist-info → inspect_ai-0.3.109.dist-info}/entry_points.txt +0 -0
  141. {inspect_ai-0.3.107.dist-info → inspect_ai-0.3.109.dist-info}/licenses/LICENSE +0 -0
  142. {inspect_ai-0.3.107.dist-info → inspect_ai-0.3.109.dist-info}/top_level.txt +0 -0
@@ -1,101 +0,0 @@
1
- import clsx from "clsx";
2
- import { CSSProperties, FC } from "react";
3
- import styles from "./MetaDataView.module.css";
4
- import { RenderedContent } from "./RenderedContent";
5
-
6
- interface MetadataViewProps {
7
- id?: string;
8
- style?: CSSProperties;
9
- entries: Record<string, unknown> | Array<{ name: string; value: unknown }>;
10
- tableOptions?: string;
11
- compact?: boolean;
12
- className?: string | string[];
13
- }
14
-
15
- /**
16
- * Renders the MetaDataView component.
17
- */
18
- export const MetaDataView: FC<MetadataViewProps> = ({
19
- id,
20
- style,
21
- entries,
22
- tableOptions,
23
- compact,
24
- className,
25
- }) => {
26
- const baseId = "metadataview";
27
-
28
- // Configure options for
29
- tableOptions = tableOptions || "sm";
30
- const tblClz = (tableOptions || "").split(",").map((option) => {
31
- return `table-${option}`;
32
- });
33
-
34
- const coercedEntries = toNameValues(entries);
35
-
36
- const entryEls = (coercedEntries || []).map((entry, index) => {
37
- const id = `${baseId}-value-${index}`;
38
- return (
39
- <tr key={id}>
40
- <td
41
- className={clsx(
42
- styles.cell,
43
- styles.cellKey,
44
- "text-size-small",
45
- "text-style-label",
46
- )}
47
- >
48
- {entry.name}
49
- </td>
50
- <td className={clsx(styles.cell, styles.cellValue, "text-size-small")}>
51
- <RenderedContent id={id} entry={entry} />
52
- </td>
53
- </tr>
54
- );
55
- });
56
-
57
- return (
58
- <table
59
- id={id}
60
- className={clsx(
61
- "table",
62
- tblClz,
63
- styles.table,
64
- compact ? styles.compact : undefined,
65
- className,
66
- )}
67
- style={style}
68
- >
69
- <tbody>{entryEls}</tbody>
70
- </table>
71
- );
72
- };
73
-
74
- // entries can be either a Record<string, stringable>
75
- // or an array of record with name/value on way in
76
- // but coerce to array of records for order
77
- const toNameValues = (
78
- entries?:
79
- | Array<{ name: string; value: unknown }>
80
- | Record<string, unknown>
81
- | Array<unknown>,
82
- ): Array<{ name: string; value: unknown }> | undefined => {
83
- if (entries) {
84
- if (Array.isArray(entries)) {
85
- // filter arrays that don't contain the expected name value pairs
86
- const filtered = entries.filter((entry) => {
87
- if (entry && typeof entry === "object") {
88
- return "name" in entry && "value" in entry;
89
- }
90
- return false;
91
- });
92
- return filtered as Array<{ name: string; value: unknown }>;
93
- } else {
94
- return Object.entries(entries || {}).map(([key, value]) => {
95
- return { name: key, value };
96
- });
97
- }
98
- } else {
99
- return entries;
100
- }
101
- };
@@ -1,34 +0,0 @@
1
- import { ResultsMetric } from "./navbar/ResultsPanel";
2
-
3
- export const metricDisplayName = (metric: ResultsMetric): string => {
4
- let modifier = undefined;
5
- for (const metricModifier of metricModifiers) {
6
- modifier = metricModifier(metric);
7
- if (modifier) {
8
- break;
9
- }
10
- }
11
- const metricName = !modifier ? metric.name : `${metric.name}[${modifier}]`;
12
-
13
- return metricName;
14
- };
15
-
16
- type MetricModifier = (metric: ResultsMetric) => string | undefined;
17
-
18
- const clusterMetricModifier: MetricModifier = (
19
- metric: ResultsMetric,
20
- ): string | undefined => {
21
- if (metric.name !== "stderr") {
22
- return undefined;
23
- }
24
-
25
- const clusterValue = ((metric.params || {}) as Record<string, unknown>)[
26
- "cluster"
27
- ];
28
- if (clusterValue === undefined || typeof clusterValue !== "string") {
29
- return undefined;
30
- }
31
- return clusterValue;
32
- };
33
-
34
- const metricModifiers: MetricModifier[] = [clusterMetricModifier];
@@ -1,15 +0,0 @@
1
- .error {
2
- color: var(--bs-danger);
3
- margin-top: 0.2em;
4
- }
5
-
6
- .running {
7
- display: grid;
8
- grid-template-columns: max-content max-content;
9
- column-gap: 0.5em;
10
- margin-top: 0.3em;
11
- }
12
-
13
- .cancelled {
14
- margin-top: 0.2em;
15
- }
@@ -1,72 +0,0 @@
1
- import clsx from "clsx";
2
- import { FC } from "react";
3
- import { EvalLogHeader } from "../../client/api/types";
4
- import styles from "./EvalStatus.module.css";
5
- import { SidebarScoreView } from "./SidebarScoreView";
6
- import { SidebarScoresView } from "./SidebarScoresView";
7
-
8
- interface EvalStatusProps {
9
- logHeader?: EvalLogHeader;
10
- }
11
-
12
- export const EvalStatus: FC<EvalStatusProps> = ({ logHeader }) => {
13
- switch (logHeader?.status) {
14
- case "error":
15
- return <StatusError message="Error" />;
16
-
17
- case "cancelled":
18
- return <StatusCancelled message="Cancelled" />;
19
-
20
- case "started":
21
- return <StatusRunning message="Running" />;
22
-
23
- default:
24
- if (logHeader?.results?.scores && logHeader.results?.scores.length > 0) {
25
- if (logHeader.results.scores.length === 1) {
26
- return <SidebarScoreView scorer={logHeader.results.scores[0]} />;
27
- } else {
28
- return <SidebarScoresView scores={logHeader.results.scores} />;
29
- }
30
- } else {
31
- return null;
32
- }
33
- }
34
- };
35
-
36
- interface StatusProps {
37
- message: string;
38
- }
39
-
40
- const StatusCancelled: FC<StatusProps> = ({ message }) => {
41
- return (
42
- <div
43
- className={clsx(
44
- "text-style-secondary",
45
- "text-style-label",
46
- "text-size-small",
47
- styles.cancelled,
48
- )}
49
- >
50
- {message}
51
- </div>
52
- );
53
- };
54
-
55
- const StatusRunning: FC<StatusProps> = ({ message }) => {
56
- return (
57
- <div
58
- className={clsx(
59
- "text-style-secondary",
60
- "text-style-label",
61
- "text-size-small",
62
- styles.running,
63
- )}
64
- >
65
- <div>{message}</div>
66
- </div>
67
- );
68
- };
69
-
70
- const StatusError: FC<StatusProps> = ({ message }) => {
71
- return <div className={clsx(styles.error, "text-size-small")}>{message}</div>;
72
- };
@@ -1,16 +0,0 @@
1
- .dirname {
2
- overflow: hidden;
3
- white-space: nowrap;
4
- text-overflow: ellipsis;
5
- }
6
-
7
- .directoryLink {
8
- color: inherit;
9
- text-decoration: none;
10
- cursor: pointer;
11
- }
12
-
13
- .directoryLink:hover {
14
- color: var(--bs-primary);
15
- text-decoration: none;
16
- }
@@ -1,70 +0,0 @@
1
- import clsx from "clsx";
2
- import { FC, useCallback } from "react";
3
- import { Link } from "react-router-dom";
4
- import { useStore } from "../../state/store";
5
- import styles from "./LogDirectoryTitleView.module.css";
6
-
7
- interface LogDirectoryTitleViewProps {
8
- log_dir?: string;
9
- }
10
-
11
- export const LogDirectoryTitleView: FC<LogDirectoryTitleViewProps> = ({
12
- log_dir,
13
- }) => {
14
- const offCanvas = useStore((state) => state.app.offcanvas);
15
- const setOffCanvas = useStore((state) => state.appActions.setOffcanvas);
16
-
17
- const handleClick = useCallback(() => {
18
- // Close the sidebar when clicking the directory link on mobile
19
- if (offCanvas) {
20
- setOffCanvas(false);
21
- }
22
- }, [offCanvas, setOffCanvas]);
23
- if (log_dir) {
24
- const displayDir = prettyDir(log_dir);
25
- return (
26
- <Link to="/logs" className={styles.directoryLink} onClick={handleClick}>
27
- <div style={{ display: "flex", flexDirection: "column" }}>
28
- <span
29
- className={clsx(
30
- "text-style-secondary",
31
- "text-style-label",
32
- "text-size-small",
33
- )}
34
- >
35
- Log Directory
36
- </span>
37
- <span
38
- title={displayDir}
39
- className={clsx("text-size-base", styles.dirname)}
40
- >
41
- {offCanvas ? displayDir : ""}
42
- </span>
43
- </div>
44
- </Link>
45
- );
46
- } else {
47
- return (
48
- <Link to="/logs" className={styles.directoryLink} onClick={handleClick}>
49
- <span className={clsx("text-size-title")}>
50
- {offCanvas ? "Log History" : ""}
51
- </span>
52
- </Link>
53
- );
54
- }
55
- };
56
-
57
- const prettyDir = (path: string): string => {
58
- try {
59
- // Try to create a new URL object
60
- let url = new URL(path);
61
-
62
- if (url.protocol === "file:") {
63
- return url.pathname;
64
- } else {
65
- return path;
66
- }
67
- } catch {
68
- return path;
69
- }
70
- };
@@ -1,77 +0,0 @@
1
- .sidebar {
2
- position: fixed;
3
- left: 0;
4
- top: 0;
5
- width: var(--sidebar-width);
6
- height: 100%;
7
- background-color: #fff;
8
- border-right: 1px solid var(--bs-light-border-subtle);
9
- display: flex;
10
- flex-direction: column;
11
- z-index: 9999; /* Sit above main content */
12
- transition: transform 0.3s ease-in-out;
13
- }
14
-
15
- .sidebarClosed {
16
- transform: translateX(-100%);
17
- }
18
-
19
- .sidebarOpen {
20
- transform: translateX(0);
21
- }
22
-
23
- .header {
24
- display: grid;
25
- grid-template-columns: minmax(0, 1fr) auto;
26
- column-gap: 0.2rem;
27
- align-items: center;
28
- opacity: 0.7;
29
- position: sticky;
30
- top: 0;
31
- width: var(--sidebar-width);
32
- border-bottom: 1px solid var(--bs-light-border-subtle);
33
- padding: 0.5rem 0 0.5rem 1rem;
34
- height: 3.6em;
35
- background-color: #fff;
36
- z-index: 10;
37
- }
38
-
39
- .toggle {
40
- padding: 0.1rem;
41
- align-self: end;
42
- width: 40px;
43
- flex: 0 0 auto;
44
- }
45
-
46
- .progress {
47
- z-index: 3;
48
- }
49
-
50
- .list {
51
- flex-grow: 1;
52
- overflow-y: auto;
53
- }
54
-
55
- .backdrop {
56
- position: fixed;
57
- inset: 0;
58
- background-color: var(--inspect-glass-color);
59
- opacity: var(--inspect-glass-opacity);
60
- z-index: 9998;
61
- }
62
-
63
- .active {
64
- background-color: var(--bs-secondary-bg-subtle);
65
- }
66
-
67
- .item {
68
- cursor: pointer;
69
- padding: 0;
70
- }
71
-
72
- .logLink {
73
- display: block;
74
- padding: 0.5rem 1rem;
75
- color: inherit;
76
- text-decoration: none;
77
- }
@@ -1,119 +0,0 @@
1
- import clsx from "clsx";
2
- import { FC, useCallback, useEffect, useRef } from "react";
3
- import { Link } from "react-router-dom";
4
- import { Fragment } from "react/jsx-runtime";
5
- import { EvalLogHeader } from "../../client/api/types";
6
- import { ProgressBar } from "../../components/ProgressBar";
7
- import { useStatefulScrollPosition } from "../../state/scrolling";
8
- import { useStore } from "../../state/store";
9
- import { ApplicationIcons } from "../appearance/icons";
10
- import { logUrl } from "../routing/url";
11
- import { LogDirectoryTitleView } from "./LogDirectoryTitleView";
12
- import styles from "./Sidebar.module.css";
13
- import { SidebarLogEntry } from "./SidebarLogEntry";
14
-
15
- interface SidebarProps {
16
- logHeaders: Record<string, EvalLogHeader>;
17
- loading: boolean;
18
- selectedIndex: number;
19
- onSelectedIndexChanged: (index: number) => void;
20
- }
21
-
22
- export const Sidebar: FC<SidebarProps> = ({
23
- logHeaders,
24
- loading,
25
- selectedIndex,
26
- onSelectedIndexChanged,
27
- }) => {
28
- const logs = useStore((state) => state.logs.logs);
29
- const setOffCanvas = useStore((state) => state.appActions.setOffcanvas);
30
- const offCanvas = useStore((state) => state.app.offcanvas);
31
- const handleToggle = useCallback(() => {
32
- setOffCanvas(!offCanvas);
33
- }, [offCanvas, setOffCanvas]);
34
-
35
- const sidebarContentsRef = useRef(null);
36
- useStatefulScrollPosition(sidebarContentsRef, "sidebar-contents", 1000);
37
-
38
- // Scroll the selected log into view when it changes
39
- const itemRefs = useRef<{ [index: number]: HTMLLIElement | null }>({});
40
-
41
- useEffect(() => {
42
- if (itemRefs.current[selectedIndex]) {
43
- itemRefs.current[selectedIndex]?.scrollIntoView({
44
- behavior: "smooth",
45
- block: "nearest",
46
- });
47
- }
48
- }, [selectedIndex]);
49
-
50
- // No longer need the click handler as we're using Links now
51
-
52
- return (
53
- <Fragment>
54
- {/* Optional backdrop for small screens, appears only when offcanvas is open */}
55
- {offCanvas && <div className={styles.backdrop} onClick={handleToggle} />}
56
-
57
- <div
58
- className={clsx(
59
- styles.sidebar,
60
- offCanvas ? styles.sidebarOpen : styles.sidebarClosed,
61
- )}
62
- >
63
- <div className={styles.header}>
64
- <LogDirectoryTitleView log_dir={logs.log_dir} />
65
- <button
66
- onClick={handleToggle}
67
- className={clsx("btn", styles.toggle)}
68
- type="button"
69
- aria-label="Close sidebar"
70
- >
71
- <i className={ApplicationIcons.close}></i>
72
- </button>
73
- </div>
74
-
75
- <div className={styles.progress}>
76
- <ProgressBar animating={loading} />
77
- </div>
78
-
79
- <ul
80
- ref={sidebarContentsRef}
81
- className={clsx("list-group", styles.list)}
82
- >
83
- {logs.files.map((file, index) => {
84
- const logHeader = logHeaders[file.name];
85
- return (
86
- <li
87
- key={file.name}
88
- ref={(el) => {
89
- itemRefs.current[index] = el;
90
- }}
91
- className={clsx(
92
- "list-group-item",
93
- "list-group-item-action",
94
- styles.item,
95
- selectedIndex === index ? styles.active : undefined,
96
- )}
97
- data-index={index}
98
- >
99
- <Link
100
- to={logUrl(file.name, logs.log_dir)}
101
- className={styles.logLink}
102
- onClick={() => {
103
- // Also update the current index in state
104
- onSelectedIndexChanged(index);
105
- }}
106
- >
107
- <SidebarLogEntry
108
- logHeader={logHeader}
109
- task={file.task || "unknown task"}
110
- />
111
- </Link>
112
- </li>
113
- );
114
- })}
115
- </ul>
116
- </div>
117
- </Fragment>
118
- );
119
- };
@@ -1,29 +0,0 @@
1
- .entry {
2
- display: flex;
3
- flex-direction: row;
4
- justify-content: space-between;
5
- }
6
-
7
- .title {
8
- overflow: hidden;
9
- min-width: 33%;
10
- }
11
-
12
- .task {
13
- white-space: nowrap;
14
- overflow: hidden;
15
- text-overflow: ellipsis;
16
- }
17
-
18
- .params {
19
- margin-top: 1em;
20
- }
21
-
22
- .scores {
23
- width: 100%;
24
- display: grid;
25
- grid-template-columns: minmax(auto, 1fr) minmax(1fr, 1fr);
26
- column-gap: 1rem;
27
- justify-content: space-between;
28
- margin-top: 0em;
29
- }
@@ -1,96 +0,0 @@
1
- import clsx from "clsx";
2
- import { FC, Fragment } from "react";
3
- import { EvalLogHeader } from "../../client/api/types";
4
- import { kModelNone } from "../../constants";
5
- import { EvalStatus } from "./EvalStatus";
6
- import styles from "./SidebarLogEntry.module.css";
7
-
8
- interface SidebarLogEntryProps {
9
- logHeader?: EvalLogHeader;
10
- task: string;
11
- }
12
-
13
- export const SidebarLogEntry: FC<SidebarLogEntryProps> = ({
14
- logHeader,
15
- task,
16
- }) => {
17
- const hyperparameters: Record<string, unknown> = {
18
- ...(logHeader?.plan?.config || {}),
19
- ...(logHeader?.eval?.task_args || {}),
20
- };
21
-
22
- const model = logHeader?.eval?.model;
23
- const datasetName = logHeader?.eval?.dataset.name;
24
-
25
- const uniqScorers = new Set();
26
- logHeader?.results?.scores?.forEach((scorer) => {
27
- uniqScorers.add(scorer.name);
28
- });
29
- const scorerNames = Array.from(uniqScorers).join(",");
30
-
31
- const scorerLabel =
32
- Object.keys(logHeader?.results?.scores || {}).length === 1
33
- ? "scorer"
34
- : "scorers";
35
-
36
- const completed = logHeader?.stats?.completed_at;
37
- const time = completed ? new Date(completed) : undefined;
38
- const timeStr = time
39
- ? `${time.toDateString()}
40
- ${time.toLocaleTimeString([], {
41
- hour: "2-digit",
42
- minute: "2-digit",
43
- })}`
44
- : "";
45
-
46
- return (
47
- <Fragment>
48
- <div className={styles.entry}>
49
- <div className={styles.title}>
50
- <div className={clsx(styles.task, "text-size-title-secondary")}>
51
- {logHeader?.eval?.task || task}
52
- </div>
53
- <small className={clsx("mb-1", "text-size-small")}>{timeStr}</small>
54
-
55
- {model && model !== kModelNone ? (
56
- <div>
57
- <small className={clsx("mb-1", "text-size-small")}>{model}</small>
58
- </div>
59
- ) : (
60
- ""
61
- )}
62
- </div>
63
- <EvalStatus logHeader={logHeader} />
64
- </div>
65
- <div className={clsx(styles.params, "three-line-clamp")}>
66
- <small className={"mb-1"}>
67
- {hyperparameters
68
- ? Object.keys(hyperparameters)
69
- .map((key) => {
70
- const val = hyperparameters[key];
71
- if (Array.isArray(val) || typeof val === "object") {
72
- return `${key}: ${JSON.stringify(val)}`;
73
- } else {
74
- return `${key}: ${val}`;
75
- }
76
- })
77
- .join(", ")
78
- : ""}
79
- </small>
80
- </div>
81
- {(logHeader?.eval?.dataset || logHeader?.results?.scores) &&
82
- logHeader?.status === "success" ? (
83
- <div
84
- className={clsx("text-truncate", "text-size-small", styles.scores)}
85
- >
86
- <div>dataset: {datasetName || "(samples)"}</div>
87
- <div className={clsx("text-truncate", styles.scoreInfo)}>
88
- {scorerLabel}: {scorerNames || "(none)"}
89
- </div>
90
- </div>
91
- ) : (
92
- ""
93
- )}
94
- </Fragment>
95
- );
96
- };
@@ -1,23 +0,0 @@
1
- .container {
2
- display: flex;
3
- flex-direction: row;
4
- flex-wrap: wrap;
5
- justify-content: flex-end;
6
- }
7
-
8
- .metric {
9
- display: flex;
10
- flex-direction: column;
11
- align-items: flex-end;
12
- margin-left: 1em;
13
- margin-bottom: 0.4em;
14
- margin-top: 0.5rem;
15
- }
16
-
17
- .metricName {
18
- margin-bottom: -0.3em;
19
- }
20
-
21
- .metricReducer {
22
- margin-bottom: -0.2rem;
23
- }
@@ -1,44 +0,0 @@
1
- import clsx from "clsx";
2
- import { EvalScore } from "../../@types/log";
3
- import { formatPrettyDecimal } from "../../utils/format";
4
-
5
- import { FC } from "react";
6
- import { metricDisplayName } from "../log-view/utils";
7
- import styles from "./SidebarScoreView.module.css";
8
- interface SidebarScoreProps {
9
- scorer: EvalScore;
10
- }
11
-
12
- export const SidebarScoreView: FC<SidebarScoreProps> = ({ scorer }) => {
13
- const showReducer = !!scorer.reducer;
14
- return (
15
- <div className={styles.container}>
16
- {Object.keys(scorer.metrics).map((metric) => {
17
- return (
18
- <div className={styles.metric} key={metric}>
19
- <div
20
- className={clsx(
21
- "text-style-secondary",
22
- "text-style-label",
23
- "text-size-small",
24
- styles.metricName,
25
- )}
26
- >
27
- {metricDisplayName(scorer.metrics[metric])}
28
- </div>
29
- {showReducer ? (
30
- <div className={clsx("text-size-small", styles.metricReducer)}>
31
- {scorer.reducer || "default"}
32
- </div>
33
- ) : (
34
- ""
35
- )}
36
- <div className={"text-size-title-secondary"}>
37
- {formatPrettyDecimal(scorer.metrics[metric].value)}
38
- </div>
39
- </div>
40
- );
41
- })}
42
- </div>
43
- );
44
- };