inspect-ai 0.3.108__py3-none-any.whl → 0.3.110__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 (141) hide show
  1. inspect_ai/_eval/task/log.py +1 -1
  2. inspect_ai/_eval/task/run.py +7 -3
  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/providers.py +2 -2
  103. inspect_ai/model/_providers/vertex.py +3 -0
  104. inspect_ai/tool/_mcp/_mcp.py +6 -1
  105. inspect_ai/tool/_mcp/sampling.py +8 -1
  106. inspect_ai/tool/_tools/_bash_session.py +3 -6
  107. inspect_ai/tool/_tools/_web_browser/_web_browser.py +3 -8
  108. inspect_ai/util/_anyio.py +12 -3
  109. {inspect_ai-0.3.108.dist-info → inspect_ai-0.3.110.dist-info}/METADATA +2 -2
  110. {inspect_ai-0.3.108.dist-info → inspect_ai-0.3.110.dist-info}/RECORD +124 -94
  111. inspect_ai/_util/datetime.py +0 -10
  112. inspect_ai/_view/www/src/app/content/MetaDataView.module.css +0 -35
  113. inspect_ai/_view/www/src/app/content/MetaDataView.tsx +0 -101
  114. inspect_ai/_view/www/src/app/log-view/utils.ts +0 -34
  115. inspect_ai/_view/www/src/app/sidebar/EvalStatus.module.css +0 -15
  116. inspect_ai/_view/www/src/app/sidebar/EvalStatus.tsx +0 -72
  117. inspect_ai/_view/www/src/app/sidebar/LogDirectoryTitleView.module.css +0 -16
  118. inspect_ai/_view/www/src/app/sidebar/LogDirectoryTitleView.tsx +0 -70
  119. inspect_ai/_view/www/src/app/sidebar/Sidebar.module.css +0 -77
  120. inspect_ai/_view/www/src/app/sidebar/Sidebar.tsx +0 -119
  121. inspect_ai/_view/www/src/app/sidebar/SidebarLogEntry.module.css +0 -29
  122. inspect_ai/_view/www/src/app/sidebar/SidebarLogEntry.tsx +0 -96
  123. inspect_ai/_view/www/src/app/sidebar/SidebarScoreView.module.css +0 -23
  124. inspect_ai/_view/www/src/app/sidebar/SidebarScoreView.tsx +0 -44
  125. inspect_ai/_view/www/src/app/sidebar/SidebarScoresView.module.css +0 -35
  126. inspect_ai/_view/www/src/app/sidebar/SidebarScoresView.tsx +0 -63
  127. inspect_ai/_view/www/src/state/logsPolling.ts +0 -118
  128. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ModelRolesView.module.css +0 -0
  129. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ModelRolesView.tsx +0 -0
  130. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ResultsPanel.module.css +0 -0
  131. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/RunningStatusPanel.module.css +0 -0
  132. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/RunningStatusPanel.tsx +0 -0
  133. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/ScoreGrid.module.css +0 -0
  134. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/SecondaryBar.module.css +0 -0
  135. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/StatusPanel.module.css +0 -0
  136. /inspect_ai/_view/www/src/app/log-view/{navbar → title-view}/StatusPanel.tsx +0 -0
  137. /inspect_ai/_view/www/src/app/log-view/{navbar/Navbar.module.css → title-view/TitleView.module.css} +0 -0
  138. {inspect_ai-0.3.108.dist-info → inspect_ai-0.3.110.dist-info}/WHEEL +0 -0
  139. {inspect_ai-0.3.108.dist-info → inspect_ai-0.3.110.dist-info}/entry_points.txt +0 -0
  140. {inspect_ai-0.3.108.dist-info → inspect_ai-0.3.110.dist-info}/licenses/LICENSE +0 -0
  141. {inspect_ai-0.3.108.dist-info → inspect_ai-0.3.110.dist-info}/top_level.txt +0 -0
@@ -63,10 +63,11 @@
63
63
  "@codemirror/state": "^6.5.2",
64
64
  "@lezer/highlight": "^1.2.1",
65
65
  "@mui/material": "^7.1.0",
66
- "@mui/x-tree-view": "^8.3.0",
66
+ "@mui/x-tree-view": "^8.3.1",
67
67
  "@popperjs/core": "^2.11.8",
