inspect-ai 0.3.81__py3-none-any.whl → 0.3.83__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 (297) hide show
  1. inspect_ai/__init__.py +2 -1
  2. inspect_ai/_cli/eval.py +35 -2
  3. inspect_ai/_cli/util.py +44 -1
  4. inspect_ai/_display/core/config.py +1 -1
  5. inspect_ai/_display/core/display.py +13 -4
  6. inspect_ai/_display/core/results.py +1 -1
  7. inspect_ai/_display/textual/app.py +14 -3
  8. inspect_ai/_display/textual/display.py +4 -0
  9. inspect_ai/_display/textual/widgets/samples.py +9 -3
  10. inspect_ai/_display/textual/widgets/task_detail.py +8 -8
  11. inspect_ai/_display/textual/widgets/tasks.py +17 -1
  12. inspect_ai/_display/textual/widgets/vscode.py +44 -0
  13. inspect_ai/_eval/eval.py +74 -25
  14. inspect_ai/_eval/evalset.py +22 -18
  15. inspect_ai/_eval/loader.py +34 -11
  16. inspect_ai/_eval/run.py +13 -15
  17. inspect_ai/_eval/score.py +13 -3
  18. inspect_ai/_eval/task/generate.py +8 -9
  19. inspect_ai/_eval/task/log.py +55 -6
  20. inspect_ai/_eval/task/run.py +51 -10
  21. inspect_ai/_eval/task/task.py +23 -9
  22. inspect_ai/_util/constants.py +2 -0
  23. inspect_ai/_util/file.py +30 -1
  24. inspect_ai/_util/json.py +37 -1
  25. inspect_ai/_util/registry.py +1 -0
  26. inspect_ai/_util/vscode.py +37 -0
  27. inspect_ai/_view/server.py +113 -1
  28. inspect_ai/_view/www/App.css +7 -1
  29. inspect_ai/_view/www/dist/assets/index.css +813 -415
  30. inspect_ai/_view/www/dist/assets/index.js +54475 -32003
  31. inspect_ai/_view/www/eslint.config.mjs +1 -1
  32. inspect_ai/_view/www/log-schema.json +137 -31
  33. inspect_ai/_view/www/node_modules/flatted/python/flatted.py +149 -0
  34. inspect_ai/_view/www/package.json +11 -2
  35. inspect_ai/_view/www/src/App.tsx +161 -853
  36. inspect_ai/_view/www/src/api/api-browser.ts +176 -5
  37. inspect_ai/_view/www/src/api/api-vscode.ts +75 -1
  38. inspect_ai/_view/www/src/api/client-api.ts +66 -10
  39. inspect_ai/_view/www/src/api/jsonrpc.ts +2 -0
  40. inspect_ai/_view/www/src/api/types.ts +107 -2
  41. inspect_ai/_view/www/src/appearance/icons.ts +2 -0
  42. inspect_ai/_view/www/src/components/AsciinemaPlayer.tsx +3 -3
  43. inspect_ai/_view/www/src/components/Card.tsx +6 -4
  44. inspect_ai/_view/www/src/components/DownloadPanel.tsx +2 -2
  45. inspect_ai/_view/www/src/components/ExpandablePanel.tsx +56 -61
  46. inspect_ai/_view/www/src/components/FindBand.tsx +17 -9
  47. inspect_ai/_view/www/src/components/HumanBaselineView.tsx +1 -1
  48. inspect_ai/_view/www/src/components/JsonPanel.tsx +14 -24
  49. inspect_ai/_view/www/src/components/LargeModal.tsx +2 -35
  50. inspect_ai/_view/www/src/components/LightboxCarousel.tsx +27 -11
  51. inspect_ai/_view/www/src/components/LinkButton.module.css +16 -0
  52. inspect_ai/_view/www/src/components/LinkButton.tsx +33 -0
  53. inspect_ai/_view/www/src/components/LiveVirtualList.module.css +11 -0
  54. inspect_ai/_view/www/src/components/LiveVirtualList.tsx +177 -0
  55. inspect_ai/_view/www/src/components/MarkdownDiv.tsx +116 -26
  56. inspect_ai/_view/www/src/components/MessageBand.tsx +14 -9
  57. inspect_ai/_view/www/src/components/Modal.module.css +38 -0
  58. inspect_ai/_view/www/src/components/Modal.tsx +77 -0
  59. inspect_ai/_view/www/src/components/MorePopOver.tsx +3 -3
  60. inspect_ai/_view/www/src/components/NavPills.tsx +20 -8
  61. inspect_ai/_view/www/src/components/NoContentsPanel.module.css +12 -0
  62. inspect_ai/_view/www/src/components/NoContentsPanel.tsx +20 -0
  63. inspect_ai/_view/www/src/components/ProgressBar.module.css +5 -4
  64. inspect_ai/_view/www/src/components/ProgressBar.tsx +3 -2
  65. inspect_ai/_view/www/src/components/PulsingDots.module.css +81 -0
  66. inspect_ai/_view/www/src/components/PulsingDots.tsx +45 -0
  67. inspect_ai/_view/www/src/components/TabSet.tsx +4 -37
  68. inspect_ai/_view/www/src/components/ToolButton.tsx +3 -4
  69. inspect_ai/_view/www/src/index.tsx +26 -94
  70. inspect_ai/_view/www/src/logfile/remoteLogFile.ts +9 -1
  71. inspect_ai/_view/www/src/logfile/remoteZipFile.ts +30 -4
  72. inspect_ai/_view/www/src/metadata/RenderedContent.tsx +4 -6
  73. inspect_ai/_view/www/src/plan/DetailStep.module.css +4 -0
  74. inspect_ai/_view/www/src/plan/DetailStep.tsx +6 -3
  75. inspect_ai/_view/www/src/plan/ScorerDetailView.tsx +1 -1
  76. inspect_ai/_view/www/src/plan/SolverDetailView.module.css +2 -1
  77. inspect_ai/_view/www/src/samples/InlineSampleDisplay.module.css +9 -1
  78. inspect_ai/_view/www/src/samples/InlineSampleDisplay.tsx +74 -28
  79. inspect_ai/_view/www/src/samples/SampleDialog.tsx +58 -22
  80. inspect_ai/_view/www/src/samples/SampleDisplay.module.css +4 -0
  81. inspect_ai/_view/www/src/samples/SampleDisplay.tsx +135 -104
  82. inspect_ai/_view/www/src/samples/SampleSummaryView.module.css +10 -0
  83. inspect_ai/_view/www/src/samples/SampleSummaryView.tsx +83 -36
  84. inspect_ai/_view/www/src/samples/SamplesTools.tsx +35 -30
  85. inspect_ai/_view/www/src/samples/chat/ChatMessage.tsx +2 -1
  86. inspect_ai/_view/www/src/samples/chat/ChatMessageRenderer.tsx +1 -1
  87. inspect_ai/_view/www/src/samples/chat/ChatViewVirtualList.tsx +45 -53
  88. inspect_ai/_view/www/src/samples/chat/MessageContent.tsx +6 -1
  89. inspect_ai/_view/www/src/samples/chat/MessageContents.tsx +5 -0
  90. inspect_ai/_view/www/src/samples/chat/messages.ts +36 -0
  91. inspect_ai/_view/www/src/samples/chat/tools/ToolCallView.module.css +3 -0
  92. inspect_ai/_view/www/src/samples/chat/tools/ToolCallView.tsx +11 -1
  93. inspect_ai/_view/www/src/samples/chat/tools/ToolInput.tsx +22 -46
  94. inspect_ai/_view/www/src/samples/descriptor/samplesDescriptor.tsx +34 -20
  95. inspect_ai/_view/www/src/samples/descriptor/score/BooleanScoreDescriptor.module.css +3 -3
  96. inspect_ai/_view/www/src/samples/descriptor/score/BooleanScoreDescriptor.tsx +1 -1
  97. inspect_ai/_view/www/src/samples/descriptor/score/ObjectScoreDescriptor.module.css +4 -4
  98. inspect_ai/_view/www/src/samples/descriptor/score/ObjectScoreDescriptor.tsx +10 -10
  99. inspect_ai/_view/www/src/samples/descriptor/types.ts +6 -5
  100. inspect_ai/_view/www/src/samples/list/SampleFooter.module.css +22 -3
  101. inspect_ai/_view/www/src/samples/list/SampleFooter.tsx +27 -2
  102. inspect_ai/_view/www/src/samples/list/SampleList.tsx +122 -85
  103. inspect_ai/_view/www/src/samples/list/SampleRow.module.css +6 -0
  104. inspect_ai/_view/www/src/samples/list/SampleRow.tsx +28 -15
  105. inspect_ai/_view/www/src/samples/sample-tools/SelectScorer.tsx +29 -18
  106. inspect_ai/_view/www/src/samples/sample-tools/SortFilter.tsx +28 -28
  107. inspect_ai/_view/www/src/samples/sample-tools/sample-filter/SampleFilter.tsx +19 -9
  108. inspect_ai/_view/www/src/samples/sampleDataAdapter.ts +33 -0
  109. inspect_ai/_view/www/src/samples/sampleLimit.ts +2 -2
  110. inspect_ai/_view/www/src/samples/scores/SampleScores.tsx +12 -27
  111. inspect_ai/_view/www/src/samples/scores/SampleScoresGrid.module.css +38 -0
  112. inspect_ai/_view/www/src/samples/scores/SampleScoresGrid.tsx +118 -0
  113. inspect_ai/_view/www/src/samples/scores/{SampleScoreView.module.css → SampleScoresView.module.css} +10 -1
  114. inspect_ai/_view/www/src/samples/scores/SampleScoresView.tsx +78 -0
  115. inspect_ai/_view/www/src/samples/transcript/ErrorEventView.tsx +0 -13
  116. inspect_ai/_view/www/src/samples/transcript/InfoEventView.tsx +0 -13
  117. inspect_ai/_view/www/src/samples/transcript/InputEventView.tsx +0 -13
  118. inspect_ai/_view/www/src/samples/transcript/ModelEventView.module.css +4 -0
  119. inspect_ai/_view/www/src/samples/transcript/ModelEventView.tsx +10 -24
  120. inspect_ai/_view/www/src/samples/transcript/SampleInitEventView.tsx +0 -13
  121. inspect_ai/_view/www/src/samples/transcript/SampleLimitEventView.tsx +4 -22
  122. inspect_ai/_view/www/src/samples/transcript/SandboxEventView.tsx +15 -24
  123. inspect_ai/_view/www/src/samples/transcript/ScoreEventView.tsx +0 -13
  124. inspect_ai/_view/www/src/samples/transcript/StepEventView.tsx +6 -28
  125. inspect_ai/_view/www/src/samples/transcript/SubtaskEventView.tsx +24 -34
  126. inspect_ai/_view/www/src/samples/transcript/ToolEventView.module.css +4 -0
  127. inspect_ai/_view/www/src/samples/transcript/ToolEventView.tsx +33 -17
  128. inspect_ai/_view/www/src/samples/transcript/TranscriptView.tsx +197 -338
  129. inspect_ai/_view/www/src/samples/transcript/TranscriptVirtualListComponent.module.css +16 -0
  130. inspect_ai/_view/www/src/samples/transcript/TranscriptVirtualListComponent.tsx +44 -0
  131. inspect_ai/_view/www/src/samples/transcript/event/EventNav.tsx +7 -4
  132. inspect_ai/_view/www/src/samples/transcript/event/EventPanel.tsx +81 -60
  133. inspect_ai/_view/www/src/samples/transcript/event/EventProgressPanel.module.css +23 -0
  134. inspect_ai/_view/www/src/samples/transcript/event/EventProgressPanel.tsx +27 -0
  135. inspect_ai/_view/www/src/samples/transcript/state/StateEventRenderers.tsx +29 -1
  136. inspect_ai/_view/www/src/samples/transcript/state/StateEventView.tsx +102 -72
  137. inspect_ai/_view/www/src/scoring/utils.ts +87 -0
  138. inspect_ai/_view/www/src/state/appSlice.ts +244 -0
  139. inspect_ai/_view/www/src/state/hooks.ts +399 -0
  140. inspect_ai/_view/www/src/state/logPolling.ts +200 -0
  141. inspect_ai/_view/www/src/state/logSlice.ts +224 -0
  142. inspect_ai/_view/www/src/state/logsPolling.ts +118 -0
  143. inspect_ai/_view/www/src/state/logsSlice.ts +181 -0
  144. inspect_ai/_view/www/src/state/samplePolling.ts +314 -0
  145. inspect_ai/_view/www/src/state/sampleSlice.ts +140 -0
  146. inspect_ai/_view/www/src/state/sampleUtils.ts +21 -0
  147. inspect_ai/_view/www/src/state/scrolling.ts +206 -0
  148. inspect_ai/_view/www/src/state/store.ts +168 -0
  149. inspect_ai/_view/www/src/state/store_filter.ts +84 -0
  150. inspect_ai/_view/www/src/state/utils.ts +23 -0
  151. inspect_ai/_view/www/src/storage/index.ts +26 -0
  152. inspect_ai/_view/www/src/types/log.d.ts +36 -26
  153. inspect_ai/_view/www/src/types/markdown-it-katex.d.ts +21 -0
  154. inspect_ai/_view/www/src/types.ts +94 -32
  155. inspect_ai/_view/www/src/utils/attachments.ts +58 -23
  156. inspect_ai/_view/www/src/utils/json-worker.ts +79 -12
  157. inspect_ai/_view/www/src/utils/logger.ts +52 -0
  158. inspect_ai/_view/www/src/utils/polling.ts +100 -0
  159. inspect_ai/_view/www/src/utils/react.ts +30 -0
  160. inspect_ai/_view/www/src/utils/vscode.ts +1 -1
  161. inspect_ai/_view/www/src/workspace/WorkSpace.tsx +184 -217
  162. inspect_ai/_view/www/src/workspace/WorkSpaceView.tsx +11 -53
  163. inspect_ai/_view/www/src/workspace/navbar/Navbar.tsx +8 -18
  164. inspect_ai/_view/www/src/workspace/navbar/PrimaryBar.module.css +1 -0
  165. inspect_ai/_view/www/src/workspace/navbar/PrimaryBar.tsx +40 -22
  166. inspect_ai/_view/www/src/workspace/navbar/ResultsPanel.module.css +16 -1
  167. inspect_ai/_view/www/src/workspace/navbar/ResultsPanel.tsx +159 -103
  168. inspect_ai/_view/www/src/workspace/navbar/RunningStatusPanel.module.css +32 -0
  169. inspect_ai/_view/www/src/workspace/navbar/RunningStatusPanel.tsx +32 -0
  170. inspect_ai/_view/www/src/workspace/navbar/ScoreGrid.module.css +35 -0
  171. inspect_ai/_view/www/src/workspace/navbar/ScoreGrid.tsx +117 -0
  172. inspect_ai/_view/www/src/workspace/navbar/SecondaryBar.tsx +12 -14
  173. inspect_ai/_view/www/src/workspace/navbar/StatusPanel.tsx +6 -2
  174. inspect_ai/_view/www/src/workspace/sidebar/LogDirectoryTitleView.tsx +4 -4
  175. inspect_ai/_view/www/src/workspace/sidebar/Sidebar.module.css +3 -2
  176. inspect_ai/_view/www/src/workspace/sidebar/Sidebar.tsx +28 -13
  177. inspect_ai/_view/www/src/workspace/tabs/InfoTab.tsx +5 -10
  178. inspect_ai/_view/www/src/workspace/tabs/JsonTab.tsx +4 -4
  179. inspect_ai/_view/www/src/workspace/tabs/RunningNoSamples.module.css +22 -0
  180. inspect_ai/_view/www/src/workspace/tabs/RunningNoSamples.tsx +19 -0
  181. inspect_ai/_view/www/src/workspace/tabs/SamplesTab.tsx +128 -115
  182. inspect_ai/_view/www/src/workspace/tabs/grouping.ts +37 -5
  183. inspect_ai/_view/www/src/workspace/tabs/types.ts +4 -0
  184. inspect_ai/_view/www/src/workspace/types.ts +4 -3
  185. inspect_ai/_view/www/src/workspace/utils.ts +4 -4
  186. inspect_ai/_view/www/vite.config.js +6 -0
  187. inspect_ai/_view/www/yarn.lock +464 -355
  188. inspect_ai/agent/__init__.py +36 -0
  189. inspect_ai/agent/_agent.py +268 -0
  190. inspect_ai/agent/_as_solver.py +72 -0
  191. inspect_ai/agent/_as_tool.py +122 -0
  192. inspect_ai/{solver → agent}/_bridge/bridge.py +23 -37
  193. inspect_ai/{solver → agent}/_bridge/patch.py +9 -8
  194. inspect_ai/agent/_filter.py +46 -0
  195. inspect_ai/agent/_handoff.py +93 -0
  196. inspect_ai/{solver/_human_agent → agent/_human}/agent.py +11 -12
  197. inspect_ai/{solver/_human_agent → agent/_human}/commands/__init__.py +2 -3
  198. inspect_ai/{solver/_human_agent → agent/_human}/commands/clock.py +3 -1
  199. inspect_ai/{solver/_human_agent → agent/_human}/commands/score.py +5 -5
  200. inspect_ai/{solver/_human_agent → agent/_human}/install.py +6 -3
  201. inspect_ai/{solver/_human_agent → agent/_human}/service.py +7 -3
  202. inspect_ai/{solver/_human_agent → agent/_human}/state.py +5 -5
  203. inspect_ai/agent/_react.py +241 -0
  204. inspect_ai/agent/_run.py +36 -0
  205. inspect_ai/agent/_types.py +81 -0
  206. inspect_ai/log/_condense.py +26 -0
  207. inspect_ai/log/_log.py +17 -5
  208. inspect_ai/log/_recorders/buffer/__init__.py +14 -0
  209. inspect_ai/log/_recorders/buffer/buffer.py +30 -0
  210. inspect_ai/log/_recorders/buffer/database.py +685 -0
  211. inspect_ai/log/_recorders/buffer/filestore.py +259 -0
  212. inspect_ai/log/_recorders/buffer/types.py +84 -0
  213. inspect_ai/log/_recorders/eval.py +2 -11
  214. inspect_ai/log/_recorders/types.py +30 -0
  215. inspect_ai/log/_transcript.py +32 -2
  216. inspect_ai/model/__init__.py +7 -1
  217. inspect_ai/model/_call_tools.py +257 -52
  218. inspect_ai/model/_chat_message.py +7 -4
  219. inspect_ai/model/_conversation.py +13 -62
  220. inspect_ai/model/_display.py +85 -0
  221. inspect_ai/model/_generate_config.py +2 -2
  222. inspect_ai/model/_model.py +114 -14
  223. inspect_ai/model/_model_output.py +14 -9
  224. inspect_ai/model/_openai.py +16 -4
  225. inspect_ai/model/_openai_computer_use.py +162 -0
  226. inspect_ai/model/_openai_responses.py +319 -165
  227. inspect_ai/model/_providers/anthropic.py +20 -21
  228. inspect_ai/model/_providers/azureai.py +24 -13
  229. inspect_ai/model/_providers/bedrock.py +1 -7
  230. inspect_ai/model/_providers/cloudflare.py +3 -3
  231. inspect_ai/model/_providers/goodfire.py +2 -6
  232. inspect_ai/model/_providers/google.py +11 -10
  233. inspect_ai/model/_providers/groq.py +6 -3
  234. inspect_ai/model/_providers/hf.py +7 -3
  235. inspect_ai/model/_providers/mistral.py +7 -10
  236. inspect_ai/model/_providers/openai.py +47 -17
  237. inspect_ai/model/_providers/openai_o1.py +11 -4
  238. inspect_ai/model/_providers/openai_responses.py +12 -14
  239. inspect_ai/model/_providers/providers.py +2 -2
  240. inspect_ai/model/_providers/together.py +12 -2
  241. inspect_ai/model/_providers/util/chatapi.py +7 -2
  242. inspect_ai/model/_providers/util/hf_handler.py +4 -2
  243. inspect_ai/model/_providers/util/llama31.py +4 -2
  244. inspect_ai/model/_providers/vertex.py +11 -9
  245. inspect_ai/model/_providers/vllm.py +4 -4
  246. inspect_ai/scorer/__init__.py +2 -0
  247. inspect_ai/scorer/_metrics/__init__.py +2 -0
  248. inspect_ai/scorer/_metrics/grouped.py +84 -0
  249. inspect_ai/scorer/_score.py +26 -6
  250. inspect_ai/solver/__init__.py +2 -2
  251. inspect_ai/solver/_basic_agent.py +22 -9
  252. inspect_ai/solver/_bridge.py +31 -0
  253. inspect_ai/solver/_chain.py +20 -12
  254. inspect_ai/solver/_fork.py +5 -1
  255. inspect_ai/solver/_human_agent.py +52 -0
  256. inspect_ai/solver/_prompt.py +3 -1
  257. inspect_ai/solver/_run.py +59 -0
  258. inspect_ai/solver/_solver.py +14 -4
  259. inspect_ai/solver/_task_state.py +5 -3
  260. inspect_ai/tool/_tool_call.py +15 -8
  261. inspect_ai/tool/_tool_def.py +17 -12
  262. inspect_ai/tool/_tool_support_helpers.py +4 -4
  263. inspect_ai/tool/_tool_with.py +14 -11
  264. inspect_ai/tool/_tools/_bash_session.py +11 -2
  265. inspect_ai/tool/_tools/_computer/_common.py +18 -2
  266. inspect_ai/tool/_tools/_computer/_computer.py +18 -2
  267. inspect_ai/tool/_tools/_computer/_resources/tool/_constants.py +2 -0
  268. inspect_ai/tool/_tools/_computer/_resources/tool/_x11_client.py +17 -0
  269. inspect_ai/tool/_tools/_think.py +1 -1
  270. inspect_ai/tool/_tools/_web_browser/_web_browser.py +103 -62
  271. inspect_ai/util/__init__.py +2 -0
  272. inspect_ai/util/_anyio.py +27 -0
  273. inspect_ai/util/_sandbox/__init__.py +2 -1
  274. inspect_ai/util/_sandbox/context.py +32 -7
  275. inspect_ai/util/_sandbox/docker/cleanup.py +4 -0
  276. inspect_ai/util/_sandbox/docker/compose.py +2 -2
  277. inspect_ai/util/_sandbox/docker/docker.py +12 -1
  278. inspect_ai/util/_store_model.py +30 -7
  279. inspect_ai/util/_subprocess.py +13 -3
  280. inspect_ai/util/_subtask.py +1 -0
  281. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.83.dist-info}/METADATA +1 -1
  282. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.83.dist-info}/RECORD +295 -229
  283. inspect_ai/_view/www/src/samples/scores/SampleScoreView.tsx +0 -169
  284. inspect_ai/_view/www/src/samples/transcript/SampleTranscript.tsx +0 -22
  285. /inspect_ai/{solver → agent}/_bridge/__init__.py +0 -0
  286. /inspect_ai/{solver/_human_agent → agent/_human}/__init__.py +0 -0
  287. /inspect_ai/{solver/_human_agent → agent/_human}/commands/command.py +0 -0
  288. /inspect_ai/{solver/_human_agent → agent/_human}/commands/instructions.py +0 -0
  289. /inspect_ai/{solver/_human_agent → agent/_human}/commands/note.py +0 -0
  290. /inspect_ai/{solver/_human_agent → agent/_human}/commands/status.py +0 -0
  291. /inspect_ai/{solver/_human_agent → agent/_human}/commands/submit.py +0 -0
  292. /inspect_ai/{solver/_human_agent → agent/_human}/panel.py +0 -0
  293. /inspect_ai/{solver/_human_agent → agent/_human}/view.py +0 -0
  294. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.83.dist-info}/WHEEL +0 -0
  295. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.83.dist-info}/entry_points.txt +0 -0
  296. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.83.dist-info}/licenses/LICENSE +0 -0
  297. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.83.dist-info}/top_level.txt +0 -0
