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
- import clsx from "clsx";
2
1
  import {
2
+ FC,
3
3
  KeyboardEvent,
4
4
  RefObject,
5
5
  useCallback,
@@ -8,15 +8,16 @@ import {
8
8
  useRef,
9
9
  useState,
10
10
  } from "react";
11
+ import { Virtuoso, VirtuosoHandle } from "react-virtuoso";
11
12
  import { EmptyPanel } from "../../components/EmptyPanel";
12
13
  import { MessageBand } from "../../components/MessageBand";
13
- import { VirtualList, VirtualListRef } from "../../components/VirtualList";
14
14
  import { formatNoDecimal } from "../../utils/format";
15
15
  import { ListItem } from "../../workspace/tabs/types";
16
16
  import { SamplesDescriptor } from "../descriptor/samplesDescriptor";
17
17
  import { SampleRow } from "./SampleRow";
18
18
  import { SampleSeparator } from "./SampleSeparator";
19
19
 
20
+ import clsx from "clsx";
20
21
  import { SampleFooter } from "./SampleFooter";
21
22
  import { SampleHeader } from "./SampleHeader";
22
23
  import styles from "./SampleList.module.css";
@@ -25,7 +26,6 @@ const kSampleHeight = 88;
25
26
  const kSeparatorHeight = 24;
26
27
 
27
28
  interface SampleListProps {
28
- listRef: RefObject<VirtualListRef | null>;
29
29
  items: ListItem[];
30
30
  sampleDescriptor: SamplesDescriptor;
31
31
  selectedIndex: number;
@@ -33,11 +33,11 @@ interface SampleListProps {
33
33
  prevSample: () => void;
34
34
  showSample: (index: number) => void;
35
35
  className?: string | string[];
36
+ listHandle: RefObject<VirtuosoHandle | null>;
36
37
  }
37
38
 
38
- export const SampleList: React.FC<SampleListProps> = (props) => {
39
+ export const SampleList: FC<SampleListProps> = (props) => {
39
40
  const {
40
- listRef,
41
41
  items,
42
42
  sampleDescriptor,
43
43
  selectedIndex,
@@ -45,12 +45,10 @@ export const SampleList: React.FC<SampleListProps> = (props) => {
45
45
  prevSample,
46
46
  showSample,
47
47
  className,
48
+ listHandle,
48
49
  } = props;
49
50
 
50
- // If there are no samples, just display an empty state
51
- if (items.length === 0) {
52
- return <EmptyPanel>No Samples</EmptyPanel>;
53
- }
51
+ const [followOutput, setFollowOutput] = useState(false);
54
52
 
55
53
  const [hidden, setHidden] = useState(false);
56
54
  useEffect(() => {
@@ -70,16 +68,45 @@ export const SampleList: React.FC<SampleListProps> = (props) => {
70
68
 
71
69
  const prevSelectedIndexRef = useRef<number>(null);
72
70
  useEffect(() => {
73
- const listEl = listRef.current;
71
+ const listEl = listHandle.current;
74
72
  if (listEl) {
75
- const actualRowIndex = itemRowMapping[selectedIndex];
76
-
77
- const direction =
78
- actualRowIndex > (prevSelectedIndexRef.current || 0) ? "down" : "up";
79
- listRef.current?.scrollToIndex(actualRowIndex, direction);
80
- prevSelectedIndexRef.current = actualRowIndex;
73
+ requestAnimationFrame(() => {
74
+ setTimeout(() => {
75
+ const actualRowIndex = itemRowMapping[selectedIndex];
76
+ listEl.scrollToIndex(actualRowIndex);
77
+ prevSelectedIndexRef.current = actualRowIndex;
78
+ }, 10);
79
+ });
81
80
  }
82
- }, [selectedIndex, listRef, itemRowMapping]);
81
+ }, [selectedIndex, listHandle, itemRowMapping]);
82
+
83
+ const onkeydown = useCallback(
84
+ (e: KeyboardEvent<HTMLDivElement>) => {
85
+ switch (e.key) {
86
+ case "ArrowUp":
87
+ prevSample();
88
+ e.preventDefault();
89
+ e.stopPropagation();
90
+ break;
91
+ case "ArrowDown":
92
+ nextSample();
93
+ e.preventDefault();
94
+ e.stopPropagation();
95
+ break;
96
+ case "Enter":
97
+ showSample(selectedIndex);
98
+ e.preventDefault();
99
+ e.stopPropagation();
100
+ break;
101
+ }
102
+ },
103
+ [selectedIndex, nextSample, prevSample, showSample],
104
+ );
105
+
106
+ // If there are no samples, just display an empty state
107
+ if (items.length === 0) {
108
+ return <EmptyPanel>No Samples</EmptyPanel>;
109
+ }
83
110
 
84
111
  const renderRow = (item: ListItem) => {
85
112
  if (item.type === "sample") {
@@ -108,29 +135,6 @@ export const SampleList: React.FC<SampleListProps> = (props) => {
108
135
  }
109
136
  };
110
137
 
111
- const onkeydown = useCallback(
112
- (e: KeyboardEvent<HTMLDivElement>) => {
113
- switch (e.key) {
114
- case "ArrowUp":
115
- prevSample();
116
- e.preventDefault();
117
- e.stopPropagation();
118
- break;
119
- case "ArrowDown":
120
- nextSample();
121
- e.preventDefault();
122
- e.stopPropagation();
123
- break;
124
- case "Enter":
125
- showSample(selectedIndex);
126
- e.preventDefault();
127
- e.stopPropagation();
128
- break;
129
- }
130
- },
131
- [selectedIndex],
132
- );
133
-
134
138
  const { input, limit, answer, target } = gridColumns(sampleDescriptor);
135
139
 
136
140
  const sampleCount = items?.reduce((prev, current) => {
@@ -186,13 +190,21 @@ export const SampleList: React.FC<SampleListProps> = (props) => {
186
190
  limit={limit !== "0"}
187
191
  gridColumnsTemplate={gridColumnsValue(sampleDescriptor)}
188
192
  />
189
- <VirtualList
190
- ref={listRef}
193
+ <Virtuoso
194
+ ref={listHandle}
195
+ style={{ height: "100%" }}
191
196
  data={items}
192
- tabIndex={0}
193
- renderRow={renderRow}
197
+ defaultItemHeight={50}
198
+ itemContent={(_index: number, data: ListItem) => {
199
+ return renderRow(data);
200
+ }}
201
+ followOutput={followOutput}
202
+ atBottomStateChange={(atBottom: boolean) => {
203
+ setFollowOutput(atBottom);
204
+ }}
205
+ className={clsx(className)}
194
206
  onKeyDown={onkeydown}
195
- className={clsx(styles.list, className)}
207
+ skipAnimationFrameInResizeObserver={true}
196
208
  />
197
209
  <SampleFooter sampleCount={sampleCount} />
198
210
  </div>
@@ -1,4 +1,5 @@
1
1
  import clsx from "clsx";
2
+ import { FC } from "react";
2
3
  import { SampleSummary } from "../../api/types";
3
4
  import { MarkdownDiv } from "../../components/MarkdownDiv";
4
5
  import { arrayToString, inputString } from "../../utils/format";
@@ -17,7 +18,7 @@ interface SampleRowProps {
17
18
  showSample: (index: number) => void;
18
19
  }
19
20
 
20
- export const SampleRow: React.FC<SampleRowProps> = ({
21
+ export const SampleRow: FC<SampleRowProps> = ({
21
22
  id,
22
23
  index,
23
24
  sample,
@@ -1,4 +1,5 @@
1
1
  import clsx from "clsx";
2
+ import { FC } from "react";
2
3
  import styles from "./SampleSeparator.module.css";
3
4
 
4
5
  interface SampleSeparatorProps {
@@ -7,7 +8,7 @@ interface SampleSeparatorProps {
7
8
  height: number;
8
9
  }
9
10
 
10
- export const SampleSeparator: React.FC<SampleSeparatorProps> = ({
11
+ export const SampleSeparator: FC<SampleSeparatorProps> = ({
11
12
  id,
12
13
  title,
13
14
  height,
@@ -1,5 +1,5 @@
1
1
  import clsx from "clsx";
2
- import { ChangeEvent } from "react";
2
+ import { ChangeEvent, FC } from "react";
3
3
  import styles from "./EpochFilter.module.css";
4
4
 
5
5
  interface EpochFilterProps {
@@ -8,7 +8,7 @@ interface EpochFilterProps {
8
8
  setEpoch: (n: string) => void;
9
9
  }
10
10
 
11
- export const EpochFilter: React.FC<EpochFilterProps> = ({
11
+ export const EpochFilter: FC<EpochFilterProps> = ({
12
12
  epochs,
13
13
  epoch,
14
14
  setEpoch,
@@ -1,6 +1,7 @@
1
1
  import clsx from "clsx";
2
2
  import { ScoreLabel } from "../../types";
3
3
 
4
+ import { FC } from "react";
4
5
  import styles from "./SelectScorer.module.css";
5
6
 
6
7
  interface SelectScorerProps {
@@ -9,7 +10,7 @@ interface SelectScorerProps {
9
10
  setScore: (score: ScoreLabel) => void;
10
11
  }
11
12
 
12
- export const SelectScorer: React.FC<SelectScorerProps> = ({
13
+ export const SelectScorer: FC<SelectScorerProps> = ({
13
14
  scores,
14
15
  score,
15
16
  setScore,
@@ -100,7 +101,7 @@ interface ScoreSelectorProps {
100
101
  className?: string | string[];
101
102
  }
102
103
 
103
- const ScoreSelector: React.FC<ScoreSelectorProps> = ({
104
+ const ScoreSelector: FC<ScoreSelectorProps> = ({
104
105
  scores,
105
106
  selectedIndex,
106
107
  setSelectedIndex,
@@ -138,7 +139,7 @@ interface ScorerSelectorProps {
138
139
  setSelectedIndex: (index: number) => void;
139
140
  }
140
141
 
141
- const ScorerSelector: React.FC<ScorerSelectorProps> = ({
142
+ const ScorerSelector: FC<ScorerSelectorProps> = ({
142
143
  scorers,
143
144
  selectedIndex,
144
145
  setSelectedIndex,
@@ -1,4 +1,5 @@
1
1
  import clsx from "clsx";
2
+ import { FC } from "react";
2
3
  import { SampleSummary } from "../../api/types";
3
4
  import {
4
5
  kEpochAscVal,
@@ -18,11 +19,7 @@ interface SortFilterProps {
18
19
  epochs: number;
19
20
  }
20
21
 
21
- export const SortFilter: React.FC<SortFilterProps> = ({
22
- sort,
23
- setSort,
24
- epochs,
25
- }) => {
22
+ export const SortFilter: FC<SortFilterProps> = ({ sort, setSort, epochs }) => {
26
23
  const options = [
27
24
  { label: "sample asc", val: kSampleAscVal },
28
25
  { label: "sample desc", val: kSampleDescVal },
@@ -14,7 +14,7 @@ import {
14
14
  import { tags } from "@lezer/highlight";
15
15
  import clsx from "clsx";
16
16
  import { EditorView, minimalSetup } from "codemirror";
17
- import { useEffect, useMemo, useRef, useState } from "react";
17
+ import { FC, useEffect, useMemo, useRef, useState } from "react";
18
18
 
19
19
  import { ScoreFilter } from "../../../types";
20
20
  import { EvalDescriptor } from "../../descriptor/types";
@@ -147,7 +147,7 @@ const getLints = (
147
147
  };
148
148
 
149
149
  // Main component
150
- export const SampleFilter: React.FC<SampleFilterProps> = ({
150
+ export const SampleFilter: FC<SampleFilterProps> = ({
151
151
  evalDescriptor,
152
152
  scoreFilter,
153
153
  setScoreFilter,
@@ -7,6 +7,7 @@ import { arrayToString, inputString } from "../../utils/format";
7
7
  import { SamplesDescriptor } from "../descriptor/samplesDescriptor";
8
8
  import { SampleScores } from "./SampleScores";
9
9
 
10
+ import { FC } from "react";
10
11
  import { SampleSummary } from "../../api/types";
11
12
  import styles from "./SampleScoreView.module.css";
12
13
 
@@ -17,7 +18,7 @@ interface SampleScoreViewProps {
17
18
  className?: string | string[];
18
19
  }
19
20
 
20
- export const SampleScoreView: React.FC<SampleScoreViewProps> = ({
21
+ export const SampleScoreView: FC<SampleScoreViewProps> = ({
21
22
  sample,
22
23
  sampleDescriptor,
23
24
  className,
@@ -1,4 +1,4 @@
1
- import { Fragment } from "react";
1
+ import { FC, Fragment } from "react";
2
2
  import { SampleSummary } from "../../api/types";
3
3
  import { SamplesDescriptor } from "../descriptor/samplesDescriptor";
4
4
 
@@ -10,7 +10,7 @@ interface SampleScoresProps {
10
10
  scorer: string;
11
11
  }
12
12
 
13
- export const SampleScores: React.FC<SampleScoresProps> = ({
13
+ export const SampleScores: FC<SampleScoresProps> = ({
14
14
  sample,
15
15
  sampleDescriptor,
16
16
  scorer,
@@ -1,3 +1,4 @@
1
+ import { FC } from "react";
1
2
  import { ApplicationIcons } from "../../appearance/icons";
2
3
  import { ApprovalEvent } from "../../types/log";
3
4
  import { EventRow } from "./event/EventRow";
@@ -10,7 +11,7 @@ interface ApprovalEventViewProps {
10
11
  /**
11
12
  * Renders the ApprovalEventView component.
12
13
  */
13
- export const ApprovalEventView: React.FC<ApprovalEventViewProps> = ({
14
+ export const ApprovalEventView: FC<ApprovalEventViewProps> = ({
14
15
  event,
15
16
  className,
16
17
  }) => {
@@ -1,3 +1,4 @@
1
+ import { FC } from "react";
1
2
  import { ApplicationIcons } from "../../appearance/icons";
2
3
  import { ANSIDisplay } from "../../components/AnsiDisplay";
3
4
  import { ErrorEvent } from "../../types/log";
@@ -16,7 +17,7 @@ interface ErrorEventViewProps {
16
17
  /**
17
18
  * Renders the ErrorEventView component.
18
19
  */
19
- export const ErrorEventView: React.FC<ErrorEventViewProps> = ({
20
+ export const ErrorEventView: FC<ErrorEventViewProps> = ({
20
21
  id,
21
22
  event,
22
23
  eventState,
@@ -1,3 +1,4 @@
1
+ import { FC } from "react";
1
2
  import { ApplicationIcons } from "../../appearance/icons";
2
3
  import { JSONPanel } from "../../components/JsonPanel";
3
4
  import { MarkdownDiv } from "../../components/MarkdownDiv";
@@ -18,7 +19,7 @@ interface InfoEventViewProps {
18
19
  /**
19
20
  * Renders the InfoEventView component.
20
21
  */
21
- export const InfoEventView: React.FC<InfoEventViewProps> = ({
22
+ export const InfoEventView: FC<InfoEventViewProps> = ({
22
23
  id,
23
24
  event,
24
25
  eventState,
@@ -1,3 +1,4 @@
1
+ import { FC } from "react";
1
2
  import { ApplicationIcons } from "../../appearance/icons";
2
3
  import { ANSIDisplay } from "../../components/AnsiDisplay";
3
4
  import { InputEvent } from "../../types/log";
@@ -16,7 +17,7 @@ interface InputEventViewProps {
16
17
  /**
17
18
  * Renders the ErrorEventView component.
18
19
  */
19
- export const InputEventView: React.FC<InputEventViewProps> = ({
20
+ export const InputEventView: FC<InputEventViewProps> = ({
20
21
  id,
21
22
  event,
22
23
  eventState,
@@ -4,3 +4,7 @@
4
4
  grid-template-columns: 1fr max-content;
5
5
  column-gap: 1em;
6
6
  }
7
+
8
+ .jsonPanel {
9
+ padding: 0 !important;
10
+ }
@@ -3,6 +3,9 @@ import { ApplicationIcons } from "../../appearance/icons";
3
3
  import { LoggerEvent } from "../../types/log";
4
4
  import { EventRow } from "./event/EventRow";
5
5
 
6
+ import { FC } from "react";
7
+ import { MetaDataGrid } from "../../metadata/MetaDataGrid";
8
+ import { parsedJson as maybeParseJson } from "../../utils/json";
6
9
  import styles from "./LoggerEventView.module.css";
7
10
 
8
11
  interface LoggerEventViewProps {
@@ -13,10 +16,11 @@ interface LoggerEventViewProps {
13
16
  /**
14
17
  * Renders the LoggerEventView component.
15
18
  */
16
- export const LoggerEventView: React.FC<LoggerEventViewProps> = ({
19
+ export const LoggerEventView: FC<LoggerEventViewProps> = ({
17
20
  event,
18
21
  className,
19
22
  }) => {
23
+ const obj = maybeParseJson(event.message.message);
20
24
  return (
21
25
  <EventRow
22
26
  className={className}
@@ -24,7 +28,13 @@ export const LoggerEventView: React.FC<LoggerEventViewProps> = ({
24
28
  icon={ApplicationIcons.logging[event.message.level.toLowerCase()]}
25
29
  >
26
30
  <div className={clsx("text-size-base", styles.grid)}>
27
- <div className={clsx("text-size-smaller")}>{event.message.message}</div>
31
+ <div className={clsx("text-size-smaller")}>
32
+ {obj !== undefined && obj !== null ? (
33
+ <MetaDataGrid entries={obj as Record<string, unknown>} />
34
+ ) : (
35
+ event.message.message
36
+ )}
37
+ </div>
28
38
  <div className={clsx("text-size-smaller", "text-style-secondary")}>
29
39
  {event.message.filename}:{event.message.lineno}
30
40
  </div>
@@ -9,7 +9,7 @@
9
9
 
10
10
  .all {
11
11
  display: grid;
12
- grid-template-columns: 1fr 1fr;
12
+ grid-template-columns: 1fr 1fr 1fr;
13
13
  column-gap: 1em;
14
14
  }
15
15
 
@@ -3,7 +3,7 @@ import "prismjs/components/prism-json";
3
3
  import "prismjs/components/prism-python";
4
4
 
5
5
  import clsx from "clsx";
6
- import { Fragment, useEffect, useMemo, useRef } from "react";
6
+ import { FC, Fragment, useEffect, useMemo, useRef } from "react";
7
7
  import { ApplicationIcons } from "../../appearance/icons";
8
8
  import { MetaDataGrid } from "../../metadata/MetaDataGrid";
9
9
  import {
@@ -14,11 +14,6 @@ import {
14
14
  Tools1,
15
15
  } from "../../types/log";
16
16
  import { ModelUsagePanel } from "../../usage/ModelUsagePanel";
17
- import {
18
- formatDateTime,
19
- formatNumber,
20
- formatPrettyDecimal,
21
- } from "../../utils/format";
22
17
  import { ChatView } from "../chat/ChatView";
23
18
  import { EventPanel } from "./event/EventPanel";
24
19
  import { EventSection } from "./event/EventSection";
@@ -26,6 +21,8 @@ import { TranscriptEventState } from "./types";
26
21
 
27
22
  import { highlightElement } from "prismjs";
28
23
  import styles from "./ModelEventView.module.css";
24
+ import { EventTimingPanel } from "./event/EventTimingPanel";
25
+ import { formatTiming, formatTitle } from "./event/utils";
29
26
 
30
27
  interface ModelEventViewProps {
31
28
  id: string;
@@ -38,7 +35,7 @@ interface ModelEventViewProps {
38
35
  /**
39
36
  * Renders the StateEventView component.
40
37
  */
41
- export const ModelEventView: React.FC<ModelEventViewProps> = ({
38
+ export const ModelEventView: FC<ModelEventViewProps> = ({
42
39
  id,
43
40
  event,
44
41
  eventState,
@@ -48,15 +45,6 @@ export const ModelEventView: React.FC<ModelEventViewProps> = ({
48
45
  const totalUsage = event.output.usage?.total_tokens;
49
46
  const callTime = event.output.time;
50
47
 
51
- const subItems = [];
52
- if (totalUsage) {
53
- subItems.push(`${formatNumber(totalUsage)} tokens`);
54
- }
55
- if (callTime) {
56
- subItems.push(`${formatPrettyDecimal(callTime)} sec`);
57
- }
58
- const subtitle = subItems.length > 0 ? `(${subItems.join(", ")})` : "";
59
-
60
48
  // Note: despite the type system saying otherwise, this has appeared empircally
61
49
  // to sometimes be undefined
62
50
  const outputMessages = event.output.choices?.map((choice) => {
@@ -83,8 +71,8 @@ export const ModelEventView: React.FC<ModelEventViewProps> = ({
83
71
  <EventPanel
84
72
  id={id}
85
73
  className={className}
86
- title={`Model Call: ${event.model} ${subtitle}`}
87
- subTitle={formatDateTime(new Date(event.timestamp))}
74
+ title={formatTitle(`Model Call: ${event.model}`, totalUsage, callTime)}
75
+ subTitle={formatTiming(event.timestamp, event.working_start)}
88
76
  icon={ApplicationIcons.model}
89
77
  selectedNav={eventState.selectedNav || ""}
90
78
  setSelectedNav={(selectedNav) => {
@@ -116,6 +104,15 @@ export const ModelEventView: React.FC<ModelEventViewProps> = ({
116
104
  ) : undefined}
117
105
  </EventSection>
118
106
 
107
+ <EventSection title="Timing" className={styles.tableSelection}>
108
+ <EventTimingPanel
109
+ timestamp={event.timestamp}
110
+ completed={event.completed}
111
+ working_start={event.working_start}
112
+ working_time={event.working_time}
113
+ />
114
+ </EventSection>
115
+
119
116
  <EventSection
120
117
  title="Tools"
121
118
  className={clsx(styles.tableSelection, styles.tools)}
@@ -150,7 +147,7 @@ interface APIViewProps {
150
147
  className?: string | string[];
151
148
  }
152
149
 
153
- export const APIView: React.FC<APIViewProps> = ({ call, className }) => {
150
+ export const APIView: FC<APIViewProps> = ({ call, className }) => {
154
151
  if (!call) {
155
152
  return null;
156
153
  }
@@ -172,11 +169,7 @@ interface APICodeCellProps {
172
169
  contents: Request | Response;
173
170
  }
174
171
 
175
- export const APICodeCell: React.FC<APICodeCellProps> = ({ id, contents }) => {
176
- if (!contents) {
177
- return null;
178
- }
179
-
172
+ export const APICodeCell: FC<APICodeCellProps> = ({ id, contents }) => {
180
173
  const codeRef = useRef<HTMLElement>(null);
181
174
  const sourceCode = useMemo(() => {
182
175
  return JSON.stringify(contents, undefined, 2);
@@ -186,11 +179,15 @@ export const APICodeCell: React.FC<APICodeCellProps> = ({ id, contents }) => {
186
179
  if (codeRef.current) {
187
180
  highlightElement(codeRef.current);
188
181
  }
189
- }, [codeRef.current, contents]);
182
+ }, [contents]);
183
+
184
+ if (!contents) {
185
+ return null;
186
+ }
190
187
 
191
188
  return (
192
- <div>
193
- <pre className={styles.codePre}>
189
+ <div className={clsx("model-call")}>
190
+ <pre className={clsx(styles.codePre)}>
194
191
  <code
195
192
  id={id}
196
193
  ref={codeRef}
@@ -207,7 +204,7 @@ interface ToolConfigProps {
207
204
  tools: Tools1;
208
205
  }
209
206
 
210
- const ToolsConfig: React.FC<ToolConfigProps> = ({ tools }) => {
207
+ const ToolsConfig: FC<ToolConfigProps> = ({ tools }) => {
211
208
  const toolEls = tools.map((tool, idx) => {
212
209
  return (
213
210
  <Fragment key={`${tool.name}-${idx}`}>
@@ -9,6 +9,7 @@ import { EventPanel } from "./event/EventPanel";
9
9
  import { EventSection } from "./event/EventSection";
10
10
  import { TranscriptEventState } from "./types";
11
11
 
12
+ import { FC } from "react";
12
13
  import styles from "./SampleInitEventView.module.css";
13
14
 
14
15
  interface SampleInitEventViewProps {
@@ -22,7 +23,7 @@ interface SampleInitEventViewProps {
22
23
  /**
23
24
  * Renders the SampleInitEventView component.
24
25
  */
25
- export const SampleInitEventView: React.FC<SampleInitEventViewProps> = ({
26
+ export const SampleInitEventView: FC<SampleInitEventViewProps> = ({
26
27
  id,
27
28
  event,
28
29
  eventState,
@@ -1,5 +1,6 @@
1
+ import { FC } from "react";
1
2
  import { ApplicationIcons } from "../../appearance/icons";
2
- import { SampleLimitEvent, Type7 } from "../../types/log";
3
+ import { SampleLimitEvent, Type8 } from "../../types/log";
3
4
  import { EventPanel } from "./event/EventPanel";
4
5
  import { TranscriptEventState } from "./types";
5
6
 
@@ -14,14 +15,14 @@ interface SampleLimitEventViewProps {
14
15
  /**
15
16
  * Renders the InfoEventView component.
16
17
  */
17
- export const SampleLimitEventView: React.FC<SampleLimitEventViewProps> = ({
18
+ export const SampleLimitEventView: FC<SampleLimitEventViewProps> = ({
18
19
  id,
19
20
  event,
20
21
  eventState,
21
22
  setEventState,
22
23
  className,
23
24
  }) => {
24
- const resolve_title = (type: Type7) => {
25
+ const resolve_title = (type: Type8) => {
25
26
  switch (type) {
26
27
  case "custom":
27
28
  return "Custom Limit Exceeded";
@@ -33,10 +34,12 @@ export const SampleLimitEventView: React.FC<SampleLimitEventViewProps> = ({
33
34
  return "Token Limit Exceeded";
34
35
  case "operator":
35
36
  return "Operator Canceled";
37
+ case "working":
38
+ return "Execution Time Limit Exceeded";
36
39
  }
37
40
  };
38
41
 
39
- const resolve_icon = (type: Type7) => {
42
+ const resolve_icon = (type: Type8) => {
40
43
  switch (type) {
41
44
  case "custom":
42
45
  return ApplicationIcons.limits.custom;
@@ -48,6 +51,8 @@ export const SampleLimitEventView: React.FC<SampleLimitEventViewProps> = ({
48
51
  return ApplicationIcons.limits.tokens;
49
52
  case "operator":
50
53
  return ApplicationIcons.limits.operator;
54
+ case "working":
55
+ return ApplicationIcons.limits.execution;
51
56
  }
52
57
  };
53
58
 
@@ -1,4 +1,4 @@
1
- import { RefObject } from "react";
1
+ import { FC, RefObject } from "react";
2
2
  import { Events } from "../../types/log";
3
3
  import { TranscriptVirtualList } from "./TranscriptView";
4
4
 
@@ -11,7 +11,7 @@ interface SampleTranscriptProps {
11
11
  /**
12
12
  * Renders the SampleTranscript component.=
13
13
  */
14
- export const SampleTranscript: React.FC<SampleTranscriptProps> = ({
14
+ export const SampleTranscript: FC<SampleTranscriptProps> = ({
15
15
  id,
16
16
  evalEvents,
17
17
  scrollRef,