68
+ "@tanstack/react-table": "^8.21.3",
68
69
  "ansi-output": "^0.0.9",
69
- "asciinema-player": "^3.9.0",
70
+ "asciinema-player": "^3.10.0",
70
71
  "bootstrap": "^5.3.6",
71
72
  "bootstrap-icons": "^1.12.1",
72
73
  "clipboard": "^2.0.11",
@@ -1,8 +1,8 @@
1
- /* eslint-disable */
2
- /**
3
- * This file was automatically generated by json-schema-to-typescript.
4
- * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
5
- * and run json-schema-to-typescript to regenerate this file.
1
+ /*
2
+ * This file is automatically generated by schema.py
3
+ * DO NOT MODIFY IT BY HAND.
4
+ * To regenerate, run: python -m ../schema.py from within the
5
+ * src/inspect_ai/_view/www directory.
6
6
  */
7
7
 
8
8
  export type Version = number;
@@ -53,7 +53,15 @@ body:not([class^="vscode-"]) button {
53
53
  display: grid;
54
54
  height: 100vh;
55
55
  overflow-y: hidden;
56
- grid-template-rows: max-content max-content 1fr;
56
+ grid-template-rows: max-content max-content max-content 1fr;
57
+ }
58
+
59
+ a {
60
+ color: var(--bs-link-color);
61
+ }
62
+
63
+ a:hover {
64
+ color: var(--bs-link-hover-color);
57
65
  }
58
66
 