@@ -1,15 +1,14 @@
1
1
  import {
2
2
  FC,
3
3
  KeyboardEvent,
4
+ memo,
4
5
  RefObject,
5
6
  useCallback,
6
7
  useEffect,
7
8
  useMemo,
8
9
  useRef,
9
- useState,
10
10
  } from "react";
11
11
  import { Virtuoso, VirtuosoHandle } from "react-virtuoso";
12
- import { EmptyPanel } from "../../components/EmptyPanel";
13
12
  import { MessageBand } from "../../components/MessageBand";
14
13
  import { formatNoDecimal } from "../../utils/format";
15
14
  import { ListItem } from "../../workspace/tabs/types";
@@ -18,6 +17,9 @@ import { SampleRow } from "./SampleRow";
18
17
  import { SampleSeparator } from "./SampleSeparator";
19
18
 
20
19
  import clsx from "clsx";
20
+ import { useProperty, useSampleDescriptor } from "../../state/hooks";
21
+ import { useVirtuosoState } from "../../state/scrolling";
22
+ import { useStore } from "../../state/store";
21
23
  import { SampleFooter } from "./SampleFooter";
22
24
  import { SampleHeader } from "./SampleHeader";
23
25
  import styles from "./SampleList.module.css";
@@ -27,8 +29,8 @@ const kSeparatorHeight = 24;
27
29
 
