inspect-ai 0.3.80__py3-none-any.whl → 0.3.82__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 (179) hide show
  1. inspect_ai/_cli/eval.py +35 -2
  2. inspect_ai/_cli/util.py +44 -1
  3. inspect_ai/_display/core/config.py +1 -1
  4. inspect_ai/_display/core/display.py +13 -4
  5. inspect_ai/_display/core/results.py +1 -1
  6. inspect_ai/_display/textual/widgets/task_detail.py +5 -4
  7. inspect_ai/_eval/eval.py +38 -1
  8. inspect_ai/_eval/evalset.py +5 -0
  9. inspect_ai/_eval/run.py +5 -2
  10. inspect_ai/_eval/task/log.py +53 -6
  11. inspect_ai/_eval/task/run.py +51 -10
  12. inspect_ai/_util/constants.py +2 -0
  13. inspect_ai/_util/file.py +17 -1
  14. inspect_ai/_util/json.py +36 -1
  15. inspect_ai/_view/server.py +113 -1
  16. inspect_ai/_view/www/App.css +1 -1
  17. inspect_ai/_view/www/dist/assets/index.css +518 -296
  18. inspect_ai/_view/www/dist/assets/index.js +38803 -36307
  19. inspect_ai/_view/www/eslint.config.mjs +1 -1
  20. inspect_ai/_view/www/log-schema.json +13 -0
  21. inspect_ai/_view/www/node_modules/flatted/python/flatted.py +149 -0
  22. inspect_ai/_view/www/package.json +8 -2
  23. inspect_ai/_view/www/src/App.tsx +151 -855
  24. inspect_ai/_view/www/src/api/api-browser.ts +176 -5
  25. inspect_ai/_view/www/src/api/api-vscode.ts +75 -1
  26. inspect_ai/_view/www/src/api/client-api.ts +66 -10
  27. inspect_ai/_view/www/src/api/jsonrpc.ts +2 -0
  28. inspect_ai/_view/www/src/api/types.ts +107 -2
  29. inspect_ai/_view/www/src/appearance/icons.ts +1 -0
  30. inspect_ai/_view/www/src/components/AsciinemaPlayer.tsx +3 -3
  31. inspect_ai/_view/www/src/components/DownloadPanel.tsx +2 -2
  32. inspect_ai/_view/www/src/components/ExpandablePanel.tsx +56 -61
  33. inspect_ai/_view/www/src/components/FindBand.tsx +17 -9
  34. inspect_ai/_view/www/src/components/HumanBaselineView.tsx +1 -1
  35. inspect_ai/_view/www/src/components/JsonPanel.tsx +14 -24
  36. inspect_ai/_view/www/src/components/LargeModal.tsx +2 -35
  37. inspect_ai/_view/www/src/components/LightboxCarousel.tsx +27 -11
  38. inspect_ai/_view/www/src/components/LiveVirtualList.module.css +11 -0
  39. inspect_ai/_view/www/src/components/LiveVirtualList.tsx +177 -0
  40. inspect_ai/_view/www/src/components/MarkdownDiv.tsx +3 -3
  41. inspect_ai/_view/www/src/components/MessageBand.tsx +14 -9
  42. inspect_ai/_view/www/src/components/MorePopOver.tsx +3 -3
  43. inspect_ai/_view/www/src/components/NavPills.tsx +20 -8
  44. inspect_ai/_view/www/src/components/NoContentsPanel.module.css +12 -0
  45. inspect_ai/_view/www/src/components/NoContentsPanel.tsx +20 -0
  46. inspect_ai/_view/www/src/components/ProgressBar.module.css +5 -4
  47. inspect_ai/_view/www/src/components/ProgressBar.tsx +3 -2
  48. inspect_ai/_view/www/src/components/PulsingDots.module.css +81 -0
  49. inspect_ai/_view/www/src/components/PulsingDots.tsx +45 -0
  50. inspect_ai/_view/www/src/components/TabSet.tsx +4 -37
  51. inspect_ai/_view/www/src/components/ToolButton.tsx +3 -4
  52. inspect_ai/_view/www/src/index.tsx +26 -94
  53. inspect_ai/_view/www/src/logfile/remoteLogFile.ts +9 -1
  54. inspect_ai/_view/www/src/logfile/remoteZipFile.ts +30 -4
  55. inspect_ai/_view/www/src/metadata/RenderedContent.tsx +4 -6
  56. inspect_ai/_view/www/src/plan/ScorerDetailView.tsx +1 -1
  57. inspect_ai/_view/www/src/samples/InlineSampleDisplay.module.css +9 -1
  58. inspect_ai/_view/www/src/samples/InlineSampleDisplay.tsx +67 -28
  59. inspect_ai/_view/www/src/samples/SampleDialog.tsx +51 -22
  60. inspect_ai/_view/www/src/samples/SampleDisplay.module.css +4 -0
  61. inspect_ai/_view/www/src/samples/SampleDisplay.tsx +144 -90
  62. inspect_ai/_view/www/src/samples/SampleSummaryView.module.css +4 -0
  63. inspect_ai/_view/www/src/samples/SampleSummaryView.tsx +82 -35
  64. inspect_ai/_view/www/src/samples/SamplesTools.tsx +23 -30
  65. inspect_ai/_view/www/src/samples/chat/ChatMessage.tsx +2 -1
  66. inspect_ai/_view/www/src/samples/chat/ChatMessageRenderer.tsx +1 -1
  67. inspect_ai/_view/www/src/samples/chat/ChatViewVirtualList.tsx +45 -53
  68. inspect_ai/_view/www/src/samples/chat/MessageContent.tsx +4 -1
  69. inspect_ai/_view/www/src/samples/chat/MessageContents.tsx +3 -0
  70. inspect_ai/_view/www/src/samples/chat/messages.ts +34 -0
  71. inspect_ai/_view/www/src/samples/chat/tools/ToolCallView.module.css +3 -0
  72. inspect_ai/_view/www/src/samples/chat/tools/ToolCallView.tsx +10 -1
  73. inspect_ai/_view/www/src/samples/chat/tools/ToolInput.tsx +22 -46
  74. inspect_ai/_view/www/src/samples/descriptor/samplesDescriptor.tsx +25 -17
  75. inspect_ai/_view/www/src/samples/descriptor/score/ObjectScoreDescriptor.tsx +2 -1
  76. inspect_ai/_view/www/src/samples/descriptor/types.ts +6 -5
  77. inspect_ai/_view/www/src/samples/list/SampleFooter.module.css +21 -3
  78. inspect_ai/_view/www/src/samples/list/SampleFooter.tsx +20 -1
  79. inspect_ai/_view/www/src/samples/list/SampleList.tsx +105 -85
  80. inspect_ai/_view/www/src/samples/list/SampleRow.module.css +6 -0
  81. inspect_ai/_view/www/src/samples/list/SampleRow.tsx +27 -14
  82. inspect_ai/_view/www/src/samples/sample-tools/SelectScorer.tsx +29 -18
  83. inspect_ai/_view/www/src/samples/sample-tools/SortFilter.tsx +28 -28
  84. inspect_ai/_view/www/src/samples/sample-tools/sample-filter/SampleFilter.tsx +19 -9
  85. inspect_ai/_view/www/src/samples/sampleDataAdapter.ts +33 -0
  86. inspect_ai/_view/www/src/samples/sampleLimit.ts +2 -2
  87. inspect_ai/_view/www/src/samples/scores/SampleScoreView.tsx +7 -9
  88. inspect_ai/_view/www/src/samples/scores/SampleScores.tsx +7 -11
  89. inspect_ai/_view/www/src/samples/transcript/ErrorEventView.tsx +0 -13
  90. inspect_ai/_view/www/src/samples/transcript/InfoEventView.tsx +0 -13
  91. inspect_ai/_view/www/src/samples/transcript/InputEventView.tsx +0 -13
  92. inspect_ai/_view/www/src/samples/transcript/ModelEventView.module.css +4 -0
  93. inspect_ai/_view/www/src/samples/transcript/ModelEventView.tsx +10 -24
  94. inspect_ai/_view/www/src/samples/transcript/SampleInitEventView.tsx +0 -13
  95. inspect_ai/_view/www/src/samples/transcript/SampleLimitEventView.tsx +4 -22
  96. inspect_ai/_view/www/src/samples/transcript/SandboxEventView.tsx +15 -24
  97. inspect_ai/_view/www/src/samples/transcript/ScoreEventView.tsx +0 -13
  98. inspect_ai/_view/www/src/samples/transcript/StepEventView.tsx +6 -28
  99. inspect_ai/_view/www/src/samples/transcript/SubtaskEventView.tsx +24 -34
  100. inspect_ai/_view/www/src/samples/transcript/ToolEventView.module.css +4 -0
  101. inspect_ai/_view/www/src/samples/transcript/ToolEventView.tsx +8 -13
  102. inspect_ai/_view/www/src/samples/transcript/TranscriptView.tsx +197 -338
  103. inspect_ai/_view/www/src/samples/transcript/TranscriptVirtualListComponent.module.css +16 -0
  104. inspect_ai/_view/www/src/samples/transcript/TranscriptVirtualListComponent.tsx +44 -0
  105. inspect_ai/_view/www/src/samples/transcript/event/EventNav.tsx +7 -4
  106. inspect_ai/_view/www/src/samples/transcript/event/EventPanel.tsx +52 -58
  107. inspect_ai/_view/www/src/samples/transcript/event/EventProgressPanel.module.css +23 -0
  108. inspect_ai/_view/www/src/samples/transcript/event/EventProgressPanel.tsx +27 -0
  109. inspect_ai/_view/www/src/samples/transcript/state/StateEventRenderers.tsx +30 -1
  110. inspect_ai/_view/www/src/samples/transcript/state/StateEventView.tsx +102 -72
  111. inspect_ai/_view/www/src/scoring/utils.ts +87 -0
  112. inspect_ai/_view/www/src/state/appSlice.ts +244 -0
  113. inspect_ai/_view/www/src/state/hooks.ts +397 -0
  114. inspect_ai/_view/www/src/state/logPolling.ts +196 -0
  115. inspect_ai/_view/www/src/state/logSlice.ts +214 -0
  116. inspect_ai/_view/www/src/state/logsPolling.ts +118 -0
  117. inspect_ai/_view/www/src/state/logsSlice.ts +181 -0
  118. inspect_ai/_view/www/src/state/samplePolling.ts +311 -0
  119. inspect_ai/_view/www/src/state/sampleSlice.ts +127 -0
  120. inspect_ai/_view/www/src/state/sampleUtils.ts +21 -0
  121. inspect_ai/_view/www/src/state/scrolling.ts +206 -0
  122. inspect_ai/_view/www/src/state/store.ts +168 -0
  123. inspect_ai/_view/www/src/state/store_filter.ts +84 -0
  124. inspect_ai/_view/www/src/state/utils.ts +23 -0
  125. inspect_ai/_view/www/src/storage/index.ts +26 -0
  126. inspect_ai/_view/www/src/types/log.d.ts +2 -0
  127. inspect_ai/_view/www/src/types.ts +94 -32
  128. inspect_ai/_view/www/src/utils/attachments.ts +58 -23
  129. inspect_ai/_view/www/src/utils/logger.ts +52 -0
  130. inspect_ai/_view/www/src/utils/polling.ts +100 -0
  131. inspect_ai/_view/www/src/utils/react.ts +30 -0
  132. inspect_ai/_view/www/src/utils/vscode.ts +1 -1
  133. inspect_ai/_view/www/src/workspace/WorkSpace.tsx +181 -216
  134. inspect_ai/_view/www/src/workspace/WorkSpaceView.tsx +11 -53
  135. inspect_ai/_view/www/src/workspace/navbar/Navbar.tsx +8 -18
  136. inspect_ai/_view/www/src/workspace/navbar/PrimaryBar.module.css +1 -0
  137. inspect_ai/_view/www/src/workspace/navbar/PrimaryBar.tsx +40 -22
  138. inspect_ai/_view/www/src/workspace/navbar/ResultsPanel.module.css +0 -1
  139. inspect_ai/_view/www/src/workspace/navbar/ResultsPanel.tsx +98 -39
  140. inspect_ai/_view/www/src/workspace/navbar/RunningStatusPanel.module.css +32 -0
  141. inspect_ai/_view/www/src/workspace/navbar/RunningStatusPanel.tsx +32 -0
  142. inspect_ai/_view/www/src/workspace/navbar/SecondaryBar.tsx +11 -13
  143. inspect_ai/_view/www/src/workspace/navbar/StatusPanel.tsx +6 -2
  144. inspect_ai/_view/www/src/workspace/sidebar/LogDirectoryTitleView.tsx +4 -4
  145. inspect_ai/_view/www/src/workspace/sidebar/Sidebar.tsx +28 -13
  146. inspect_ai/_view/www/src/workspace/tabs/InfoTab.tsx +5 -10
  147. inspect_ai/_view/www/src/workspace/tabs/JsonTab.tsx +4 -4
  148. inspect_ai/_view/www/src/workspace/tabs/RunningNoSamples.module.css +22 -0
  149. inspect_ai/_view/www/src/workspace/tabs/RunningNoSamples.tsx +19 -0
  150. inspect_ai/_view/www/src/workspace/tabs/SamplesTab.tsx +110 -115
  151. inspect_ai/_view/www/src/workspace/tabs/grouping.ts +37 -5
  152. inspect_ai/_view/www/src/workspace/tabs/types.ts +4 -0
  153. inspect_ai/_view/www/src/workspace/types.ts +4 -3
  154. inspect_ai/_view/www/src/workspace/utils.ts +4 -4
  155. inspect_ai/_view/www/vite.config.js +6 -0
  156. inspect_ai/_view/www/yarn.lock +370 -354
  157. inspect_ai/log/_condense.py +26 -0
  158. inspect_ai/log/_log.py +6 -3
  159. inspect_ai/log/_recorders/buffer/__init__.py +14 -0
  160. inspect_ai/log/_recorders/buffer/buffer.py +30 -0
  161. inspect_ai/log/_recorders/buffer/database.py +685 -0
  162. inspect_ai/log/_recorders/buffer/filestore.py +259 -0
  163. inspect_ai/log/_recorders/buffer/types.py +84 -0
  164. inspect_ai/log/_recorders/eval.py +2 -11
  165. inspect_ai/log/_recorders/types.py +30 -0
  166. inspect_ai/log/_transcript.py +27 -1
  167. inspect_ai/model/_call_tools.py +1 -0
  168. inspect_ai/model/_generate_config.py +2 -2
  169. inspect_ai/model/_model.py +1 -0
  170. inspect_ai/tool/_tool_support_helpers.py +4 -4
  171. inspect_ai/tool/_tools/_web_browser/_web_browser.py +3 -1
  172. inspect_ai/util/_subtask.py +1 -0
  173. {inspect_ai-0.3.80.dist-info → inspect_ai-0.3.82.dist-info}/METADATA +2 -2
  174. {inspect_ai-0.3.80.dist-info → inspect_ai-0.3.82.dist-info}/RECORD +178 -138
  175. inspect_ai/_view/www/src/samples/transcript/SampleTranscript.tsx +0 -22
  176. {inspect_ai-0.3.80.dist-info → inspect_ai-0.3.82.dist-info}/WHEEL +0 -0
  177. {inspect_ai-0.3.80.dist-info → inspect_ai-0.3.82.dist-info}/entry_points.txt +0 -0
  178. {inspect_ai-0.3.80.dist-info → inspect_ai-0.3.82.dist-info}/licenses/LICENSE +0 -0
  179. {inspect_ai-0.3.80.dist-info → inspect_ai-0.3.82.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,100 @@
1
+ import { Timeout } from "../types/log";
2
+ import { createLogger } from "./logger";
3
+
4
+ export interface PollingOptions {
5
+ maxRetries: number;
6
+ interval: number;
7
+ }
8
+
9
+ export interface Polling {
10
+ name: string;
11
+ start: () => void;
12
+ stop: () => void;
13
+ }
14
+
15
+ export const createPolling = (
16
+ name: string,
17
+ callback: () => Promise<boolean>,
18
+ options: PollingOptions,
19
+ ): Polling => {
20
+ const log = createLogger(`Polling ${name}`);
21
+
22
+ const { maxRetries, interval } = options;
23
+ let timeoutId: Timeout = null;
24
+ let retryCount = 0;
25
+ // Are we currently polling
26
+ let isPolling = false;
27
+
28
+ // Are we stopped (e.g. cleaning up)
29
+ let isStopped = false;
30
+
31
+ const calculateBackoff = (retryCount: number) => {
32
+ return Math.min(interval * Math.pow(2, retryCount) * 1000, 60000);
33
+ };
34
+
35
+ const stop = () => {
36
+ if (timeoutId) {
37
+ clearTimeout(timeoutId);
38
+ timeoutId = null;
39
+ }
40
+ log.debug("Stop Polling");
41
+ isPolling = false;
42
+ isStopped = true;
43
+ };
44
+
45
+ const poll = async () => {
46
+ try {
47
+ log.debug("Poll");
48
+ // Don't proceed if polling has been stopped
49
+ if (!isPolling || isStopped) {
50
+ return;
51
+ }
52
+
53
+ const shouldContinue = await callback();
54
+ if (shouldContinue === false) {
55
+ stop();
56
+ return;
57
+ }
58
+
59
+ // Reset retry count on success
60
+ retryCount = 0;
61
+ if (!isPolling || isStopped) {
62
+ return;
63
+ }
64
+ timeoutId = setTimeout(poll, interval * 1000);
65
+ } catch (e) {
66
+ // Don't retry if polling has been stopped
67
+ if (!isPolling || isStopped) {
68
+ return;
69
+ }
70
+ log.debug("Polling error occurred", e);
71
+
72
+ retryCount += 1;
73
+
74
+ if (retryCount >= maxRetries) {
75
+ stop();
76
+ throw new Error(
77
+ `Gave up polling ${name} after ${maxRetries} attempts.`,
78
+ );
79
+ }
80
+
81
+ const backoffTime = calculateBackoff(retryCount);
82
+ log.debug(
83
+ `Retry ${retryCount}/${maxRetries}, backoff: ${backoffTime / 1000}s`,
84
+ );
85
+ timeoutId = setTimeout(poll, backoffTime);
86
+ }
87
+ };
88
+
89
+ const start = () => {
90
+ if (isPolling) {
91
+ return;
92
+ }
93
+ log.debug("Start Polling");
94
+ isPolling = true;
95
+ isStopped = false;
96
+ poll();
97
+ };
98
+
99
+ return { name, start, stop };
100
+ };
@@ -0,0 +1,30 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ export const useWhyDidYouUpdate = (componentName: string, props: any) => {
4
+ const previousProps = useRef(props);
5
+
6
+ useEffect(() => {
7
+ if (previousProps.current !== props) {
8
+ const changedProps = Object.entries(props).reduce(
9
+ (diff, [key, value]) => {
10
+ if (previousProps.current[key] !== value) {
11
+ diff[key] = {
12
+ before: previousProps.current[key],
13
+ after: value,
14
+ };
15
+ }
16
+ return diff;
17
+ },
18
+ {} as Record<string, unknown>,
19
+ );
20
+
21
+ if (Object.keys(changedProps).length > 0) {
22
+ console.log(`[${componentName}] props changed:`, changedProps);
23
+ } else {
24
+ console.log(`[${componentName}] no props changed`);
25
+ }
26
+ }
27
+
28
+ previousProps.current = props;
29
+ }, [props, componentName]);
30
+ };
@@ -2,7 +2,7 @@
2
2
  * Type definition for the VS Code API object
3
3
  * Note: This is a minimal definition - expand based on your needs
4
4
  */
5
- interface VSCodeApi {
5
+ export interface VSCodeApi {
6
6
  postMessage(message: unknown): void;
7
7
  getState(): unknown;
8
8
  setState(state: unknown): void;
@@ -5,27 +5,24 @@ import { JsonTab } from "./tabs/JsonTab";
5
5
  import { SamplesTab } from "./tabs/SamplesTab";
6
6
 
7
7
  import clsx from "clsx";
8
- import { FC, MouseEvent, RefObject, useEffect, useMemo, useRef } from "react";
9
- import { SampleSummary } from "../api/types.ts";
8
+ import { FC, MouseEvent, useEffect, useMemo, useRef } from "react";
9
+ import { RunningMetric } from "../api/types.ts";
10
10
  import {
11
11
  kEvalWorkspaceTabId,
12
12
  kInfoWorkspaceTabId,
13
13
  kJsonWorkspaceTabId,
14
14
  } from "../constants";
15
- import { SamplesDescriptor } from "../samples/descriptor/samplesDescriptor";
16
15
  import {
17
- Capabilities,
18
- CurrentLog,
19
- SampleMode,
20
- ScoreFilter,
21
- ScoreLabel,
22
- } from "../types.ts";
16
+ useFilteredSamples,
17
+ useSampleDescriptor,
18
+ useTotalSampleCount,
19
+ } from "../state/hooks.ts";
20
+ import { useStore } from "../state/store.ts";
21
+ import { CurrentLog } from "../types.ts";
23
22
  import {
24
- Epochs,
25
23
  EvalError,
26
24
  EvalPlan,
27
25
  EvalResults,
28
- EvalSample,
29
26
  EvalSpec,
30
27
  EvalStats,
31
28
  Status,
@@ -35,7 +32,6 @@ import { WorkSpaceView } from "./WorkSpaceView.tsx";
35
32
 
36
33
  interface WorkSpaceProps {
37
34
  task_id?: string;
38
- logFileName?: string;
39
35
  evalError?: EvalError;
40
36
  evalStatus?: Status;
41
37
  evalVersion?: number;
@@ -43,42 +39,10 @@ interface WorkSpaceProps {
43
39
  evalPlan?: EvalPlan;
44
40
  evalStats?: EvalStats;
45
41
  evalResults?: EvalResults;
42
+ runningMetrics?: RunningMetric[];
46
43
  log?: CurrentLog;
47
- samples?: SampleSummary[];
48
- sampleMode: SampleMode;
49
- groupBy: "none" | "epoch" | "sample";
50
- groupByOrder: "asc" | "desc";
51
- selectedSample?: EvalSample;
52
- sampleStatus: string;
53
- sampleError?: Error;
54
44
  showToggle: boolean;
55
- refreshLog: () => Promise<void>;
56
- capabilities: Capabilities;
57
- selectedSampleIndex: number;
58
- samplesDescriptor?: SamplesDescriptor;
59
- setSelectedSampleIndex: (index: number) => void;
60
- selectedSampleTab?: string;
61
- setSelectedSampleTab: (tab: string) => void;
62
- sort: string;
63
- setSort: (sort: string) => void;
64
- epochs?: Epochs;
65
- epoch: string;
66
- showingSampleDialog: boolean;
67
- setShowingSampleDialog: (showing: boolean) => void;
68
- setEpoch: (epoch: string) => void;
69
- filter: ScoreFilter;
70
- setFilter: (filter: ScoreFilter) => void;
71
- score?: ScoreLabel;
72
- setScore: (score: ScoreLabel) => void;
73
- scores: ScoreLabel[];
74
- offcanvas: boolean;
75
- setOffcanvas: (offcanvas: boolean) => void;
76
- selectedTab: string;
77
- setSelectedTab: (id: string) => void;
78
- sampleScrollPositionRef: RefObject<number>;
79
- setSampleScrollPosition: (position: number) => void;
80
- workspaceTabScrollPositionRef: RefObject<Record<string, number>>;
81
- setWorkspaceTabScrollPosition: (tab: string, position: number) => void;
45
+ refreshLog: () => void;
82
46
  }
83
47
 
84
48
  /**
@@ -88,20 +52,12 @@ export const WorkSpace: FC<WorkSpaceProps> = (props) => {
88
52
  const {
89
53
  task_id,
90
54
  evalStatus,
91
- logFileName,
92
55
  evalSpec,
93
56
  evalPlan,
94
57
  evalStats,
95
58
  evalResults,
96
- samples,
59
+ runningMetrics,
97
60
  showToggle,
98
- offcanvas,
99
- setOffcanvas,
100
- samplesDescriptor,
101
- selectedTab,
102
- setSelectedTab,
103
- workspaceTabScrollPositionRef,
104
- setWorkspaceTabScrollPosition,
105
61
  } = props;
106
62
 
107
63
  const divRef = useRef<HTMLDivElement>(null);
@@ -121,27 +77,20 @@ export const WorkSpace: FC<WorkSpaceProps> = (props) => {
121
77
 
122
78
  return (
123
79
  <WorkSpaceView
124
- logFileName={logFileName}
125
80
  divRef={divRef}
126
81
  evalSpec={evalSpec}
127
82
  evalPlan={evalPlan}
128
83
  evalResults={evalResults}
84
+ runningMetrics={runningMetrics}
129
85
  evalStats={evalStats}
130
- samples={samples}
131
- evalDescriptor={samplesDescriptor?.evalDescriptor}
132
86
  status={evalStatus}
133
87
  tabs={resolvedTabs}
134
- selectedTab={selectedTab}
135
88
  showToggle={showToggle}
136
- offcanvas={offcanvas}
137
- setSelectedTab={setSelectedTab}
138
- workspaceTabScrollPositionRef={workspaceTabScrollPositionRef}
139
- setWorkspaceTabScrollPosition={setWorkspaceTabScrollPosition}
140
- setOffcanvas={setOffcanvas}
141
89
  />
142
90
  );
143
91
  };
144
92
 
93
+ // Helper function for copy feedback
145
94
  const copyFeedback = (e: MouseEvent<HTMLElement>) => {
146
95
  const textEl = e.currentTarget.querySelector(".task-btn-copy-content");
147
96
  const iconEl = e.currentTarget.querySelector("i.bi");
@@ -162,164 +111,180 @@ const copyFeedback = (e: MouseEvent<HTMLElement>) => {
162
111
  }
163
112
  };
164
113
 
165
- const useResolvedTabs = ({
166
- evalVersion,
167
- evalStatus,
168
- sampleMode,
169
- samples,
170
- selectedSample,
171
- sampleStatus,
172
- sampleError,
173
- showingSampleDialog,
174
- setShowingSampleDialog,
175
- groupBy,
176
- groupByOrder,
177
- selectedSampleIndex,
178
- setSelectedSampleIndex,
179
- samplesDescriptor,
180
- selectedSampleTab,
181
- setSelectedSampleTab,
182
- filter,
183
- sort,
184
- epoch,
185
- sampleScrollPositionRef,
186
- setSampleScrollPosition,
187
- epochs,
188
- setEpoch,
189
- setFilter,
190
- setSort,
191
- score,
192
- setScore,
193
- scores,
194
- evalSpec,
195
- evalPlan,
196
- evalResults,
197
- evalStats,
198
- evalError,
199
- logFileName,
200
- capabilities,
201
- selectedTab,
202
- refreshLog,
203
- }: WorkSpaceProps) => {
204
- const sampleTabScrollRef = useRef<HTMLDivElement>(null);
114
+ // Individual hook for Samples tab
115
+ export const useSamplesTabConfig = (
116
+ evalStatus: Status | undefined,
117
+ refreshLog: () => void,
118
+ ) => {
119
+ const totalSampleCount = useTotalSampleCount();
120
+ const samplesDescriptor = useSampleDescriptor();
121
+ const sampleSummaries = useFilteredSamples();
122
+ const streamSamples = useStore((state) => state.capabilities.streamSamples);
123
+
124
+ return useMemo(() => {
125
+ return {
126
+ id: kEvalWorkspaceTabId,
127
+ scrollable: false,
128
+ label: totalSampleCount > 1 ? "Samples" : "Sample",
129
+ component: SamplesTab,
130
+ componentProps: {
131
+ running: evalStatus === "started",
132
+ },
133
+ tools: () =>
134
+ totalSampleCount === 1 || !samplesDescriptor
135
+ ? undefined
136
+ : [
137
+ <SampleTools
138
+ samples={sampleSummaries || []}
139
+ key="sample-tools"
140
+ />,
141
+ evalStatus === "started" && !streamSamples && (
142
+ <ToolButton
143
+ key="refresh"
144
+ label="Refresh"
145
+ icon={ApplicationIcons.refresh}
146
+ onClick={refreshLog}
147
+ />
148
+ ),
149
+ ].filter(Boolean),
150
+ };
151
+ }, [
152
+ evalStatus,
153
+ refreshLog,
154
+ sampleSummaries,
155
+ samplesDescriptor,
156
+ totalSampleCount,
157
+ ]);
158
+ };
159
+
160
+ // Individual hook for Info tab
161
+ export const useInfoTabConfig = (
162
+ evalSpec: EvalSpec | undefined,
163
+ evalPlan: EvalPlan | undefined,
164
+ evalError: EvalError | undefined,
165
+ evalResults: EvalResults | undefined,
166
+ evalStats: EvalStats | undefined,
167
+ ) => {
168
+ const totalSampleCount = useTotalSampleCount();
169
+ return useMemo(() => {
170
+ return {
171
+ id: kInfoWorkspaceTabId,
172
+ label: "Info",
173
+ scrollable: true,
174
+ component: InfoTab,
175
+ componentProps: {
176
+ evalSpec,
177
+ evalPlan,
178
+ evalError,
179
+ evalResults,
180
+ evalStats,
181
+ sampleCount: totalSampleCount,
182
+ },
183
+ };
184
+ }, [evalSpec, evalPlan, evalError, evalResults, evalStats, totalSampleCount]);
185
+ };
186
+
187
+ // Individual hook for JSON tab
188
+ export const useJsonTabConfig = (
189
+ evalVersion: number | undefined,
190
+ evalStatus: Status | undefined,
191
+ evalSpec: EvalSpec | undefined,
192
+ evalPlan: EvalPlan | undefined,
193
+ evalError: EvalError | undefined,
194
+ evalResults: EvalResults | undefined,
195
+ evalStats: EvalStats | undefined,
196
+ ) => {
197
+ const selectedLogFile = useStore((state) =>
198
+ state.logsActions.getSelectedLogFile(),
199
+ );
200
+ const selectedTab = useStore((state) => state.app.tabs.workspace);
201
+
202
+ return useMemo(() => {
203
+ const evalHeader = {
204
+ version: evalVersion,
205
+ status: evalStatus,
206
+ eval: evalSpec,
207
+ plan: evalPlan,
208
+ error: evalError,
209
+ results: evalResults,
210
+ stats: evalStats,
211
+ };
212
+
213
+ return {
214
+ id: kJsonWorkspaceTabId,
215
+ label: "JSON",
216
+ scrollable: true,
217
+ component: JsonTab,
218
+ componentProps: {
219
+ logFile: selectedLogFile,
220
+ json: JSON.stringify(evalHeader, null, 2),
221
+ selected: selectedTab === kJsonWorkspaceTabId,
222
+ },
223
+ tools: () => [
224
+ <ToolButton
225
+ key="copy-json"
226
+ label="Copy JSON"
227
+ icon={ApplicationIcons.copy}
228
+ className={clsx("task-btn-json-copy", "clipboard-button")}
229
+ data-clipboard-target="#task-json-contents"
230
+ onClick={copyFeedback}
231
+ />,
232
+ ],
233
+ };
234
+ }, [
235
+ selectedLogFile,
236
+ evalVersion,
237
+ evalStatus,
238
+ evalSpec,
239
+ evalPlan,
240
+ evalError,
241
+ evalResults,
242
+ evalStats,
243
+ selectedTab,
244
+ ]);
245
+ };
246
+
247
+ // Main hook combining all tab configs
248
+ export const useResolvedTabs = (props: WorkSpaceProps) => {
249
+ const {
250
+ evalVersion,
251
+ evalStatus,
252
+ evalSpec,
253
+ evalPlan,
254
+ evalResults,
255
+ evalStats,
256
+ evalError,
257
+ refreshLog,
258
+ } = props;
205
259
 
206
- const samplesTab =
207
- sampleMode !== "none"
208
- ? {
209
- id: kEvalWorkspaceTabId,
210
- scrollable: samples?.length === 1,
211
- scrollRef: sampleTabScrollRef,
212
- label: (samples || []).length > 1 ? "Samples" : "Sample",
213
- content: () => (
214
- <SamplesTab
215
- sample={selectedSample}
216
- sampleStatus={sampleStatus}
217
- sampleError={sampleError}
218
- showingSampleDialog={showingSampleDialog}
219
- setShowingSampleDialog={setShowingSampleDialog}
220
- samples={samples}
221
- sampleMode={sampleMode}
222
- groupBy={groupBy}
223
- groupByOrder={groupByOrder}
224
- selectedSampleIndex={selectedSampleIndex}
225
- setSelectedSampleIndex={setSelectedSampleIndex}
226
- sampleDescriptor={samplesDescriptor}
227
- selectedSampleTab={selectedSampleTab}
228
- setSelectedSampleTab={setSelectedSampleTab}
229
- filter={filter}
230
- epoch={epoch}
231
- sampleScrollPositionRef={sampleScrollPositionRef}
232
- setSampleScrollPosition={setSampleScrollPosition}
233
- sampleTabScrollRef={sampleTabScrollRef}
234
- />
235
- ),
236
- tools: () =>
237
- sampleMode === "single" || !samplesDescriptor
238
- ? undefined
239
- : [
240
- <SampleTools
241
- key="sample-tools"
242
- epoch={epoch}
243
- epochs={epochs || 1}
244
- setEpoch={setEpoch}
245
- scoreFilter={filter}
246
- setScoreFilter={setFilter}
247
- sort={sort}
248
- setSort={setSort}
249
- score={score}
250
- setScore={setScore}
251
- scores={scores}
252
- sampleDescriptor={samplesDescriptor}
253
- />,
254
- evalStatus === "started" && (
255
- <ToolButton
256
- key="refresh"
257
- label="Refresh"
258
- icon={ApplicationIcons.refresh}
259
- onClick={refreshLog}
260
- />
261
- ),
262
- ].filter(Boolean),
263
- }
264
- : null;
260
+ // Use individual tab config hooks
261
+ const samplesTabConfig = useSamplesTabConfig(evalStatus, refreshLog);
265
262
 
266
- const configTab = {
267
- id: kInfoWorkspaceTabId,
268
- label: "Info",
269
- scrollable: true,
270
- content: () => (
271
- <InfoTab
272
- evalSpec={evalSpec}
273
- evalPlan={evalPlan}
274
- evalError={evalError}
275
- evalResults={evalResults}
276
- evalStats={evalStats}
277
- samples={samples}
278
- />
279
- ),
280
- };
263
+ const configTabConfig = useInfoTabConfig(
264
+ evalSpec,
265
+ evalPlan,
266
+ evalError,
267
+ evalResults,
268
+ evalStats,
269
+ );
281
270
 
282
- const jsonTab = {
283
- id: kJsonWorkspaceTabId,
284
- label: "JSON",
285
- scrollable: true,
286
- content: () => {
287
- const evalHeader = {
288
- version: evalVersion,
289
- status: evalStatus,
290
- eval: evalSpec,
291
- plan: evalPlan,
292
- error: evalError,
293
- results: evalResults,
294
- stats: evalStats,
295
- };
296
- return (
297
- <JsonTab
298
- logFile={logFileName}
299
- json={JSON.stringify(evalHeader, null, 2)}
300
- capabilities={capabilities}
301
- selected={selectedTab === kJsonWorkspaceTabId}
302
- />
303
- );
304
- },
305
- tools: () => [
306
- <ToolButton
307
- key="copy-json"
308
- label="Copy JSON"
309
- icon={ApplicationIcons.copy}
310
- className={clsx("task-btn-json-copy", "clipboard-button")}
311
- data-clipboard-target="#task-json-contents"
312
- onClick={copyFeedback}
313
- />,
314
- ],
315
- };
271
+ const jsonTabConfig = useJsonTabConfig(
272
+ evalVersion,
273
+ evalStatus,
274
+ evalSpec,
275
+ evalPlan,
276
+ evalError,
277
+ evalResults,
278
+ evalStats,
279
+ );
316
280
 
281
+ // Combine all tab configs
317
282
  return useMemo(
318
283
  () => ({
319
- ...(samplesTab ? { samples: samplesTab } : {}),
320
- config: configTab,
321
- json: jsonTab,
284
+ ...(samplesTabConfig ? { samples: samplesTabConfig } : {}),
285
+ config: configTabConfig,
286
+ json: jsonTabConfig,
322
287
  }),
323
- [samplesTab, configTab, jsonTab],
288
+ [samplesTabConfig, configTabConfig, jsonTabConfig],
324
289
  );
325
290
  };