inspect-ai 0.3.69__py3-none-any.whl → 0.3.71__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 (242) hide show
  1. inspect_ai/_cli/eval.py +27 -9
  2. inspect_ai/_display/core/display.py +2 -0
  3. inspect_ai/_display/core/footer.py +13 -3
  4. inspect_ai/_display/plain/display.py +6 -2
  5. inspect_ai/_display/rich/display.py +19 -6
  6. inspect_ai/_display/textual/app.py +9 -3
  7. inspect_ai/_display/textual/display.py +4 -0
  8. inspect_ai/_display/textual/widgets/samples.py +4 -10
  9. inspect_ai/_display/textual/widgets/transcript.py +35 -18
  10. inspect_ai/_eval/eval.py +14 -2
  11. inspect_ai/_eval/evalset.py +6 -1
  12. inspect_ai/_eval/run.py +6 -0
  13. inspect_ai/_eval/task/run.py +49 -23
  14. inspect_ai/_eval/task/task.py +26 -3
  15. inspect_ai/_util/content.py +20 -1
  16. inspect_ai/_util/interrupt.py +6 -0
  17. inspect_ai/_util/logger.py +19 -0
  18. inspect_ai/_util/rich.py +7 -8
  19. inspect_ai/_util/text.py +13 -0
  20. inspect_ai/_util/transcript.py +20 -6
  21. inspect_ai/_util/working.py +50 -0
  22. inspect_ai/_view/www/App.css +6 -0
  23. inspect_ai/_view/www/dist/assets/index.css +171 -99
  24. inspect_ai/_view/www/dist/assets/index.js +5972 -2770
  25. inspect_ai/_view/www/eslint.config.mjs +24 -1
  26. inspect_ai/_view/www/log-schema.json +619 -21
  27. inspect_ai/_view/www/package.json +8 -3
  28. inspect_ai/_view/www/src/App.tsx +2 -2
  29. inspect_ai/_view/www/src/appearance/icons.ts +3 -1
  30. inspect_ai/_view/www/src/components/AnsiDisplay.tsx +4 -3
  31. inspect_ai/_view/www/src/components/Card.tsx +9 -8
  32. inspect_ai/_view/www/src/components/DownloadButton.tsx +2 -1
  33. inspect_ai/_view/www/src/components/EmptyPanel.tsx +2 -2
  34. inspect_ai/_view/www/src/components/ErrorPanel.tsx +4 -3
  35. inspect_ai/_view/www/src/components/ExpandablePanel.tsx +13 -5
  36. inspect_ai/_view/www/src/components/FindBand.tsx +3 -3
  37. inspect_ai/_view/www/src/components/HumanBaselineView.tsx +3 -3
  38. inspect_ai/_view/www/src/components/LabeledValue.tsx +5 -4
  39. inspect_ai/_view/www/src/components/LargeModal.tsx +18 -13
  40. inspect_ai/_view/www/src/components/{LightboxCarousel.css → LightboxCarousel.module.css} +22 -18
  41. inspect_ai/_view/www/src/components/LightboxCarousel.tsx +36 -27
  42. inspect_ai/_view/www/src/components/MessageBand.tsx +2 -1
  43. inspect_ai/_view/www/src/components/NavPills.tsx +9 -8
  44. inspect_ai/_view/www/src/components/ProgressBar.tsx +2 -1
  45. inspect_ai/_view/www/src/components/TabSet.tsx +21 -15
  46. inspect_ai/_view/www/src/index.tsx +2 -2
  47. inspect_ai/_view/www/src/metadata/MetaDataGrid.tsx +11 -9
  48. inspect_ai/_view/www/src/metadata/MetaDataView.tsx +3 -2
  49. inspect_ai/_view/www/src/metadata/MetadataGrid.module.css +1 -0
  50. inspect_ai/_view/www/src/metadata/RenderedContent.tsx +16 -1
  51. inspect_ai/_view/www/src/plan/DatasetDetailView.tsx +3 -2
  52. inspect_ai/_view/www/src/plan/DetailStep.tsx +2 -1
  53. inspect_ai/_view/www/src/plan/PlanCard.tsx +2 -5
  54. inspect_ai/_view/www/src/plan/PlanDetailView.tsx +6 -9
  55. inspect_ai/_view/www/src/plan/ScorerDetailView.tsx +2 -1
  56. inspect_ai/_view/www/src/plan/SolverDetailView.tsx +3 -3
  57. inspect_ai/_view/www/src/samples/InlineSampleDisplay.tsx +2 -2
  58. inspect_ai/_view/www/src/samples/SampleDialog.tsx +3 -3
  59. inspect_ai/_view/www/src/samples/SampleDisplay.module.css +9 -1
  60. inspect_ai/_view/www/src/samples/SampleDisplay.tsx +30 -3
  61. inspect_ai/_view/www/src/samples/SampleSummaryView.module.css +4 -0
  62. inspect_ai/_view/www/src/samples/SampleSummaryView.tsx +25 -4
  63. inspect_ai/_view/www/src/samples/SamplesTools.tsx +2 -1
  64. inspect_ai/_view/www/src/samples/chat/ChatMessage.tsx +3 -19
  65. inspect_ai/_view/www/src/samples/chat/ChatMessageRenderer.tsx +2 -1
  66. inspect_ai/_view/www/src/samples/chat/ChatMessageRow.tsx +2 -1
  67. inspect_ai/_view/www/src/samples/chat/ChatView.tsx +2 -1
  68. inspect_ai/_view/www/src/samples/chat/ChatViewVirtualList.tsx +22 -7
  69. inspect_ai/_view/www/src/samples/chat/MessageContent.tsx +35 -6
  70. inspect_ai/_view/www/src/samples/chat/MessageContents.tsx +2 -2
  71. inspect_ai/_view/www/src/samples/chat/messages.ts +15 -2
  72. inspect_ai/_view/www/src/samples/chat/tools/ToolCallView.tsx +13 -4
  73. inspect_ai/_view/www/src/samples/chat/tools/ToolInput.module.css +2 -2
  74. inspect_ai/_view/www/src/samples/chat/tools/ToolInput.tsx +18 -19
  75. inspect_ai/_view/www/src/samples/chat/tools/ToolOutput.module.css +1 -1
  76. inspect_ai/_view/www/src/samples/chat/tools/ToolOutput.tsx +4 -3
  77. inspect_ai/_view/www/src/samples/chat/tools/ToolTitle.tsx +2 -2
  78. inspect_ai/_view/www/src/samples/error/FlatSampleErrorView.tsx +2 -3
  79. inspect_ai/_view/www/src/samples/error/SampleErrorView.tsx +3 -2
  80. inspect_ai/_view/www/src/samples/list/SampleFooter.tsx +2 -1
  81. inspect_ai/_view/www/src/samples/list/SampleHeader.tsx +2 -1
  82. inspect_ai/_view/www/src/samples/list/SampleList.tsx +57 -45
  83. inspect_ai/_view/www/src/samples/list/SampleRow.tsx +2 -1
  84. inspect_ai/_view/www/src/samples/list/SampleSeparator.tsx +2 -1
  85. inspect_ai/_view/www/src/samples/sample-tools/EpochFilter.tsx +2 -2
  86. inspect_ai/_view/www/src/samples/sample-tools/SelectScorer.tsx +4 -3
  87. inspect_ai/_view/www/src/samples/sample-tools/SortFilter.tsx +2 -5
  88. inspect_ai/_view/www/src/samples/sample-tools/sample-filter/SampleFilter.tsx +2 -2
  89. inspect_ai/_view/www/src/samples/scores/SampleScoreView.tsx +2 -1
  90. inspect_ai/_view/www/src/samples/scores/SampleScores.tsx +2 -2
  91. inspect_ai/_view/www/src/samples/transcript/ApprovalEventView.tsx +2 -1
  92. inspect_ai/_view/www/src/samples/transcript/ErrorEventView.tsx +2 -1
  93. inspect_ai/_view/www/src/samples/transcript/InfoEventView.tsx +2 -1
  94. inspect_ai/_view/www/src/samples/transcript/InputEventView.tsx +2 -1
  95. inspect_ai/_view/www/src/samples/transcript/LoggerEventView.module.css +4 -0
  96. inspect_ai/_view/www/src/samples/transcript/LoggerEventView.tsx +12 -2
  97. inspect_ai/_view/www/src/samples/transcript/ModelEventView.module.css +1 -1
  98. inspect_ai/_view/www/src/samples/transcript/ModelEventView.tsx +25 -28
  99. inspect_ai/_view/www/src/samples/transcript/SampleInitEventView.tsx +2 -1
  100. inspect_ai/_view/www/src/samples/transcript/SampleLimitEventView.tsx +9 -4
  101. inspect_ai/_view/www/src/samples/transcript/SampleTranscript.tsx +2 -2
  102. inspect_ai/_view/www/src/samples/transcript/SandboxEventView.module.css +32 -0
  103. inspect_ai/_view/www/src/samples/transcript/SandboxEventView.tsx +153 -0
  104. inspect_ai/_view/www/src/samples/transcript/ScoreEventView.tsx +2 -2
  105. inspect_ai/_view/www/src/samples/transcript/StepEventView.tsx +12 -5
  106. inspect_ai/_view/www/src/samples/transcript/SubtaskEventView.tsx +18 -14
  107. inspect_ai/_view/www/src/samples/transcript/ToolEventView.tsx +5 -5
  108. inspect_ai/_view/www/src/samples/transcript/TranscriptView.tsx +53 -16
  109. inspect_ai/_view/www/src/samples/transcript/event/EventNav.tsx +2 -1
  110. inspect_ai/_view/www/src/samples/transcript/event/EventNavs.tsx +2 -1
  111. inspect_ai/_view/www/src/samples/transcript/event/EventPanel.tsx +6 -3
  112. inspect_ai/_view/www/src/samples/transcript/event/EventRow.tsx +3 -2
  113. inspect_ai/_view/www/src/samples/transcript/event/EventSection.tsx +2 -2
  114. inspect_ai/_view/www/src/samples/transcript/event/EventTimingPanel.module.css +28 -0
  115. inspect_ai/_view/www/src/samples/transcript/event/EventTimingPanel.tsx +115 -0
  116. inspect_ai/_view/www/src/samples/transcript/event/utils.ts +29 -0
  117. inspect_ai/_view/www/src/samples/transcript/state/StateDiffView.tsx +2 -1
  118. inspect_ai/_view/www/src/samples/transcript/state/StateEventRenderers.tsx +3 -3
  119. inspect_ai/_view/www/src/samples/transcript/state/StateEventView.tsx +11 -8
  120. inspect_ai/_view/www/src/samples/transcript/types.ts +3 -1
  121. inspect_ai/_view/www/src/types/log.d.ts +312 -137
  122. inspect_ai/_view/www/src/usage/ModelTokenTable.tsx +6 -10
  123. inspect_ai/_view/www/src/usage/ModelUsagePanel.module.css +4 -0
  124. inspect_ai/_view/www/src/usage/ModelUsagePanel.tsx +32 -9
  125. inspect_ai/_view/www/src/usage/TokenTable.tsx +4 -6
  126. inspect_ai/_view/www/src/usage/UsageCard.tsx +2 -1
  127. inspect_ai/_view/www/src/utils/format.ts +8 -5
  128. inspect_ai/_view/www/src/utils/json.ts +24 -0
  129. inspect_ai/_view/www/src/workspace/WorkSpace.tsx +6 -5
  130. inspect_ai/_view/www/src/workspace/WorkSpaceView.tsx +18 -8
  131. inspect_ai/_view/www/src/workspace/error/TaskErrorPanel.tsx +2 -1
  132. inspect_ai/_view/www/src/workspace/navbar/Navbar.tsx +2 -1
  133. inspect_ai/_view/www/src/workspace/navbar/PrimaryBar.tsx +3 -3
  134. inspect_ai/_view/www/src/workspace/navbar/ResultsPanel.tsx +4 -3
  135. inspect_ai/_view/www/src/workspace/navbar/SecondaryBar.tsx +5 -4
  136. inspect_ai/_view/www/src/workspace/navbar/StatusPanel.tsx +5 -8
  137. inspect_ai/_view/www/src/workspace/sidebar/EvalStatus.tsx +5 -4
  138. inspect_ai/_view/www/src/workspace/sidebar/LogDirectoryTitleView.tsx +2 -1
  139. inspect_ai/_view/www/src/workspace/sidebar/Sidebar.tsx +2 -1
  140. inspect_ai/_view/www/src/workspace/sidebar/SidebarLogEntry.tsx +2 -2
  141. inspect_ai/_view/www/src/workspace/sidebar/SidebarScoreView.tsx +2 -1
  142. inspect_ai/_view/www/src/workspace/sidebar/SidebarScoresView.tsx +2 -2
  143. inspect_ai/_view/www/src/workspace/tabs/InfoTab.tsx +2 -2
  144. inspect_ai/_view/www/src/workspace/tabs/JsonTab.tsx +2 -5
  145. inspect_ai/_view/www/src/workspace/tabs/SamplesTab.tsx +12 -11
  146. inspect_ai/_view/www/yarn.lock +241 -5
  147. inspect_ai/log/__init__.py +2 -0
  148. inspect_ai/log/_condense.py +4 -0
  149. inspect_ai/log/_log.py +72 -12
  150. inspect_ai/log/_recorders/eval.py +6 -1
  151. inspect_ai/log/_samples.py +5 -1
  152. inspect_ai/log/_transcript.py +89 -2
  153. inspect_ai/model/__init__.py +2 -0
  154. inspect_ai/model/_call_tools.py +8 -1
  155. inspect_ai/model/_chat_message.py +22 -7
  156. inspect_ai/model/_conversation.py +11 -9
  157. inspect_ai/model/_generate_config.py +25 -4
  158. inspect_ai/model/_model.py +164 -72
  159. inspect_ai/model/_model_call.py +10 -3
  160. inspect_ai/model/_model_output.py +3 -0
  161. inspect_ai/model/_openai.py +106 -40
  162. inspect_ai/model/_providers/anthropic.py +145 -26
  163. inspect_ai/model/_providers/bedrock.py +7 -0
  164. inspect_ai/model/_providers/cloudflare.py +20 -7
  165. inspect_ai/model/_providers/google.py +29 -8
  166. inspect_ai/model/_providers/groq.py +66 -27
  167. inspect_ai/model/_providers/hf.py +6 -0
  168. inspect_ai/model/_providers/mistral.py +78 -51
  169. inspect_ai/model/_providers/openai.py +66 -4
  170. inspect_ai/model/_providers/openai_o1.py +10 -0
  171. inspect_ai/model/_providers/providers.py +2 -2
  172. inspect_ai/model/_providers/util/tracker.py +92 -0
  173. inspect_ai/model/_providers/vllm.py +13 -5
  174. inspect_ai/model/_reasoning.py +15 -2
  175. inspect_ai/scorer/_model.py +23 -19
  176. inspect_ai/solver/_basic_agent.py +1 -3
  177. inspect_ai/solver/_bridge/patch.py +0 -2
  178. inspect_ai/solver/_human_agent/agent.py +14 -10
  179. inspect_ai/solver/_human_agent/commands/__init__.py +7 -3
  180. inspect_ai/solver/_human_agent/commands/submit.py +76 -30
  181. inspect_ai/solver/_limit.py +4 -4
  182. inspect_ai/solver/_plan.py +0 -3
  183. inspect_ai/solver/_task_state.py +7 -0
  184. inspect_ai/tool/__init__.py +2 -0
  185. inspect_ai/tool/_tool.py +3 -1
  186. inspect_ai/tool/_tools/_computer/_resources/tool/_run.py +1 -1
  187. inspect_ai/tool/_tools/_web_browser/_resources/.pylintrc +8 -0
  188. inspect_ai/tool/_tools/_web_browser/_resources/.vscode/launch.json +24 -0
  189. inspect_ai/tool/_tools/_web_browser/_resources/.vscode/settings.json +25 -0
  190. inspect_ai/tool/_tools/_web_browser/_resources/Dockerfile +5 -6
  191. inspect_ai/tool/_tools/_web_browser/_resources/README.md +10 -11
  192. inspect_ai/tool/_tools/_web_browser/_resources/accessibility_tree.py +71 -0
  193. inspect_ai/tool/_tools/_web_browser/_resources/accessibility_tree_node.py +323 -0
  194. inspect_ai/tool/_tools/_web_browser/_resources/cdp/__init__.py +5 -0
  195. inspect_ai/tool/_tools/_web_browser/_resources/cdp/a11y.py +279 -0
  196. inspect_ai/tool/_tools/_web_browser/_resources/cdp/dom.py +9 -0
  197. inspect_ai/tool/_tools/_web_browser/_resources/cdp/dom_snapshot.py +293 -0
  198. inspect_ai/tool/_tools/_web_browser/_resources/cdp/page.py +94 -0
  199. inspect_ai/tool/_tools/_web_browser/_resources/constants.py +2 -0
  200. inspect_ai/tool/_tools/_web_browser/_resources/images/usage_diagram.svg +2 -0
  201. inspect_ai/tool/_tools/_web_browser/_resources/playwright_browser.py +50 -0
  202. inspect_ai/tool/_tools/_web_browser/_resources/playwright_crawler.py +31 -359
  203. inspect_ai/tool/_tools/_web_browser/_resources/playwright_page_crawler.py +280 -0
  204. inspect_ai/tool/_tools/_web_browser/_resources/pyproject.toml +65 -0
  205. inspect_ai/tool/_tools/_web_browser/_resources/rectangle.py +64 -0
  206. inspect_ai/tool/_tools/_web_browser/_resources/rpc_client_helpers.py +146 -0
  207. inspect_ai/tool/_tools/_web_browser/_resources/scale_factor.py +64 -0
  208. inspect_ai/tool/_tools/_web_browser/_resources/test_accessibility_tree_node.py +180 -0
  209. inspect_ai/tool/_tools/_web_browser/_resources/test_playwright_crawler.py +15 -9
  210. inspect_ai/tool/_tools/_web_browser/_resources/test_rectangle.py +15 -0
  211. inspect_ai/tool/_tools/_web_browser/_resources/test_web_client.py +44 -0
  212. inspect_ai/tool/_tools/_web_browser/_resources/web_browser_rpc_types.py +39 -0
  213. inspect_ai/tool/_tools/_web_browser/_resources/web_client.py +198 -48
  214. inspect_ai/tool/_tools/_web_browser/_resources/web_client_new_session.py +26 -25
  215. inspect_ai/tool/_tools/_web_browser/_resources/web_server.py +178 -39
  216. inspect_ai/tool/_tools/_web_browser/_web_browser.py +38 -19
  217. inspect_ai/tool/_tools/_web_search.py +3 -3
  218. inspect_ai/util/__init__.py +2 -1
  219. inspect_ai/util/_concurrency.py +14 -8
  220. inspect_ai/util/_display.py +12 -0
  221. inspect_ai/util/_sandbox/context.py +15 -0
  222. inspect_ai/util/_sandbox/docker/docker.py +7 -5
  223. inspect_ai/util/_sandbox/environment.py +32 -1
  224. inspect_ai/util/_sandbox/events.py +183 -0
  225. inspect_ai/util/_sandbox/local.py +3 -3
  226. inspect_ai/util/_sandbox/self_check.py +131 -43
  227. inspect_ai/util/_subtask.py +11 -0
  228. {inspect_ai-0.3.69.dist-info → inspect_ai-0.3.71.dist-info}/METADATA +3 -3
  229. {inspect_ai-0.3.69.dist-info → inspect_ai-0.3.71.dist-info}/RECORD +233 -211
  230. {inspect_ai-0.3.69.dist-info → inspect_ai-0.3.71.dist-info}/WHEEL +1 -1
  231. inspect_ai/_view/www/src/components/VirtualList.module.css +0 -19
  232. inspect_ai/_view/www/src/components/VirtualList.tsx +0 -292
  233. inspect_ai/tool/_tools/_web_browser/_resources/accessibility_node.py +0 -312
  234. inspect_ai/tool/_tools/_web_browser/_resources/dm_env_servicer.py +0 -275
  235. inspect_ai/tool/_tools/_web_browser/_resources/images/usage_diagram.png +0 -0
  236. inspect_ai/tool/_tools/_web_browser/_resources/test_accessibility_node.py +0 -176
  237. inspect_ai/tool/_tools/_web_browser/_resources/test_dm_env_servicer.py +0 -135
  238. inspect_ai/tool/_tools/_web_browser/_resources/test_web_environment.py +0 -71
  239. inspect_ai/tool/_tools/_web_browser/_resources/web_environment.py +0 -184
  240. {inspect_ai-0.3.69.dist-info → inspect_ai-0.3.71.dist-info}/LICENSE +0 -0
  241. {inspect_ai-0.3.69.dist-info → inspect_ai-0.3.71.dist-info}/entry_points.txt +0 -0
  242. {inspect_ai-0.3.69.dist-info → inspect_ai-0.3.71.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  import { clsx } from "clsx";
2
- import { ReactElement, useState } from "react";
2
+ import { FC, ReactElement, ReactNode, useState } from "react";
3
3
  import styles from "./NavPills.module.css";
4
4
 
5
5
  interface NavPillChildProps {
@@ -11,13 +11,14 @@ interface NavPillsProps {
11
11
  children?: ReactElement<NavPillChildProps>[];
12
12
  }
13
13
 
14
- export const NavPills: React.FC<NavPillsProps> = ({ children }) => {
15
- if (!children?.length) {
16
- return null;
14
+ export const NavPills: FC<NavPillsProps> = ({ children }) => {
15
+ const [activeItem, setActiveItem] = useState(
16
+ children ? children[0].props["title"] : null,
17
+ );
18
+ if (!activeItem || !children) {
19
+ return undefined;
17
20
  }
18
21
 
19
- const [activeItem, setActiveItem] = useState(children[0].props["title"]);
20
-
21
22
  // Create Nav Pills for each child
22
23
  const navPills = children.map((nav, idx) => {
23
24
  const title =
@@ -66,10 +67,10 @@ interface NavPillProps {
66
67
  title: string;
67
68
  activeItem: string;
68
69
  setActiveItem: (item: string) => void;
69
- children?: React.ReactNode;
70
+ children?: ReactNode;
70
71
  }
71
72
 
72
- const NavPill: React.FC<NavPillProps> = ({
73
+ const NavPill: FC<NavPillProps> = ({
73
74
  title,
74
75
  activeItem,
75
76
  setActiveItem,
@@ -1,10 +1,11 @@
1
+ import { FC } from "react";
1
2
  import styles from "./ProgressBar.module.css";
2
3
 
3
4
  interface ProgressBarProps {
4
5
  animating: boolean;
5
6
  }
6
7
 
7
- export const ProgressBar: React.FC<ProgressBarProps> = ({ animating }) => {
8
+ export const ProgressBar: FC<ProgressBarProps> = ({ animating }) => {
8
9
  return (
9
10
  <div className={styles.wrapper}>
10
11
  <div
@@ -1,10 +1,15 @@
1
1
  import clsx from "clsx";
2
2
  import {
3
3
  Children,
4
+ CSSProperties,
5
+ FC,
4
6
  Fragment,
5
7
  isValidElement,
6
8
  MouseEvent,
7
9
  ReactElement,
10
+ ReactNode,
11
+ RefObject,
12
+ UIEvent,
8
13
  useCallback,
9
14
  useEffect,
10
15
  useRef,
@@ -17,7 +22,7 @@ interface TabSetProps {
17
22
  className?: string | string[];
18
23
  tabPanelsClassName?: string | string[];
19
24
  tabControlsClassName?: string | string;
20
- tools?: React.ReactNode;
25
+ tools?: ReactNode;
21
26
  children:
22
27
  | ReactElement<TabPanelProps>
23
28
  | (ReactElement<TabPanelProps> | null | undefined)[];
@@ -27,19 +32,19 @@ interface TabPanelProps {
27
32
  id: string;
28
33
  index?: number;
29
34
  selected?: boolean;
30
- style?: React.CSSProperties;
35
+ style?: CSSProperties;
31
36
  scrollable?: boolean;
32
- scrollRef?: React.RefObject<HTMLDivElement | null>;
37
+ scrollRef?: RefObject<HTMLDivElement | null>;
33
38
  className?: string | string[];
34
39
  scrollPosition?: number;
35
40
  setScrollPosition?: (position: number) => void;
36
- children?: React.ReactNode;
41
+ children?: ReactNode;
37
42
  title: string;
38
43
  icon?: string;
39
44
  onSelected: (e: MouseEvent<HTMLElement>) => void;
40
45
  }
41
46
 
42
- export const TabSet: React.FC<TabSetProps> = ({
47
+ export const TabSet: FC<TabSetProps> = ({
43
48
  id,
44
49
  type = "tabs",
45
50
  className,
@@ -76,9 +81,9 @@ export const TabSet: React.FC<TabSetProps> = ({
76
81
  };
77
82
 
78
83
  // Individual Tab Component
79
- const Tab: React.FC<{
84
+ const Tab: FC<{
80
85
  type?: "tabs" | "pills";
81
- tab: React.ReactElement<TabPanelProps>;
86
+ tab: ReactElement<TabPanelProps>;
82
87
  index: number;
83
88
  className?: string | string[];
84
89
  }> = ({ type = "tabs", tab, index, className }) => {
@@ -114,9 +119,9 @@ const Tab: React.FC<{
114
119
  };
115
120
 
116
121
  // Tab Panels Container
117
- const TabPanels: React.FC<{
122
+ const TabPanels: FC<{
118
123
  id: string;
119
- tabs: React.ReactElement<TabPanelProps>[];
124
+ tabs: ReactElement<TabPanelProps>[];
120
125
  className?: string | string[];
121
126
  }> = ({ id, tabs, className }) => (
122
127
  <div className={clsx("tab-content", className)} id={`${id}-content`}>
@@ -127,7 +132,7 @@ const TabPanels: React.FC<{
127
132
  );
128
133
 
129
134
  // Individual Tab Panel
130
- export const TabPanel: React.FC<TabPanelProps> = ({
135
+ export const TabPanel: FC<TabPanelProps> = ({
131
136
  id,
132
137
  selected,
133
138
  style,
@@ -139,7 +144,8 @@ export const TabPanel: React.FC<TabPanelProps> = ({
139
144
  children,
140
145
  }) => {
141
146
  const tabContentsId = computeTabContentsId(id);
142
- const tabContentsRef = scrollRef || useRef<HTMLDivElement>(null);
147
+ const panelRef = useRef<HTMLDivElement>(null);
148
+ const tabContentsRef = scrollRef || panelRef;
143
149
 
144
150
  useEffect(() => {
145
151
  if (!selected || scrollPosition === undefined || !tabContentsRef.current)
@@ -162,7 +168,7 @@ export const TabPanel: React.FC<TabPanelProps> = ({
162
168
 
163
169
  // Handle scrolling
164
170
  const onScroll = useCallback(
165
- (e: React.UIEvent<HTMLDivElement>) => {
171
+ (e: UIEvent<HTMLDivElement>) => {
166
172
  if (setScrollPosition) {
167
173
  setScrollPosition(e.currentTarget.scrollTop);
168
174
  }
@@ -190,7 +196,7 @@ export const TabPanel: React.FC<TabPanelProps> = ({
190
196
  };
191
197
 
192
198
  // Tab Tools Component
193
- const TabTools: React.FC<{ tools?: React.ReactNode }> = ({ tools }) => (
199
+ const TabTools: FC<{ tools?: ReactNode }> = ({ tools }) => (
194
200
  <div className={clsx("tab-tools", moduleStyles.tabTools)}>{tools}</div>
195
201
  );
196
202
 
@@ -199,11 +205,11 @@ const computeTabId = (id: string, index: number) => `${id}-${index}`;
199
205
  const computeTabContentsId = (id: string) => `${id}-contents`;
200
206
 
201
207
  const flattenChildren = (
202
- children: React.ReactNode,
208
+ children: ReactNode,
203
209
  ): ReactElement<TabPanelProps>[] => {
204
210
  return Children.toArray(children).flatMap((child) => {
205
211
  if (isValidElement(child)) {
206
- const element = child as React.ReactElement<any>;
212
+ const element = child as ReactElement<any>;
207
213
 
208
214
  if (element.type === Fragment) {
209
215
  return flattenChildren(element.props.children);
@@ -74,7 +74,7 @@ function filterLargeSample(state: ApplicationState) {
74
74
 
75
75
  const estimatedTotalSize = estimateSize(state.selectedSample.messages);
76
76
  if (estimatedTotalSize > 400000) {
77
- const { selectedSample, ...filteredState } = state; // eslint-disable-line
77
+ const { selectedSample, ...filteredState } = state;
78
78
  return filteredState;
79
79
  } else {
80
80
  return state;
@@ -91,7 +91,7 @@ function filterLargeSelectedLog(state: ApplicationState) {
91
91
  state.selectedLog.contents.sampleSummaries,
92
92
  );
93
93
  if (estimatedSize > 400000) {
94
- const { selectedLog, ...filteredState } = state; // eslint-disable-line
94
+ const { selectedLog, ...filteredState } = state;
95
95
  return filteredState;
96
96
  } else {
97
97
  return state;
@@ -1,12 +1,12 @@
1
1
  import clsx from "clsx";
2
- import { Fragment } from "react";
2
+ import { CSSProperties, FC, Fragment } from "react";
3
3
  import styles from "./MetadataGrid.module.css";
4
4
  import { RenderedContent } from "./RenderedContent";
5
5
 
6
6
  interface MetadataGridProps {
7
7
  id?: string;
8
8
  className?: string | string[];
9
- style?: React.CSSProperties;
9
+ style?: CSSProperties;
10
10
  entries: Record<string, unknown>;
11
11
  plain?: boolean;
12
12
  }
@@ -14,7 +14,7 @@ interface MetadataGridProps {
14
14
  /**
15
15
  * Renders the MetaDataView component.
16
16
  */
17
- export const MetaDataGrid: React.FC<MetadataGridProps> = ({
17
+ export const MetaDataGrid: FC<MetadataGridProps> = ({
18
18
  id,
19
19
  entries,
20
20
  className,
@@ -27,12 +27,14 @@ export const MetaDataGrid: React.FC<MetadataGridProps> = ({
27
27
  const id = `${baseId}-value-${index}`;
28
28
  return (
29
29
  <Fragment key={`${baseId}-record-${index}`}>
30
- <div
31
- style={{
32
- gridColumn: "1 / -1",
33
- borderBottom: `${!plain ? "solid 1px var(--bs-light-border-subtle" : ""}`,
34
- }}
35
- ></div>
30
+ {index !== 0 ? (
31
+ <div
32
+ style={{
33
+ gridColumn: "1 / -1",
34
+ borderBottom: `${!plain ? "solid 1px var(--bs-light-border-subtle" : ""}`,
35
+ }}
36
+ ></div>
37
+ ) : undefined}
36
38
  <div
37
39
  className={clsx(
38
40
  `${baseId}-key`,
@@ -1,10 +1,11 @@
1
1
  import clsx from "clsx";
2
+ import { CSSProperties, FC } from "react";
2
3
  import styles from "./MetaDataView.module.css";
3
4
  import { RenderedContent } from "./RenderedContent";
4
5
 
5
6
  interface MetadataViewProps {
6
7
  id?: string;
7
- style?: React.CSSProperties;
8
+ style?: CSSProperties;
8
9
  entries: Record<string, unknown>;
9
10
  tableOptions?: string;
10
11
  compact?: boolean;
@@ -14,7 +15,7 @@ interface MetadataViewProps {
14
15
  /**
15
16
  * Renders the MetaDataView component.
16
17
  */
17
- export const MetaDataView: React.FC<MetadataViewProps> = ({
18
+ export const MetaDataView: FC<MetadataViewProps> = ({
18
19
  id,
19
20
  style,
20
21
  entries,
@@ -2,6 +2,7 @@
2
2
  display: grid;
3
3
  grid-template-columns: max-content auto;
4
4
  column-gap: 1em;
5
+ row-gap: 0.2em;
5
6
  }
6
7
 
7
8
  .cell {
@@ -7,6 +7,8 @@ import { MetaDataView } from "./MetaDataView";
7
7
 
8
8
  import clsx from "clsx";
9
9
  import React, { Fragment, JSX } from "react";
10
+ import JSONPanel from "../components/JsonPanel";
11
+ import { isJson } from "../utils/json";
10
12
  import styles from "./RenderedContent.module.css";
11
13
  import { Buckets, ContentRenderer } from "./types";
12
14
 
@@ -79,6 +81,20 @@ const contentRenderers: Record<string, ContentRenderer> = {
79
81
  };
80
82
  },
81
83
  },
84
+ JsonString: {
85
+ bucket: Buckets.first,
86
+ canRender: (entry) => {
87
+ if (typeof entry.value === "string") {
88
+ const trimmed = entry.value.trim();
89
+ return isJson(trimmed);
90
+ }
91
+ return false;
92
+ },
93
+ render: (_id, entry) => {
94
+ const obj = JSON.parse(entry.value);
95
+ return { rendered: <JSONPanel data={obj as Record<string, unknown>} /> };
96
+ },
97
+ },
82
98
  Model: {
83
99
  bucket: Buckets.intermediate,
84
100
  canRender: (entry) => {
@@ -237,7 +253,6 @@ const contentRenderers: Record<string, ContentRenderer> = {
237
253
  },
238
254
  render: (id, entry) => {
239
255
  // Generate a json preview
240
- console.log({ entry });
241
256
  return {
242
257
  rendered: (
243
258
  <MetaDataView
@@ -2,14 +2,15 @@ import clsx from "clsx";
2
2
  import { MetaDataView } from "../metadata/MetaDataView";
3
3
  import { EvalDataset } from "../types/log";
4
4
 
5
+ import { CSSProperties, FC } from "react";
5
6
  import styles from "./DatasetDetailView.module.css";
6
7
 
7
8
  interface DatasetDetailViewProps {
8
9
  dataset: EvalDataset;
9
- style?: React.CSSProperties;
10
+ style?: CSSProperties;
10
11
  }
11
12
 
12
- export const DatasetDetailView: React.FC<DatasetDetailViewProps> = ({
13
+ export const DatasetDetailView: FC<DatasetDetailViewProps> = ({
13
14
  dataset,
14
15
  style,
15
16
  }) => {
@@ -1,4 +1,5 @@
1
1
  import clsx from "clsx";
2
+ import { FC } from "react";
2
3
  import { MetaDataView } from "../metadata/MetaDataView";
3
4
  import styles from "./DatasetDetailView.module.css";
4
5
 
@@ -9,7 +10,7 @@ interface DetailStepProps {
9
10
  className?: string | string[];
10
11
  }
11
12
 
12
- export const DetailStep: React.FC<DetailStepProps> = ({
13
+ export const DetailStep: FC<DetailStepProps> = ({
13
14
  icon,
14
15
  name,
15
16
  params,
@@ -1,3 +1,4 @@
1
+ import { FC } from "react";
1
2
  import { ApplicationIcons } from "../appearance/icons";
2
3
  import { Card, CardBody, CardHeader } from "../components/Card";
3
4
  import { EvalPlan, EvalScore, EvalSpec } from "../types/log";
@@ -12,11 +13,7 @@ interface PlanCardProps {
12
13
  /**
13
14
  * Renders the plan card
14
15
  */
15
- export const PlanCard: React.FC<PlanCardProps> = ({
16
- evalSpec,
17
- evalPlan,
18
- scores,
19
- }) => {
16
+ export const PlanCard: FC<PlanCardProps> = ({ evalSpec, evalPlan, scores }) => {
20
17
  return (
21
18
  <Card>
22
19
  <CardHeader icon={ApplicationIcons.config} label="Config" />
@@ -7,6 +7,7 @@ import { ScorerDetailView } from "./ScorerDetailView";
7
7
  import { SolversDetailView } from "./SolverDetailView";
8
8
 
9
9
  import clsx from "clsx";
10
+ import { FC, ReactNode } from "react";
10
11
  import styles from "./PlanDetailView.module.css";
11
12
 
12
13
  interface PlanDetailViewProps {
@@ -15,7 +16,7 @@ interface PlanDetailViewProps {
15
16
  scores?: EvalScore[];
16
17
  }
17
18
 
18
- export const PlanDetailView: React.FC<PlanDetailViewProps> = ({
19
+ export const PlanDetailView: FC<PlanDetailViewProps> = ({
19
20
  evaluation,
20
21
  plan,
21
22
  scores,
@@ -88,7 +89,7 @@ export const PlanDetailView: React.FC<PlanDetailViewProps> = ({
88
89
  const taskColumns: {
89
90
  title: string;
90
91
  className: string | string[];
91
- contents: React.ReactNode;
92
+ contents: ReactNode;
92
93
  }[] = [];
93
94
  taskColumns.push({
94
95
  title: "Dataset",
@@ -145,7 +146,7 @@ export const PlanDetailView: React.FC<PlanDetailViewProps> = ({
145
146
  const metadataColumns: {
146
147
  title: string;
147
148
  className: string;
148
- contents: React.ReactNode;
149
+ contents: ReactNode;
149
150
  }[] = [];
150
151
  const cols = colCount(
151
152
  metadataColumns,
@@ -297,14 +298,10 @@ const colCount = (...other: unknown[]) => {
297
298
  interface PlanColumnProps {
298
299
  title: string;
299
300
  className: string | string[];
300
- children: React.ReactNode;
301
+ children: ReactNode;
301
302
  }
302
303
 
303
- const PlanColumn: React.FC<PlanColumnProps> = ({
304
- title,
305
- className,
306
- children,
307
- }) => {
304
+ const PlanColumn: FC<PlanColumnProps> = ({ title, className, children }) => {
308
305
  return (
309
306
  <div className={clsx(className)}>
310
307
  <div
@@ -1,4 +1,5 @@
1
1
  import clsx from "clsx";
2
+ import { FC } from "react";
2
3
  import { ApplicationIcons } from "../appearance/icons";
3
4
  import styles from "./DatasetDetailView.module.css";
4
5
  import { DetailStep } from "./DetailStep";
@@ -9,7 +10,7 @@ interface ScorerDetailViewProps {
9
10
  params: Record<string, unknown>;
10
11
  }
11
12
 
12
- export const ScorerDetailView: React.FC<ScorerDetailViewProps> = ({
13
+ export const ScorerDetailView: FC<ScorerDetailViewProps> = ({
13
14
  name,
14
15
  scores,
15
16
  params,
@@ -1,15 +1,15 @@
1
1
  import clsx from "clsx";
2
- import { Fragment } from "react";
2
+ import { FC, Fragment } from "react";
3
3
  import { ApplicationIcons } from "../appearance/icons";
4
4
  import { Steps } from "../types/log";
5
5
  import { DetailStep } from "./DetailStep";
6
6
  import styles from "./SolverDetailView.module.css";
7
7
 
8
- interface SolversDetailView {
8
+ interface SolversDetailViewProps {
9
9
  steps: Steps;
10
10
  }
11
11
 
12
- export const SolversDetailView: React.FC<SolversDetailView> = ({ steps }) => {
12
+ export const SolversDetailView: FC<SolversDetailViewProps> = ({ steps }) => {
13
13
  const separator = (
14
14
  <div className={clsx(styles.items, "text-size-small", styles.separator)}>
15
15
  <i className={ApplicationIcons.arrows.right} />
@@ -1,4 +1,4 @@
1
- import { RefObject } from "react";
1
+ import { FC, RefObject } from "react";
2
2
  import { ErrorPanel } from "../components/ErrorPanel";
3
3
  import { ProgressBar } from "../components/ProgressBar";
4
4
  import { EvalSample } from "../types/log";
@@ -21,7 +21,7 @@ interface InlineSampleDisplayProps {
21
21
  /**
22
22
  * Inline Sample Display
23
23
  */
24
- export const InlineSampleDisplay: React.FC<InlineSampleDisplayProps> = ({
24
+ export const InlineSampleDisplay: FC<InlineSampleDisplayProps> = ({
25
25
  id,
26
26
  sample,
27
27
  sampleStatus,
@@ -1,7 +1,7 @@
1
1
  import { ApplicationIcons } from "../appearance/icons";
2
2
  import { LargeModal, ModalTool, ModalTools } from "../components/LargeModal";
3
3
 
4
- import { Ref, RefObject, useCallback, useMemo, useRef } from "react";
4
+ import { FC, Ref, RefObject, useCallback, useMemo, useRef } from "react";
5
5
  import { ErrorPanel } from "../components/ErrorPanel";
6
6
  import { EvalSample } from "../types/log";
7
7
  import { SampleDisplay } from "./SampleDisplay";
@@ -27,7 +27,7 @@ interface SampleDialogProps {
27
27
  /**
28
28
  * Inline Sample Display
29
29
  */
30
- export const SampleDialog: React.FC<SampleDialogProps> = ({
30
+ export const SampleDialog: FC<SampleDialogProps> = ({
31
31
  id,
32
32
  title,
33
33
  sample,
@@ -84,7 +84,7 @@ export const SampleDialog: React.FC<SampleDialogProps> = ({
84
84
  break;
85
85
  }
86
86
  },
87
- [prevSample, nextSample],
87
+ [prevSample, nextSample, setShowingSampleDialog],
88
88
  );
89
89
 
90
90
  const onHide = useCallback(() => {
@@ -9,7 +9,7 @@
9
9
  .metadataPanel {
10
10
  display: flex;
11
11
  flex-wrap: wrap;
12
- align-items: flex-start;
12
+ align-items: stretch;
13
13
  gap: 1em;
14
14
  padding-left: 0;
15
15
  margin-top: 0.5em;
@@ -27,3 +27,11 @@
27
27
  .noTop {
28
28
  margin-top: 0;
29
29
  }
30
+
31
+ .timePanel {
32
+ display: grid;
33
+ grid-template-columns: max-content max-content;
34
+ grid-template-rows: auto;
35
+ column-gap: 0.5em;
36
+ min-width: 200px;
37
+ }
@@ -10,7 +10,7 @@ import { ToolButton } from "../components/ToolButton";
10
10
  import { SampleScoreView } from "./scores/SampleScoreView";
11
11
 
12
12
  import clsx from "clsx";
13
- import { Fragment, MouseEvent, RefObject } from "react";
13
+ import { FC, Fragment, MouseEvent, RefObject } from "react";
14
14
  import { Card, CardBody, CardHeader } from "../components/Card";
15
15
  import { EmptyPanel } from "../components/EmptyPanel";
16
16
  import { JSONPanel } from "../components/JsonPanel";
@@ -24,6 +24,7 @@ import {
24
24
  } from "../constants";
25
25
  import { EvalSample } from "../types/log";
26
26
  import { ModelTokenTable } from "../usage/ModelTokenTable";
27
+ import { formatTime } from "../utils/format";
27
28
  import { printHeadingHtml, printHtml } from "../utils/print";
28
29
  import { ChatViewVirtualList } from "./chat/ChatViewVirtualList";
29
30
  import { SamplesDescriptor } from "./descriptor/samplesDescriptor";
@@ -43,7 +44,7 @@ interface SampleDisplayProps {
43
44
  /**
44
45
  * Component to display a sample with relevant context and visibility control.
45
46
  */
46
- export const SampleDisplay: React.FC<SampleDisplayProps> = ({
47
+ export const SampleDisplay: FC<SampleDisplayProps> = ({
47
48
  id,
48
49
  sample,
49
50
  sampleDescriptor,
@@ -180,7 +181,7 @@ export const SampleDisplay: React.FC<SampleDisplayProps> = ({
180
181
  {sampleMetadatas.length > 0 ? (
181
182
  <TabPanel
182
183
  id={kSampleMetdataTabId}
183
- className="sample-tab"
184
+ className={clsx("sample-tab")}
184
185
  title="Metadata"
185
186
  onSelected={onSelectedTab}
186
187
  selected={selectedTab === kSampleMetdataTabId}
@@ -228,6 +229,7 @@ export const SampleDisplay: React.FC<SampleDisplayProps> = ({
228
229
 
229
230
  const metadataViewsForSample = (id: string, sample: EvalSample) => {
230
231
  const sampleMetadatas = [];
232
+
231
233
  if (sample.model_usage && Object.keys(sample.model_usage).length > 0) {
232
234
  sampleMetadatas.push(
233
235
  <Card key={`sample-usage-${id}`}>
@@ -242,6 +244,31 @@ const metadataViewsForSample = (id: string, sample: EvalSample) => {
242
244
  );
243
245
  }
244
246
 
247
+ if (
248
+ sample.total_time !== undefined &&
249
+ sample.total_time !== null &&
250
+ sample.working_time !== undefined &&
251
+ sample.working_time !== null
252
+ ) {
253
+ sampleMetadatas.push(
254
+ <Card key={`sample-time-${id}`}>
255
+ <CardHeader label="Time" />
256
+ <CardBody>
257
+ <div className={clsx(styles.timePanel, "text-size-smaller")}>
258
+ <div className={clsx("text-style-label", "text-style-secondary")}>
259
+ Working
260
+ </div>
261
+ <div>{formatTime(sample.working_time)}</div>
262
+ <div className={clsx("text-style-label", "text-style-secondary")}>
263
+ Total
264
+ </div>
265
+ <div>{formatTime(sample.total_time)}</div>
266
+ </div>
267
+ </CardBody>
268
+ </Card>,
269
+ );
270
+ }
271
+
245
272
  if (Object.keys(sample?.metadata).length > 0) {
246
273
  sampleMetadatas.push(
247
274
  <Card key={`sample-metadata-${id}`}>
@@ -22,3 +22,7 @@
22
22
  .wrap {
23
23
  word-wrap: anywhere;
24
24
  }
25
+
26
+ .titled:hover {
27
+ cursor: pointer;
28
+ }
@@ -1,11 +1,11 @@
1
1
  import clsx from "clsx";
2
2
  import { MarkdownDiv } from "../components/MarkdownDiv";
3
- import { EvalSample } from "../types/log";
4
- import { arrayToString, inputString } from "../utils/format";
3
+ import { EvalSample, WorkingTime } from "../types/log";
4
+ import { arrayToString, formatTime, inputString } from "../utils/format";
5
5
  import { SamplesDescriptor } from "./descriptor/samplesDescriptor";
6
6
  import { FlatSampleError } from "./error/FlatSampleErrorView";
7
7
 
8
- import { ReactNode } from "react";
8
+ import { FC, ReactNode } from "react";
9
9
  import styles from "./SampleSummaryView.module.css";
10
10
 
11
11
  interface SampleSummaryViewProps {
@@ -20,12 +20,13 @@ interface SummaryColumn {
20
20
  size: string;
21
21
  center?: boolean;
22
22
  clamp?: boolean;
23
+ title?: string;
23
24
  }
24
25
 
25
26
  /**
26
27
  * Component to display a sample with relevant context and visibility control.
27
28
  */
28
- export const SampleSummaryView: React.FC<SampleSummaryViewProps> = ({
29
+ export const SampleSummaryView: FC<SampleSummaryViewProps> = ({
29
30
  parent_id,
30
31
  sample,
31
32
  sampleDescriptor,
@@ -46,6 +47,7 @@ export const SampleSummaryView: React.FC<SampleSummaryViewProps> = ({
46
47
  sampleDescriptor?.messageShape.normalized.limit > 0
47
48
  ? Math.max(0.15, sampleDescriptor.messageShape.normalized.limit)
48
49
  : 0;
50
+ const timeSize = sample.working_time || sample.total_time ? 0.15 : 0;
49
51
  const idSize = Math.max(
50
52
  2,
51
53
  Math.min(10, sampleDescriptor?.messageShape.raw.id),
@@ -110,6 +112,23 @@ export const SampleSummaryView: React.FC<SampleSummaryViewProps> = ({
110
112
  });
111
113
  }
112
114
 
115
+ const toolTip = (working_time?: WorkingTime) => {
116
+ if (working_time === undefined || working_time === null) {
117
+ return undefined;
118
+ }
119
+ return `Working time: ${formatTime(working_time)}`;
120
+ };
121
+
122
+ if (sample.total_time) {
123
+ columns.push({
124
+ label: "Time",
125
+ value: formatTime(sample.total_time),
126
+ size: `${timeSize}fr`,
127
+ center: true,
128
+ title: toolTip(sample.working_time),
129
+ });
130
+ }
131
+
113
132
  if (sample?.limit && limitSize > 0) {
114
133
  columns.push({
115
134
  label: "Limit",
@@ -151,8 +170,10 @@ export const SampleSummaryView: React.FC<SampleSummaryViewProps> = ({
151
170
  "text-style-label",
152
171
  "text-style-secondary",
153
172
  "text-size-base",
173
+ col.title ? styles.titled : undefined,
154
174
  col.center ? styles.centerLabel : undefined,
155
175
  )}
176
+ title={col.title}
156
177
  >
157
178
  {col.label}
158
179
  </div>