28
30
  interface SampleListProps {
29
31
  items: ListItem[];
30
- sampleDescriptor: SamplesDescriptor;
31
- selectedIndex: number;
32
+ totalItemCount: number;
33
+ running: boolean;
32
34
  nextSample: () => void;
33
35
  prevSample: () => void;
34
36
  showSample: (index: number) => void;
@@ -36,11 +38,13 @@ interface SampleListProps {
36
38
  listHandle: RefObject<VirtuosoHandle | null>;
37
39
  }
38
40
 
39
- export const SampleList: FC<SampleListProps> = (props) => {
41
+ export const kSampleFollowProp = "sample-list";
42
+
43
+ export const SampleList: FC<SampleListProps> = memo((props) => {
40
44
  const {
41
45
  items,
42
- sampleDescriptor,
43
- selectedIndex,
46
+ totalItemCount,
47
+ running,
44
48
  nextSample,
45
49
  prevSample,
46
50
  showSample,
@@ -48,37 +52,56 @@ export const SampleList: FC<SampleListProps> = (props) => {
48
52
  listHandle,
49
53
  } = props;
50
54
 
51
- const [followOutput, setFollowOutput] = useState(false);
55
+ const { getRestoreState, isScrolling } = useVirtuosoState(
56
+ listHandle,
57
+ "sample-list",
58
+ );
52
59
 
53
- const [hidden, setHidden] = useState(false);
54
- useEffect(() => {
55
- setHidden(false);
56
- }, [items]);
60
+ const selectedSampleIndex = useStore(
61
+ (state) => state.log.selectedSampleIndex,
62
+ );
63
+ const samplesDescriptor = useSampleDescriptor();
64
+ const [followOutput, setFollowOutput] = useProperty(
65
+ kSampleFollowProp,
66
+ "follow",
67
+ {
68
+ defaultValue: !!running,
69
+ },
70
+ );
57
71
 
58
- // Keep a mapping of the indexes to items (skipping separators)
59
- const itemRowMapping = useMemo(() => {
60
- const rowIndexes: number[] = [];
61
- items.forEach((item, index) => {
62
- if (item.type === "sample") {
63
- rowIndexes.push(index);
64
- }
65
- });
66
- return rowIndexes;
67
- }, [items]);
72
+ // Track whether we were previously running so we can
73
+ // decide whether to pop up to the top
74
+ const prevRunningRef = useRef(running);
68
75
 
69
- const prevSelectedIndexRef = useRef<number>(null);
70
76
  useEffect(() => {
71
- const listEl = listHandle.current;
72
- if (listEl) {
73
- requestAnimationFrame(() => {
74
- setTimeout(() => {
75
- const actualRowIndex = itemRowMapping[selectedIndex];
76
- listEl.scrollToIndex(actualRowIndex);
77
- prevSelectedIndexRef.current = actualRowIndex;
78
- }, 10);
79
- });
77
+ // When we finish running, if we are following output
78
+ // then scroll up to the top
79
+ if (
80
+ !running &&
81
+ prevRunningRef.current &&
82
+ followOutput &&
83
+ listHandle.current
84
+ ) {
85
+ setFollowOutput(false);
86
+ setTimeout(() => {
87
+ if (listHandle.current) {
88
+ listHandle.current.scrollTo({ top: 0, behavior: "instant" });
89
+ }
90
+ }, 100);
80
91
  }
81
- }, [selectedIndex, listHandle, itemRowMapping]);
92
+ prevRunningRef.current = running;
93
+ }, [running, followOutput, listHandle]);
94
+
95
+ const loaded = useRef(false);
96
+ const handleAtBottomStateChange = useCallback(
97
+ (atBottom: boolean) => {
98
+ if (loaded.current && running) {
99
+ setFollowOutput(atBottom);
100
+ }
101
+ loaded.current = true;
102
+ },
103
+ [running, setFollowOutput, followOutput],
104
+ );
82
105
 
83
106
  const onkeydown = useCallback(
84
107
  (e: KeyboardEvent<HTMLDivElement>) => {
@@ -94,48 +117,51 @@ export const SampleList: FC<SampleListProps> = (props) => {
94
117
  e.stopPropagation();
95
118
  break;
96
119
  case "Enter":
97
- showSample(selectedIndex);
120
+ showSample(selectedSampleIndex);
98
121
  e.preventDefault();
99
122
  e.stopPropagation();
100
123
  break;
101
124
  }
102
125
  },
103
- [selectedIndex, nextSample, prevSample, showSample],
126
+ [selectedSampleIndex, nextSample, prevSample, showSample],
104
127
  );
105
128
 
106
- // If there are no samples, just display an empty state
107
- if (items.length === 0) {
108
- return <EmptyPanel>No Samples</EmptyPanel>;
109
- }
129
+ const gridColumnsTemplate = useMemo(() => {
130
+ return gridColumnsValue(samplesDescriptor);
131
+ }, [samplesDescriptor]);
110
132
 
111
- const renderRow = (item: ListItem) => {
112
- if (item.type === "sample") {
113
- return (
114
- <SampleRow
115
- id={`${item.number}`}
116
- index={item.index}
117
- sample={item.data}
118
- height={kSampleHeight}
119
- sampleDescriptor={sampleDescriptor}
120
- gridColumnsTemplate={gridColumnsValue(sampleDescriptor)}
121
- selected={selectedIndex === item.index}
122
- showSample={showSample}
123
- />
124
- );
125
- } else if (item.type === "separator") {
126
- return (
127
- <SampleSeparator
128
- id={`sample-group${item.number}`}
129
- title={item.data}
130
- height={kSeparatorHeight}
131
- />
132
- );
133
- } else {
134
- return null;
135
- }
136
- };
133
+ const renderRow = useCallback(
134
+ (_index: number, item: ListItem) => {
135
+ if (item.type === "sample") {
136
+ return (
137
+ <SampleRow
138
+ id={`${item.number}`}
139
+ index={item.index}
140
+ sample={item.data}
141
+ height={kSampleHeight}
142
+ answer={item.answer}
143
+ completed={item.completed}
144
+ scoreRendered={item.scoreRendered}
145
+ gridColumnsTemplate={gridColumnsTemplate}
146
+ showSample={showSample}
147
+ />
148
+ );
149
+ } else if (item.type === "separator") {
150
+ return (
151
+ <SampleSeparator
152
+ id={`sample-group${item.number}`}
153
+ title={item.data}
154
+ height={kSeparatorHeight}
155
+ />
156
+ );
157
+ } else {
158
+ return null;
159
+ }
160
+ },
161
+ [showSample, gridColumnsTemplate],
162
+ );
137
163
 
138
- const { input, limit, answer, target } = gridColumns(sampleDescriptor);
164
+ const { input, limit, answer, target } = gridColumns(samplesDescriptor);
139
165
 
140
166
  const sampleCount = items?.reduce((prev, current) => {
141
167
  if (current.type === "sample") {
@@ -176,68 +202,79 @@ export const SampleList: FC<SampleListProps> = (props) => {
176
202
  <div className={styles.mainLayout}>
177
203
  {warningMessage ? (
178
204
  <MessageBand
205
+ id={"sample-warning-message"}
179
206
  message={warningMessage}
180
- hidden={hidden}
181
- setHidden={setHidden}
182
207
  type="info"
183
208
  />
184
209
  ) : undefined}
185
-
186
210
  <SampleHeader
187
211
  input={input !== "0"}
188
212
  target={target !== "0"}
189
213
  answer={answer !== "0"}
190
214
  limit={limit !== "0"}
191
- gridColumnsTemplate={gridColumnsValue(sampleDescriptor)}
215
+ gridColumnsTemplate={gridColumnsTemplate}
192
216
  />
193
217
  <Virtuoso
194
218
  ref={listHandle}
195
219
  style={{ height: "100%" }}
196
220
  data={items}
197
221
  defaultItemHeight={50}
198
- itemContent={(_index: number, data: ListItem) => {
199
- return renderRow(data);
222
+ itemContent={renderRow}
223
+ followOutput={(_atBottom: boolean) => {
224
+ return followOutput;
200
225
  }}
201
- followOutput={followOutput}
202
- atBottomStateChange={(atBottom: boolean) => {
203
- setFollowOutput(atBottom);
226
+ atBottomStateChange={handleAtBottomStateChange}
227
+ atBottomThreshold={30}
228
+ increaseViewportBy={{ top: 300, bottom: 300 }}
229
+ overscan={{
230
+ main: 10,
231
+ reverse: 10,
204
232
  }}
205
233
  className={clsx(className)}
206
234
  onKeyDown={onkeydown}
207
235
  skipAnimationFrameInResizeObserver={true}
236
+ isScrolling={isScrolling}
237
+ restoreStateFrom={getRestoreState()}
238
+ />
239
+ <SampleFooter
240
+ sampleCount={sampleCount}
241
+ totalSampleCount={totalItemCount}
242
+ running={running}
208
243
  />
209
- <SampleFooter sampleCount={sampleCount} />
210
244
  </div>
211
245
  );
212
- };
246
+ });
213
247
 
214
- const gridColumnsValue = (sampleDescriptor: SamplesDescriptor) => {
248
+ const gridColumnsValue = (sampleDescriptor?: SamplesDescriptor) => {
215
249
  const { input, target, answer, limit, id, score } =
216
250
  gridColumns(sampleDescriptor);
217
251
  return `${id} ${input} ${target} ${answer} ${limit} ${score}`;
218
252
  };
219
253
 
220
- const gridColumns = (sampleDescriptor: SamplesDescriptor) => {
254
+ const gridColumns = (sampleDescriptor?: SamplesDescriptor) => {
221
255
  const input =
222
- sampleDescriptor?.messageShape.normalized.input > 0
256
+ sampleDescriptor && sampleDescriptor.messageShape.normalized.input > 0
223
257
  ? Math.max(0.15, sampleDescriptor.messageShape.normalized.input)
224
258
  : 0;
225
259
  const target =
226
- sampleDescriptor?.messageShape.normalized.target > 0
260
+ sampleDescriptor && sampleDescriptor.messageShape.normalized.target > 0
227
261
  ? Math.max(0.15, sampleDescriptor.messageShape.normalized.target)
228
262
  : 0;
229
263
  const answer =
230
- sampleDescriptor?.messageShape.normalized.answer > 0
264
+ sampleDescriptor && sampleDescriptor.messageShape.normalized.answer > 0
231
265
  ? Math.max(0.15, sampleDescriptor.messageShape.normalized.answer)
232
266
  : 0;
233
267
  const limit =
234
- sampleDescriptor?.messageShape.normalized.limit > 0
268
+ sampleDescriptor && sampleDescriptor.messageShape.normalized.limit > 0
235
269
  ? Math.max(0.15, sampleDescriptor.messageShape.normalized.limit)
236
270
  : 0;
237
- const id = Math.max(2, Math.min(10, sampleDescriptor?.messageShape.raw.id));
271
+ const id = Math.max(
272
+ 2,
273
+ Math.min(10, sampleDescriptor?.messageShape.raw.id || 0),
274
+ );
238
275
  const score = Math.max(
239
276
  3,
240
- Math.min(10, sampleDescriptor?.messageShape.raw.score),
277
+ Math.min(10, sampleDescriptor?.messageShape.raw.score || 0),
241
278
  );
242
279
 
243
280
  const frSize = (val: number) => {
@@ -31,3 +31,9 @@
31
31
  display: flex;
32
32
  justify-self: center;
33
33
  }
34
+
35
+ .spinner {
36
+ height: 1.4em;
37
+ width: 1.4em;
38
+ color: var(--bs-focus-ring-color);
39
+ }
@@ -1,9 +1,10 @@
1
1
  import clsx from "clsx";
2
- import { FC } from "react";
2
+ import { FC, ReactNode, useCallback } from "react";
3
3
  import { SampleSummary } from "../../api/types";
4
4
  import { MarkdownDiv } from "../../components/MarkdownDiv";
5
+ import { PulsingDots } from "../../components/PulsingDots";
6
+ import { useStore } from "../../state/store";
5
7
  import { arrayToString, inputString } from "../../utils/format";
6
- import { SamplesDescriptor } from "../descriptor/samplesDescriptor";
7
8
  import { SampleErrorView } from "../error/SampleErrorView";
8
9
  import styles from "./SampleRow.module.css";
9
10
 
@@ -11,10 +12,11 @@ interface SampleRowProps {
11
12
  id: string;
12
13
  index: number;
13
14
  sample: SampleSummary;
14
- sampleDescriptor: SamplesDescriptor;
15
+ answer: string;
16
+ completed: boolean;
17
+ scoreRendered: ReactNode;
15
18
  gridColumnsTemplate: string;
16
19
  height: number;
17
- selected: boolean;
18
20
  showSample: (index: number) => void;
19
21
  }
20
22
 
@@ -22,22 +24,33 @@ export const SampleRow: FC<SampleRowProps> = ({
22
24
  id,
23
25
  index,
24
26
  sample,
25
- sampleDescriptor,
27
+ answer,
28
+ completed,
29
+ scoreRendered,
26
30
  gridColumnsTemplate,
27
31
  height,
28
- selected,
29
32
  showSample,
30
33
  }) => {
34
+ const streamSampleData = useStore(
35
+ (state) => state.capabilities.streamSampleData,
36
+ );
37
+ const selectedSampleIndex = useStore(
38
+ (state) => state.log.selectedSampleIndex,
39
+ );
40
+ const handleClick = useCallback(() => {
41
+ if (completed || streamSampleData) {
42
+ showSample(index);
43
+ }
44
+ }, [index, showSample, completed]);
45
+
31
46
  return (
32
47
  <div
33
48
  id={`sample-${id}`}
34
- onClick={() => {
35
- showSample(index);
36
- }}
49
+ onClick={handleClick}
37
50
  className={clsx(
38
51
  styles.grid,
39
52
  "text-size-base",
40
- selected ? styles.selected : undefined,
53
+ selectedSampleIndex === index ? styles.selected : undefined,
41
54
  )}
42
55
  style={{
43
56
  height: `${height}px`,
@@ -56,7 +69,7 @@ export const SampleRow: FC<SampleRowProps> = ({
56
69
  styles.wrapAnywhere,
57
70
  )}
58
71
  >
59
- {inputString(sample.input).join(" ")}
72
+ <MarkdownDiv markdown={inputString(sample.input).join(" ")} />
60
73
  </div>
61
74
  <div className={clsx("sample-target", "three-line-clamp", styles.cell)}>
62
75
  <MarkdownDiv
@@ -67,9 +80,7 @@ export const SampleRow: FC<SampleRowProps> = ({
67
80
  <div className={clsx("sample-answer", "three-line-clamp", styles.cell)}>
68
81
  {sample ? (
69
82
  <MarkdownDiv
70
- markdown={sampleDescriptor
71
- ?.selectedScorerDescriptor(sample)
72
- .answer()}
83
+ markdown={answer || ""}
73
84
  className={clsx("no-last-para-padding", styles.noLeft)}
74
85
  />
75
86
  ) : (
@@ -90,8 +101,10 @@ export const SampleRow: FC<SampleRowProps> = ({
90
101
  <div className={clsx("text-size-small", styles.cell, styles.score)}>
91
102
  {sample.error ? (
92
103
  <SampleErrorView message={sample.error} />
104
+ ) : completed ? (
105
+ scoreRendered
93
106
  ) : (
94
- sampleDescriptor?.selectedScore(sample)?.render()
107
+ <PulsingDots />
95
108
  )}
96
109
  </div>
97
110
  </div>
@@ -1,7 +1,7 @@
1
1
  import clsx from "clsx";
2
2
  import { ScoreLabel } from "../../types";
3
3
 
4
- import { FC } from "react";
4
+ import { ChangeEvent, FC, useCallback } from "react";
5
5
  import styles from "./SelectScorer.module.css";
6
6
 
7
7
  interface SelectScorerProps {
@@ -26,6 +26,13 @@ export const SelectScorer: FC<SelectScorerProps> = ({
26
26
  return accum;
27
27
  }, [] as ScoreLabel[]);
28
28
 
29
+ const handleSelectScore = useCallback(
30
+ (index: number) => {
31
+ setScore(scores[index]);
32
+ },
33
+ [setScore, scores],
34
+ );
35
+
29
36
  if (scorers.length === 1) {
30
37
  // There is only a single scorer in play, just show the list of available scores
31
38
  return (
@@ -44,9 +51,7 @@ export const SelectScorer: FC<SelectScorerProps> = ({
44
51
  <ScoreSelector
45
52
  scores={scores}
46
53
  selectedIndex={scoreIndex(scores, score)}
47
- setSelectedIndex={(index: number) => {
48
- setScore(scores[index]);
49
- }}
54
+ setSelectedIndex={handleSelectScore}
50
55
  />
51
56
  </div>
52
57
  );
@@ -75,18 +80,14 @@ export const SelectScorer: FC<SelectScorerProps> = ({
75
80
  <ScorerSelector
76
81
  scorers={scorers}
77
82
  selectedIndex={scorerIndex(scorers, score)}
78
- setSelectedIndex={(index: number) => {
79
- setScore(scorers[index]);
80
- }}
83
+ setSelectedIndex={handleSelectScore}
81
84
  />
82
85
  {scorerScores.length > 1 ? (
83
86
  <ScoreSelector
84
87
  className={clsx(styles.secondSel)}
85
88
  scores={scorerScores}
86
89
  selectedIndex={scoreIndex(scorerScores, score)}
87
- setSelectedIndex={(index: number) => {
88
- setScore(scorerScores[index]);
89
- }}
90
+ setSelectedIndex={handleSelectScore}
90
91
  />
91
92
  ) : undefined}
92
93
  </div>
@@ -107,6 +108,14 @@ const ScoreSelector: FC<ScoreSelectorProps> = ({
107
108
  setSelectedIndex,
108
109
  className,
109
110
  }) => {
111
+ const handleChange = useCallback(
112
+ (e: ChangeEvent<HTMLSelectElement>) => {
113
+ const sel = e.target as HTMLSelectElement;
114
+ setSelectedIndex(sel.selectedIndex);
115
+ },
116
+ [setSelectedIndex],
117
+ );
118
+
110
119
  return (
111
120
  <select
112
121
  className={clsx(
@@ -117,10 +126,7 @@ const ScoreSelector: FC<ScoreSelectorProps> = ({
117
126
  )}
118
127
  aria-label=".select-scorer-label"
119
128
  value={scores[selectedIndex].name}
120
- onChange={(e) => {
121
- const sel = e.target as HTMLSelectElement;
122
- setSelectedIndex(sel.selectedIndex);
123
- }}
129
+ onChange={handleChange}
124
130
  >
125
131
  {scores.map((score) => {
126
132
  return (
@@ -144,15 +150,20 @@ const ScorerSelector: FC<ScorerSelectorProps> = ({
144
150
  selectedIndex,
145
151
  setSelectedIndex,
146
152
  }) => {
153
+ const handleChange = useCallback(
154
+ (e: ChangeEvent<HTMLSelectElement>) => {
155
+ const sel = e.target as HTMLSelectElement;
156
+ setSelectedIndex(sel.selectedIndex);
157
+ },
158
+ [setSelectedIndex],
159
+ );
160
+
147
161
  return (
148
162
  <select
149
163
  className={clsx("form-select", "form-select-sm", "text-size-smaller")}
150
164
  aria-label=".epoch-filter-label"
151
165
  value={scorers[selectedIndex].scorer}
152
- onChange={(e) => {
153
- const sel = e.target as HTMLSelectElement;
154
- setSelectedIndex(sel.selectedIndex);
155
- }}
166
+ onChange={handleChange}
156
167
  >
157
168
  {scorers.map((scorer) => {
158
169
  return (
@@ -1,5 +1,5 @@
1
1
  import clsx from "clsx";
2
- import { FC } from "react";
2
+ import { ChangeEvent, FC, useCallback } from "react";
3
3
  import { SampleSummary } from "../../api/types";
4
4
  import {
5
5
  kEpochAscVal,
@@ -9,6 +9,7 @@ import {
9
9
  kScoreAscVal,
10
10
  kScoreDescVal,
11
11
  } from "../../constants";
12
+ import { ScoreLabel } from "../../types";
12
13
  import { isNumeric } from "../../utils/type";
13
14
  import { SamplesDescriptor } from "../descriptor/samplesDescriptor";
14
15
  import styles from "./SortFilter.module.css";
@@ -42,6 +43,15 @@ export const SortFilter: FC<SortFilterProps> = ({ sort, setSort, epochs }) => {
42
43
  label: "score desc",
43
44
  val: kScoreDescVal,
44
45
  });
46
+
47
+ const handleChange = useCallback(
48
+ (e: ChangeEvent<HTMLSelectElement>) => {
49
+ const sel = e.target as HTMLSelectElement;
50
+ setSort(sel.value);
51
+ },
52
+ [setSort],
53
+ );
54
+
45
55
  return (
46
56
  <div className={styles.flex}>
47
57
  <span
@@ -59,10 +69,7 @@ export const SortFilter: FC<SortFilterProps> = ({ sort, setSort, epochs }) => {
59
69
  className={clsx("form-select", "form-select-sm", "text-size-smaller")}
60
70
  aria-label=".sort-filter-label"
61
71
  value={sort}
62
- onChange={(e) => {
63
- const sel = e.target as HTMLSelectElement;
64
- setSort(sel.value);
65
- }}
72
+ onChange={handleChange}
66
73
  >
67
74
  {options.map((option) => {
68
75
  return (
@@ -102,8 +109,13 @@ export const sortSamples = (
102
109
  sort: string,
103
110
  samples: SampleSummary[],
104
111
  samplesDescriptor: SamplesDescriptor,
105
- ): { sorted: SampleSummary[]; order: "asc" | "desc" } => {
112
+ score?: ScoreLabel,
113
+ ): SampleSummary[] => {
106
114
  const sortedSamples = samples.sort((a: SampleSummary, b: SampleSummary) => {
115
+ const scoreDescriptor = score
116
+ ? samplesDescriptor.evalDescriptor.scoreDescriptor(score)
117
+ : undefined;
118
+
107
119
  switch (sort) {
108
120
  case kSampleAscVal: {
109
121
  const result = sortId(a, b);
@@ -134,50 +146,38 @@ export const sortSamples = (
134
146
  if (result !== 0) {
135
147
  return result;
136
148
  } else {
137
- return sortId(a, b);
149
+ return sortId(b, a);
138
150
  }
139
151
  }
140
152
 
141
153
  case kScoreAscVal: {
142
- const aScore = samplesDescriptor.selectedScore(a);
143
- const bScore = samplesDescriptor.selectedScore(b);
154
+ const aScore = samplesDescriptor.evalDescriptor.score(a, score);
155
+ const bScore = samplesDescriptor.evalDescriptor.score(b, score);
144
156
  if (
145
157
  aScore === undefined ||
146
158
  bScore === undefined ||
147
- samplesDescriptor.selectedScoreDescriptor == undefined
159
+ scoreDescriptor === undefined
148
160
  ) {
149
161
  return 0;
150
162
  }
151
- return samplesDescriptor.selectedScoreDescriptor.compare(
152
- aScore,
153
- bScore,
154
- );
163
+ return scoreDescriptor?.compare(aScore, bScore);
155
164
  }
156
165
  case kScoreDescVal: {
157
- const aScore = samplesDescriptor.selectedScore(a);
158
- const bScore = samplesDescriptor.selectedScore(b);
166
+ const aScore = samplesDescriptor.evalDescriptor.score(a, score);
167
+ const bScore = samplesDescriptor.evalDescriptor.score(b, score);
159
168
  if (
160
169
  aScore === undefined ||
161
170
  bScore === undefined ||
162
- samplesDescriptor.selectedScoreDescriptor == undefined
171
+ scoreDescriptor == undefined
163
172
  ) {
164
173
  return 0;
165
174
  }
166
175
 
167
- return samplesDescriptor.selectedScoreDescriptor.compare(
168
- bScore,
169
- aScore,
170
- );
176
+ return scoreDescriptor?.compare(bScore, aScore);
171
177
  }
172
178
  default:
173
179
  return 0;
174
180
  }
175
181
  });
176
- return {
177
- sorted: sortedSamples,
178
- order:
179
- sort === kSampleAscVal || sort === kEpochAscVal || sort === kScoreAscVal
180
- ? "asc"
181
- : "desc",
182
- };
182
+ return sortedSamples;
183
183
  };