59
67
  .modal {
@@ -64,7 +72,7 @@ body:not([class^="vscode-"]) button {
64
72
  --bs-backdrop-opacity: 0.4;
65
73
  }
66
74
 
67
- body[class^="vscode-"] .app-main-grid {
75
+ .app-main-grid.single-file-mode {
68
76
  grid-template-rows: max-content max-content 1fr;
69
77
  }
70
78
 
@@ -135,6 +143,7 @@ body[class^="vscode-"] {
135
143
  --bs-border-radius: 0;
136
144
  --bs-border-radius-lg: 0;
137
145
  --bs-body-bg: var(--vscode-editor-background);
146
+ --bs-secondary-bg-subtle: var(--vscode-editorHoverWidget-background);
138
147
  --bs-card-bg: var(--vscode-editor-background);
139
148
  --bs-table-bg: var(--vscode-editor-background);
140
149
  --bs-light-bg-subtle: var(--vscode-sideBar-background);
@@ -150,12 +159,15 @@ body[class^="vscode-"] {
150
159
  --bs-btn-bg: var(--vscode-peekViewTitle-background);
151
160
  --bs-primary: var(--vscode-banner-iconForeground);
152
161
  --bs-nav-pills-link-active-bg: var(--vscode-banner-iconForeground);
162
+ --bs-link-color: var(--vscode-textLink-foreground);
163
+ --bs-link-hover-color: var(--vscode-textLink-activeForeground);
153
164
  --bs-secondary: var(--vscode-breadcrumb-foreground);
154
165
  --bs-secondary-bg: var(--vscode-list-inactiveSelectionBackground);
155
166
  --bs-border-color: var(--vscode-editorGroup-border);
156
167
  --bs-card-border-color: var(--vscode-editorGroup-border);
157
168
  --bs-warning-bg-subtle: var(--vscode-inputValidation-warningBackground);
158
169
  --bs-warning-text-emphasis: var(--vscode-input-foreground);
170
+ --bs-breadcrumb-divider-color: var(--vscode-foreground);
159
171
  --inspect-find-background: var(--vscode-editorWidget-background);
160
172
  --inspect-find-foreground: var(--vscode-editorWidget-foreground);
161
173
  --inspect-input-background: var(--vscode-input-background);
@@ -328,6 +340,10 @@ body[class^="vscode-"] .sidebar .list-group {
328
340
  --bs-list-group-active-color: var(--vscode-sideBarSectionHeader-foreground);
329
341
  }
330
342
 
343
+ body[class^="vscode-"] .breadcrumb-item {
344
+ --bs-breadcrumb-divider-color: var(--vscode-foreground);
345
+ }
346
+
331
347
  body[class^="vscode-"] div.ap-control-bar .ap-fullscreen-button {
332
348
  display: none;
333
349
  }
@@ -1025,11 +1041,11 @@ ul.jsondiffpatch-textdiff {
1025
1041
  /* prism-custom.css */
1026
1042
  code[class*="language-"],
1027
1043
  pre[class*="language-"] {
1028
- font-size: 0.8rem !important;
1044
+ font-size: 0.7rem !important;
1029
1045
  }
1030
1046
 
1031
1047
  .token {
1032
- font-size: 0.8rem !important;
1048
+ font-size: 0.7rem !important;
1033
1049
  }
1034
1050
 
1035
1051
  /* PrismJS 1.29.0 https://prismjs.com/download.html#themes=prism-dark&languages=markup+css+clike+javascript+bash+python */
@@ -1140,3 +1156,54 @@ pre[class*="language-"] {
1140
1156
  color: red;
1141
1157
  }
1142
1158
  /* END PrismJS */
1159
+
1160
+ /* SVG Icon styles - following Bootstrap Icons pattern */
1161
+ .inspect-icon-16::before {
1162
+ content: "";
1163
+ width: 1em;
1164
+ height: 1em;
1165
+ display: inline-block;
1166
+ vertical-align: middle;
1167
+ mask: url("../img/inspect-16.svg") no-repeat center / contain;
1168
+ -webkit-mask: url("../img/inspect-16.svg") no-repeat center / contain;
1169
+ }
1170
+
1171
+ .inspect-icon-back::before {
1172
+ content: "";
1173
+ width: 1em;
1174
+ height: 1em;
1175
+ display: inline-block;
1176
+ vertical-align: middle;
1177
+ mask: url("../img/inspect-back.svg") no-repeat center / contain;
1178
+ -webkit-mask: url("../img/inspect-back.svg") no-repeat center / contain;
1179
+ }
1180
+
1181
+ .inspect-icon-forward::before {
1182
+ content: "";
1183
+ width: 1em;
1184
+ height: 1em;
1185
+ display: inline-block;
1186
+ vertical-align: middle;
1187
+ mask: url("../img/inspect-forward.svg") no-repeat center / contain;
1188
+ -webkit-mask: url("../img/inspect-forward.svg") no-repeat center / contain;
1189
+ }
1190
+
1191
+ .inspect-icon-file::before {
1192
+ content: "";
1193
+ width: 1em;
1194
+ height: 1em;
1195
+ display: inline-block;
1196
+ vertical-align: middle;
1197
+ mask: url("../img/inspect-file.svg") no-repeat center / contain;
1198
+ -webkit-mask: url("../img/inspect-file.svg") no-repeat center / contain;
1199
+ }
1200
+
1201
+ .inspect-icon-home::before {
1202
+ content: "";
1203
+ width: 1em;
1204
+ height: 1em;
1205
+ display: inline-block;
1206
+ vertical-align: middle;
1207
+ mask: url("../img/inspect-home.svg") no-repeat center / contain;
1208
+ -webkit-mask: url("../img/inspect-home.svg") no-repeat center / contain;
1209
+ }
@@ -45,6 +45,10 @@ export const App: FC<AppProps> = ({ api }) => {
45
45
  const loadLog = useStore((state) => state.logActions.loadLog);
46
46
  const pollLog = useStore((state) => state.logActions.pollLog);
47
47
 
48
+ const setSingleFileMode = useStore(
49
+ (state) => state.appActions.setSingleFileMode,
50
+ );
51
+
48
52
  // Load a specific log
49
53
  useEffect(() => {
50
54
  const loadSpecificLog = async () => {
@@ -135,6 +139,7 @@ export const App: FC<AppProps> = ({ api }) => {
135
139
  if (embeddedState && !rehydrated) {
136
140
  const state = JSON5.parse(embeddedState.textContent || "");
137
141
  onMessage({ data: state });
142
+ setSingleFileMode(true);
138
143
  } else {
139
144
  // For non-route URL params support (legacy)
140
145
  const urlParams = new URLSearchParams(window.location.search);
@@ -151,11 +156,13 @@ export const App: FC<AppProps> = ({ api }) => {
151
156
  log_dir: "",
152
157
  files: [{ name: resolvedLogPath }],
153
158
  });
159
+ setSingleFileMode(true);
154
160
  } else {
155
161
  // If a log file was passed, select it
156
162
  const log_file = urlParams.get("log_file");
157
163
  if (log_file) {
158
164
  await selectLogFile(log_file);
165
+ setSingleFileMode(true);
159
166
  }
160
167
  // Else do nothing - RouteProvider will handle it
161
168
  }
@@ -23,6 +23,7 @@ export const ApplicationIcons = {
23
23
  down: "bi bi-arrow-down",
24
24
  up: "bi bi-arrow-up",
25
25
  },
26
+ cancelled: "bi bi-x-circle",
26
27
  caret: {
27
28
  right: "bi bi-caret-right",
28
29
  down: "bi bi-caret-down",
@@ -36,11 +37,12 @@ export const ApplicationIcons = {
36
37
  right: "bi bi-chevron-right",
37
38
  down: "bi bi-chevron-down",
38
39
  },
40
+ "clear-text": "bi bi-x-circle-fill",
41
+ close: "bi bi-x",
39
42
  collapse: {
40
43
  all: "bi bi-arrows-collapse",
41
44
  up: "bi bi-chevron-up",
42
45
  },
43
- close: "bi bi-x",
44
46
  config: "bi bi-gear",
45
47
  confirm: "bi bi-check",
46
48
  copy: "bi bi-copy",
@@ -48,12 +50,18 @@ export const ApplicationIcons = {
48
50
  return `bi bi-${epoch}-circle`;
49
51
  },
50
52
  error: "bi bi-exclamation-circle",
53
+ eval: "bi bi-info-circle-fill",
51
54
  "expand-all": "bi bi-arrows-expand",
52
55
  "expand-down": "bi bi-chevron-down",
56
+ file: "bi bi-file-code",
57
+ filter: "bi bi-funnel",
58
+ folder: "bi bi-folder",
53
59
  fork: "bi bi-signpost-split",
60
+ home: "bi bi-house",
54
61
  info: "bi bi-info-circle",
55
62
  input: "bi bi-terminal",
56
- inspect: "bi bi-gear",
63
+ inspect: "ii inspect-icon-16",
64
+ inspectFile: "ii inspect-icon-file",
57
65
  json: "bi bi-filetype-json",
58
66
  limits: {
59
67
  messages: "bi bi-chat-right-text",
@@ -73,6 +81,13 @@ export const ApplicationIcons = {
73
81
  "toggle-right": "bi bi-chevron-right",
74
82
  more: "bi bi-zoom-in",
75
83
  "multiple-choice": "bi bi-card-list",
84
+ navbar: {
85
+ home: "ii inspect-icon-home",
86
+ back: "ii inspect-icon-back",
87
+ forward: "ii inspect-icon-forward",
88
+ inspectLogo: "ii inspect-icon-16",
89
+ },
90
+
76
91
  next: "bi bi-chevron-right",
77
92
  noSamples: "bi bi-ban",
78
93
  play: "bi bi-play-fill",
@@ -103,6 +118,7 @@ export const ApplicationIcons = {
103
118
  },
104
119
  step: "bi bi-fast-forward-btn",
105
120
  subtask: "bi bi-subtract",
121
+ success: "bi bi-check-circle",
106
122
  transcript: "bi bi-list-columns-reverse",
107
123
  tree: {
108
124
  open: "bi bi-caret-down-fill",
@@ -8,7 +8,7 @@ import { formatNumber } from "../../utils/format";
8
8
  import { isJson } from "../../utils/json";
9
9
  import { ApplicationIcons } from "../appearance/icons";
10
10
  import { ChatMessageRenderer } from "../samples/chat/ChatMessageRenderer";
11
- import { MetaDataView } from "./MetaDataView";
11
+ import { MetaDataGrid } from "./MetaDataGrid";
12
12
  import styles from "./RenderedContent.module.css";
13
13
  import { Buckets, ContentRenderer, RenderOptions } from "./types";
14
14
 
@@ -190,12 +190,11 @@ const contentRenderers: (
190
190
  const arrayRendered = renderObject ? (
191
191
  renderObject(arrayMap)
192
192
  ) : (
193
- <MetaDataView
193
+ <MetaDataGrid
194
194
  id={id}
195
195
  className={"font-size-small"}
196
196
  entries={arrayMap}
197
- tableOptions="borderless,sm"
198
- compact={true}
197
+ plain={true}
199
198
  />
200
199
  );
201
200
  return { rendered: arrayRendered };
@@ -283,12 +282,11 @@ const contentRenderers: (
283
282
  } else {
284
283
  return {
285
284
  rendered: (
286
- <MetaDataView
285
+ <MetaDataGrid
287
286
  id={id}
288
- className={"text-size-smaller"}
289
- entries={entry.value}
290
- tableOptions="borderless,sm"
291
- compact
287
+ className={"font-size-small"}
288
+ entries={entry.value as Record<string, unknown>}
289
+ plain={true}
292
290
  />
293
291
  ),
294
292
  };
@@ -0,0 +1,18 @@
1
+ import { EvalLogHeader, LogFile } from "../../client/api/types";
2
+
3
+ export interface LogItem {
4
+ id: string;
5
+ name: string;
6
+ url: string;
7
+ }
8
+
9
+ export interface FolderLogItem extends LogItem {
10
+ type: "folder";
11
+ itemCount: number;
12
+ }
13
+
14
+ export interface FileLogItem extends LogItem {
15
+ type: "file";
16
+ logFile: LogFile;
17
+ header?: EvalLogHeader;
18
+ }
@@ -0,0 +1,55 @@
1
+ .footer {
2
+ border-top: solid var(--bs-light-border-subtle) 1px;
3
+ background: var(--bs-light-bg-subtle);
4
+ display: grid;
5
+ grid-template-columns: 0.5fr 1fr 0.5fr;
6
+ justify-content: space-between;
7
+
8
+ padding: 0.2em 1em;
9
+ }
10
+
11
+ .spinnerContainer {
12
+ display: grid;
13
+ grid-template-columns: max-content max-content;
14
+ column-gap: 0.3em;
15
+ padding-top: 0.2em;
16
+ }
17
+
18
+ .spinner {
19
+ height: 11px;
20
+ width: 11px;
21
+ color: var(--bs-secondary);
22
+ border-width: 1px;
23
+ }
24
+
25
+ .label {
26
+ margin-left: 0.1em;
27
+ margin-top: -3px;
28
+ }
29
+
30
+ .right {
31
+ display: grid;
32
+ grid-auto-columns: max-content;
33
+ grid-auto-flow: column;
34
+ justify-content: end;
35
+ align-items: center;
36
+ column-gap: 0.5em;
37
+ }
38
+
39
+ .left {
40
+ display: grid;
41
+ grid-auto-columns: max-content;
42
+ grid-auto-flow: column;
43
+ justify-content: start;
44
+ align-items: center;
45
+ column-gap: 0.5em;
46
+ }
47
+
48
+ .center {
49
+ display: grid;
50
+ grid-auto-columns: max-content;
51
+ grid-auto-flow: column;
52
+ justify-content: center;
53
+ align-items: center;
54
+ column-gap: 0.5em;
55
+ }
@@ -0,0 +1,67 @@
1
+ interface LogListFooterProps {
2
+ logDir: string;
3
+ itemCount: number;
4
+ progressText?: string;
5
+ }
6
+
7
+ import clsx from "clsx";
8
+ import { FC } from "react";
9
+ import { useLogsListing, usePagination } from "../../state/hooks";
10
+ import styles from "./LogListFooter.module.css";
11
+ import { LogPager } from "./LogPager";
12
+ import { kDefaultPageSize, kLogsPaginationId } from "./LogsPanel";
13
+
14
+ export const LogListFooter: FC<LogListFooterProps> = ({
15
+ itemCount,
16
+ progressText,
17
+ }) => {
18
+ // Get pagination info from the store
19
+ const { page, itemsPerPage } = usePagination(
20
+ kLogsPaginationId,
21
+ kDefaultPageSize,
22
+ );
23
+
24
+ // Get filtered count from the store
25
+ const { filteredCount } = useLogsListing();
26
+ const effectiveItemCount = filteredCount ?? itemCount;
27
+
28
+ const currentPage = page || 0;
29
+ const pageItemCount = Math.min(
30
+ itemsPerPage,
31
+ effectiveItemCount - currentPage * itemsPerPage,
32
+ );
33
+ const startItem = effectiveItemCount > 0 ? currentPage * itemsPerPage + 1 : 0;
34
+ const endItem = startItem + pageItemCount - 1;
35
+
36
+ return (
37
+ <div className={clsx("text-size-smaller", styles.footer)}>
38
+ <div className={clsx(styles.left)}>
39
+ {progressText ? (
40
+ <div className={clsx(styles.spinnerContainer)}>
41
+ <div
42
+ className={clsx("spinner-border", styles.spinner)}
43
+ role="status"
44
+ >
45
+ <span className={clsx("visually-hidden")}>{progressText}...</span>
46
+ </div>
47
+ <div className={clsx("text-style-secondary", styles.label)}>
48
+ {progressText}...
49
+ </div>
50
+ </div>
51
+ ) : undefined}
52
+ </div>
53
+ <div className={clsx(styles.center)}>
54
+ <LogPager itemCount={effectiveItemCount} />
55
+ </div>
56
+ <div className={clsx(styles.right)}>
57
+ <div>
58
+ {effectiveItemCount === 0
59
+ ? ""
60
+ : filteredCount !== undefined && filteredCount !== itemCount
61
+ ? `${startItem} - ${endItem} / ${effectiveItemCount} (${itemCount} total)`
62
+ : `${startItem} - ${endItem} / ${effectiveItemCount}`}
63
+ </div>
64
+ </div>
65
+ </div>
66
+ );
67
+ };
@@ -0,0 +1,29 @@
1
+ .pager {
2
+ --bs-pagination-padding-x: 0.5em;
3
+ --bs-pagination-padding-y: 0.15em;
4
+ --bs-pagination-font-size: 0.8rem;
5
+ --bs-pagination-padding-x: 0.5em;
6
+ --bs-pagination-padding-y: 0;
7
+ --bs-pagination-border-radius: var(--bs-border-radius);
8
+ margin-bottom: 0;
9
+ }
10
+
11
+ .item:not(:global(.disabled)) {
12
+ cursor: pointer;
13
+ }
14
+
15
+ .item {
16
+ margin-left: 0.2em;
17
+ margin-right: 0.2em;
18
+ }
19
+
20
+ .item:first-child,
21
+ .item:last-child {
22
+ --bs-pagination-padding-x: 0.3em;
23
+ }
24
+
25
+ .item:first-child :global(.ii:before),
26
+ .item:last-child :global(.ii:before) {
27
+ margin-top: -2px;
28
+ font-size: 0.8em;
29
+ }
@@ -0,0 +1,134 @@
1
+ import clsx from "clsx";
2
+ import { FC } from "react";
3
+
4
+ import { usePagination } from "../../state/hooks";
5
+ import { ApplicationIcons } from "../appearance/icons";
6
+ import styles from "./LogPager.module.css";
7
+ import { kDefaultPageSize, kLogsPaginationId } from "./LogsPanel";
8
+
9
+ interface LogPagerProps {
10
+ itemCount: number;
11
+ }
12
+
13
+ export const LogPager: FC<LogPagerProps> = ({ itemCount }) => {
14
+ const { page, itemsPerPage, setPage } = usePagination(
15
+ kLogsPaginationId,
16
+ kDefaultPageSize,
17
+ );
18
+ const pageCount = Math.ceil(itemCount / itemsPerPage);
19
+ if (pageCount <= 1) {
20
+ return null;
21
+ }
22
+
23
+ const currentPage = page || 0;
24
+
25
+ const generatePaginationSegments = () => {
26
+ const segments: Array<{
27
+ type: "page" | "ellipsis";
28
+ page?: number;
29
+ key: string;
30
+ }> = [];
31
+
32
+ if (pageCount <= 5) {
33
+ // Show all pages if 5 or fewer
34
+ for (let i = 0; i < pageCount; i++) {
35
+ segments.push({ type: "page", page: i, key: `page-${i}` });
36
+ }
37
+ } else {
38
+ // There are more than 5 pages, use ellpsis to constrain the size
39
+
40
+ // first page
41
+ segments.push({ type: "page", page: 0, key: "page-0" });
42
+
43
+ // Determine the range around current page
44
+ const startPage = Math.max(1, currentPage - 1);
45
+ const endPage = Math.min(pageCount - 2, currentPage + 1);
46
+
47
+ // Add ellipsis before middle section if needed
48
+ if (startPage > 1) {
49
+ segments.push({ type: "ellipsis", key: "ellipsis-start" });
50
+ }
51
+
52
+ // Add middle section pages
53
+ for (let i = startPage; i <= endPage; i++) {
54
+ segments.push({ type: "page", page: i, key: `page-${i}` });
55
+ }
56
+
57
+ // Add ellipsis after middle section if needed
58
+ if (endPage < pageCount - 2) {
59
+ segments.push({ type: "ellipsis", key: "ellipsis-end" });
60
+ }
61
+
62
+ // last page
63
+ segments.push({
64
+ type: "page",
65
+ page: pageCount - 1,
66
+ key: `page-${pageCount - 1}`,
67
+ });
68
+ }
69
+
70
+ return segments;
71
+ };
72
+
73
+ const segments = generatePaginationSegments();
74
+
75
+ return (
76
+ <nav aria-label="Log Pagination">
77
+ <ul className={clsx("pagination", styles.pager)}>
78
+ <li className={clsx(currentPage === 0 ? "disabled" : "", styles.item)}>
79
+ <a
80
+ className={clsx("page-link")}
81
+ onClick={() => {
82
+ if (currentPage > 0) {
83
+ setPage(currentPage - 1);
84
+ }
85
+ }}
86
+ >
87
+ <i className={clsx(ApplicationIcons.navbar.back)} />
88
+ </a>
89
+ </li>
90
+
91
+ {segments.map((segment) => (
92
+ <li
93
+ key={segment.key}
94
+ className={clsx(
95
+ segment.type === "page" && segment.page === currentPage
96
+ ? "active"
97
+ : undefined,
98
+ segment.type === "ellipsis" ? "disabled" : undefined,
99
+ styles.item,
100
+ )}
101
+ >
102
+ <a
103
+ className={clsx("page-link")}
104
+ onClick={() => {
105
+ if (segment.type === "page" && segment.page !== undefined) {
106
+ setPage(segment.page);
107
+ }
108
+ }}
109
+ >
110
+ {segment.type === "page" ? segment.page! + 1 : "..."}
111
+ </a>
112
+ </li>
113
+ ))}
114
+ <li
115
+ className={clsx(
116
+ currentPage + 1 >= pageCount ? "disabled" : "",
117
+ styles.item,
118
+ )}
119
+ >
120
+ <a
121
+ className={clsx("page-link")}
122
+ onClick={() => {
123
+ if (currentPage < pageCount) {
124
+ setPage(currentPage + 1);
125
+ }
126
+ }}
127
+ >
128
+ <i className={clsx(ApplicationIcons.navbar.forward)} />
129
+ </a>
130
+ </li>
131
+ </ul>
132
+ </nav>
133
+ );
134
+ };
@@ -0,0 +1,5 @@
1
+ .filterInput {
2
+ font-size: 0.8em;
3
+ margin: 0em;
4
+ color: var(--bs-secondary);
5
+ }
@@ -0,0 +1,31 @@
1
+ import { FC, useCallback } from "react";
2
+
3
+ import clsx from "clsx";
4
+ import { TextInput } from "../../components/TextInput";
5
+ import { useLogsListing } from "../../state/hooks";
6
+ import { ApplicationIcons } from "../appearance/icons";
7
+ import styles from "./LogsFilterInput.module.css";
8
+
9
+ export interface LogsToolbarProps {}
10
+
11
+ export const LogsFilterInput: FC<LogsToolbarProps> = () => {
12
+ const { globalFilter, setGlobalFilter } = useLogsListing();
13
+ const debouncedUpdate = useCallback(
14
+ async (value: string) => {
15
+ setGlobalFilter(value);
16
+ },
17
+ [setGlobalFilter],
18
+ );
19
+
20
+ return (
21
+ <TextInput
22
+ icon={ApplicationIcons.filter}
23
+ value={globalFilter || ""}
24
+ onChange={(e) => {
25
+ debouncedUpdate(e.target.value);
26
+ }}
27
+ placeholder="Filter..."
28
+ className={clsx(styles.filterInput)}
29
+ />
30
+ );
31
+ };
@@ -0,0 +1,12 @@
1
+ .panel {
2
+ height: 100vh;
3
+ width: 100vw;
4
+ display: grid;
5
+ grid-template-rows: max-content max-content 1fr max-content;
6
+ }
7
+
8
+ .list {
9
+ overflow: hidden;
10
+ height: 100%;
11
+ min-height: 0;
12
+ }