inspect-ai 0.3.81__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.81.dist-info → inspect_ai-0.3.82.dist-info}/METADATA +1 -1
  174. {inspect_ai-0.3.81.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.81.dist-info → inspect_ai-0.3.82.dist-info}/WHEEL +0 -0
  177. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.82.dist-info}/entry_points.txt +0 -0
  178. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.82.dist-info}/licenses/LICENSE +0 -0
  179. {inspect_ai-0.3.81.dist-info → inspect_ai-0.3.82.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- import React, { RefObject, useCallback, useState } from "react";
1
+ import { FC, memo, RefObject, useMemo } from "react";
2
2
  import { Events } from "../../types/log";
3
3
  import { ApprovalEventView } from "./ApprovalEventView";
4
4
  import { ErrorEventView } from "./ErrorEventView";
@@ -8,17 +8,17 @@ import { LoggerEventView } from "./LoggerEventView";
8
8
  import { ModelEventView } from "./ModelEventView";
9
9
  import { SampleInitEventView } from "./SampleInitEventView";
10
10
  import { SampleLimitEventView } from "./SampleLimitEventView";
11
+ import { SandboxEventView } from "./SandboxEventView";
11
12
  import { ScoreEventView } from "./ScoreEventView";
12
13
  import { StateEventView } from "./state/StateEventView";
13
14
  import { StepEventView } from "./StepEventView";
14
15
  import { SubtaskEventView } from "./SubtaskEventView";
15
16
  import { ToolEventView } from "./ToolEventView";
16
- import { EventNode, EventType, TranscriptEventState } from "./types";
17
+ import { EventNode, EventType } from "./types";
17
18
 
18
19
  import clsx from "clsx";
19
- import { Virtuoso } from "react-virtuoso";
20
- import { SandboxEventView } from "./SandboxEventView";
21
20
  import styles from "./TranscriptView.module.css";
21
+ import { TranscriptVirtualListComponent } from "./TranscriptVirtualListComponent";
22
22
 
23
23
  interface TranscriptViewProps {
24
24
  id: string;
@@ -26,38 +26,21 @@ interface TranscriptViewProps {
26
26
  depth: number;
27
27
  }
28
28
 
29
- type TranscriptState = Record<string, TranscriptEventState>;
30
-
31
29
  /**
32
30
  * Renders the TranscriptView component.
33
31
  */
34
- export const TranscriptView: React.FC<TranscriptViewProps> = ({
32
+ export const TranscriptView: FC<TranscriptViewProps> = ({
35
33
  id,
36
34
  events,
37
35
  depth,
38
36
  }) => {
39
- const [transcriptState, setTranscriptState] = useState<TranscriptState>({});
40
- const onTranscriptState = useCallback(
41
- (state: TranscriptState) => {
42
- setTranscriptState(state);
43
- },
44
- [setTranscriptState],
45
- );
46
-
47
37
  // Normalize Events themselves
48
38
  const resolvedEvents = fixupEventStream(events);
49
39
  const eventNodes = treeifyEvents(
50
40
  resolvedEvents,
51
41
  depth !== undefined ? depth : 0,
52
42
  );
53
- return (
54
- <TranscriptComponent
55
- id={id}
56
- eventNodes={eventNodes}
57
- transcriptState={transcriptState}
58
- setTranscriptState={onTranscriptState}
59
- />
60
- );
43
+ return <TranscriptComponent id={id} eventNodes={eventNodes} />;
61
44
  };
62
45
 
63
46
  interface TranscriptVirtualListProps {
@@ -65,367 +48,243 @@ interface TranscriptVirtualListProps {
65
48
  events: Events;
66
49
  depth?: number;
67
50
  scrollRef: RefObject<HTMLDivElement | null>;
51
+ running?: boolean;
68
52
  }
69
53
 
70
54
  /**
71
55
  * Renders the Transcript Virtual List.
72
56
  */
73
- export const TranscriptVirtualList: React.FC<TranscriptVirtualListProps> = (
74
- props,
75
- ) => {
76
- let { id, scrollRef, events, depth } = props;
77
-
78
- // Normalize Events themselves
79
- const resolvedEvents = fixupEventStream(events);
80
- const eventNodes = treeifyEvents(resolvedEvents, depth || 0);
81
-
82
- const [transcriptState, setTranscriptState] = useState({});
83
- const onTranscriptState = useCallback(
84
- (state: TranscriptEventState) => {
85
- setTranscriptState(state);
86
- },
87
- [setTranscriptState],
88
- );
89
-
90
- return (
91
- <TranscriptVirtualListComponent
92
- id={id}
93
- eventNodes={eventNodes}
94
- scrollRef={scrollRef}
95
- transcriptState={transcriptState}
96
- setTranscriptState={onTranscriptState}
97
- />
98
- );
99
- };
100
-
101
- interface TranscriptVirtualListComponentProps {
102
- id: string;
103
- eventNodes: EventNode[];
104
- transcriptState: TranscriptState;
105
- setTranscriptState: (state: TranscriptState) => void;
106
- scrollRef?: RefObject<HTMLDivElement | null>;
107
- }
108
-
109
- /**
110
- * Renders the Transcript component.
111
- */
112
- export const TranscriptVirtualListComponent: React.FC<
113
- TranscriptVirtualListComponentProps
114
- > = ({ id, eventNodes, scrollRef, transcriptState, setTranscriptState }) => {
115
- const setEventState = useCallback(
116
- (eventId: string, state: TranscriptEventState) => {
117
- setTranscriptState({ ...transcriptState, [eventId]: state });
118
- },
119
- [transcriptState, setTranscriptState],
120
- );
57
+ export const TranscriptVirtualList: FC<TranscriptVirtualListProps> = memo(
58
+ (props) => {
59
+ let { id, scrollRef, events, depth, running } = props;
121
60
 
122
- const [followOutput, setFollowOutput] = useState(false);
61
+ // Normalize Events themselves
62
+ const eventNodes = useMemo(() => {
63
+ const resolvedEvents = fixupEventStream(events, !running);
64
+ const eventNodes = treeifyEvents(resolvedEvents, depth || 0);
123
65
 
124
- const renderRow = (item: EventNode, index: number) => {
125
- const bgClass = item.depth % 2 == 0 ? styles.darkenedBg : styles.normalBg;
126
- const paddingClass = index === 0 ? styles.first : undefined;
127
-
128
- const eventId = `${id}-event${index}`;
66
+ return eventNodes;
67
+ }, [events, depth]);
129
68
 
130
69
  return (
131
- <div key={eventId} className={clsx(styles.node, paddingClass)}>
132
- <RenderedEventNode
133
- id={eventId}
134
- node={item}
135
- className={clsx(bgClass)}
136
- scrollRef={scrollRef}
137
- eventState={transcriptState[eventId] || {}}
138
- setEventState={(state) => setEventState(eventId, state)}
139
- />
140
- </div>
70
+ <TranscriptVirtualListComponent
71
+ id={id}
72
+ eventNodes={eventNodes}
73
+ scrollRef={scrollRef}
74
+ running={running}
75
+ />
141
76
  );
142
- };
143
-
144
- return (
145
- <Virtuoso
146
- customScrollParent={scrollRef?.current ? scrollRef.current : undefined}
147
- style={{ height: "100%", width: "100%" }}
148
- data={eventNodes}
149
- itemContent={(index: number, data: EventNode) => {
150
- return renderRow(data, index);
151
- }}
152
- increaseViewportBy={{ top: 1000, bottom: 1000 }}
153
- overscan={{
154
- main: 10,
155
- reverse: 10,
156
- }}
157
- followOutput={followOutput}
158
- atBottomStateChange={(atBottom: boolean) => {
159
- setFollowOutput(atBottom);
160
- }}
161
- skipAnimationFrameInResizeObserver={true}
162
- className={clsx("transcript")}
163
- />
164
- );
165
- };
77
+ },
78
+ );
166
79
 
167
80
  interface TranscriptComponentProps {
168
81
  id: string;
169
- transcriptState: TranscriptState;
170
- setTranscriptState: (state: TranscriptState) => void;
171
82
  eventNodes: EventNode[];
172
83
  }
173
84
  /**
174
85
  * Renders the Transcript component.
175
86
  */
176
- export const TranscriptComponent: React.FC<TranscriptComponentProps> = ({
177
- id,
178
- transcriptState,
179
- setTranscriptState,
180
- eventNodes,
181
- }) => {
182
- const setEventState = useCallback(
183
- (state: TranscriptEventState, eventId: string) => {
184
- setTranscriptState({ ...transcriptState, [eventId]: state });
185
- },
186
- [setTranscriptState, transcriptState],
187
- );
188
-
189
- const rows = eventNodes.map((eventNode, index) => {
190
- const clz = [styles.eventNode];
191
- if (eventNode.depth % 2 == 0) {
192
- clz.push(styles.darkenBg);
193
- }
194
- if (index === eventNodes.length - 1) {
195
- clz.push(styles.lastNode);
196
- }
87
+ export const TranscriptComponent: FC<TranscriptComponentProps> = memo(
88
+ ({ id, eventNodes }) => {
89
+ const rows = eventNodes.map((eventNode, index) => {
90
+ const clz = [styles.eventNode];
91
+ if (eventNode.depth % 2 == 0) {
92
+ clz.push(styles.darkenBg);
93
+ }
94
+ if (index === eventNodes.length - 1) {
95
+ clz.push(styles.lastNode);
96
+ }
197
97
 
198
- const eventId = `${id}-event${index}`;
98
+ const eventId = `${id}|event|${index}`;
99
+
100
+ const row = (
101
+ <div
102
+ key={eventId}
103
+ className={clsx(
104
+ styles.eventNodeContainer,
105
+ index === eventNodes.length - 1 ? styles.noBottom : undefined,
106
+ )}
107
+ >
108
+ <RenderedEventNode
109
+ id={eventId}
110
+ node={eventNode}
111
+ className={clsx(clz)}
112
+ />
113
+ </div>
114
+ );
115
+ return row;
116
+ });
199
117
 
200
- const row = (
118
+ return (
201
119
  <div
202
- key={eventId}
203
- className={clsx(
204
- styles.eventNodeContainer,
205
- index === eventNodes.length - 1 ? styles.noBottom : undefined,
206
- )}
120
+ id={id}
121
+ className={clsx("text-size-small", styles.transcriptComponent)}
207
122
  >
208
- <RenderedEventNode
209
- id={eventId}
210
- node={eventNode}
211
- className={clsx(clz)}
212
- eventState={transcriptState[eventId] || {}}
213
- setEventState={(state: TranscriptEventState) => {
214
- setEventState(state, eventId);
215
- }}
216
- />
123
+ {rows}
217
124
  </div>
218
125
  );
219
- return row;
220
- });
221
-
222
- return (
223
- <div
224
- id={id}
225
- className={clsx("text-size-small", styles.transcriptComponent)}
226
- >
227
- {rows}
228
- </div>
229
- );
230
- };
126
+ },
127
+ );
231
128
 
232
129
  interface RenderedEventNodeProps {
233
130
  id: string;
234
131
  node: EventNode;
235
- scrollRef?: RefObject<HTMLDivElement | null>;
236
- eventState: TranscriptEventState;
237
- setEventState: (state: TranscriptEventState) => void;
238
132
  className?: string | string[];
239
133
  }
240
134
  /**
241
135
  * Renders the event based on its type.
242
136
  */
243
- export const RenderedEventNode: React.FC<RenderedEventNodeProps> = ({
244
- id,
245
- node,
246
- scrollRef,
247
- eventState,
248
- setEventState,
249
- className,
250
- }) => {
251
- switch (node.event.event) {
252
- case "sample_init":
253
- return (
254
- <SampleInitEventView
255
- id={id}
256
- event={node.event}
257
- eventState={eventState}
258
- setEventState={setEventState}
259
- className={className}
260
- />
261
- );
262
-
263
- case "sample_limit":
264
- return (
265
- <SampleLimitEventView
266
- id={id}
267
- event={node.event}
268
- eventState={eventState}
269
- setEventState={setEventState}
270
- className={className}
271
- />
272
- );
273
-
274
- case "info":
275
- return (
276
- <InfoEventView
277
- id={id}
278
- event={node.event}
279
- eventState={eventState}
280
- setEventState={setEventState}
281
- className={className}
282
- />
283
- );
284
-
285
- case "logger":
286
- return <LoggerEventView event={node.event} className={className} />;
287
-
288
- case "model":
289
- return (
290
- <ModelEventView
291
- id={id}
292
- event={node.event}
293
- eventState={eventState}
294
- setEventState={setEventState}
295
- className={className}
296
- />
297
- );
298
-
299
- case "score":
300
- return (
301
- <ScoreEventView
302
- id={id}
303
- event={node.event}
304
- eventState={eventState}
305
- setEventState={setEventState}
306
- className={className}
307
- />
308
- );
309
-
310
- case "state":
311
- return (
312
- <StateEventView
313
- id={id}
314
- event={node.event}
315
- eventState={eventState}
316
- setEventState={setEventState}
317
- className={className}
318
- />
319
- );
320
-
321
- case "step":
322
- return (
323
- <StepEventView
324
- event={node.event}
325
- eventState={eventState}
326
- setEventState={setEventState}
327
- children={node.children}
328
- scrollRef={scrollRef}
329
- className={className}
330
- />
331
- );
332
-
333
- case "store":
334
- return (
335
- <StateEventView
336
- id={id}
337
- event={node.event}
338
- eventState={eventState}
339
- setEventState={setEventState}
340
- className={className}
341
- isStore={true}
342
- />
343
- );
344
-
345
- case "subtask":
346
- return (
347
- <SubtaskEventView
348
- id={id}
349
- event={node.event}
350
- eventState={eventState}
351
- setEventState={setEventState}
352
- className={className}
353
- depth={node.depth}
354
- />
355
- );
356
-
357
- case "tool":
358
- return (
359
- <ToolEventView
360
- id={id}
361
- event={node.event}
362
- eventState={eventState}
363
- setEventState={setEventState}
364
- className={className}
365
- depth={node.depth}
366
- />
367
- );
368
-
369
- case "input":
370
- return (
371
- <InputEventView
372
- id={id}
373
- event={node.event}
374
- eventState={eventState}
375
- setEventState={setEventState}
376
- className={className}
377
- />
378
- );
379
-
380
- case "error":
381
- return (
382
- <ErrorEventView
383
- id={id}
384
- event={node.event}
385
- eventState={eventState}
386
- setEventState={setEventState}
387
- className={className}
388
- />
389
- );
390
-
391
- case "approval":
392
- return <ApprovalEventView event={node.event} className={className} />;
393
-
394
- case "sandbox":
395
- return (
396
- <SandboxEventView
397
- id={id}
398
- event={node.event}
399
- className={className}
400
- eventState={eventState}
401
- setEventState={setEventState}
402
- />
403
- );
404
-
405
- default:
406
- return null;
407
- }
408
- };
137
+ export const RenderedEventNode: FC<RenderedEventNodeProps> = memo(
138
+ ({ id, node, className }) => {
139
+ switch (node.event.event) {
140
+ case "sample_init":
141
+ return (
142
+ <SampleInitEventView
143
+ id={id}
144
+ event={node.event}
145
+ className={className}
146
+ />
147
+ );
148
+
149
+ case "sample_limit":
150
+ return (
151
+ <SampleLimitEventView
152
+ id={id}
153
+ event={node.event}
154
+ className={className}
155
+ />
156
+ );
157
+
158
+ case "info":
159
+ return (
160
+ <InfoEventView id={id} event={node.event} className={className} />
161
+ );
162
+
163
+ case "logger":
164
+ return <LoggerEventView event={node.event} className={className} />;
165
+
166
+ case "model":
167
+ return (
168
+ <ModelEventView id={id} event={node.event} className={className} />
169
+ );
170
+
171
+ case "score":
172
+ return (
173
+ <ScoreEventView id={id} event={node.event} className={className} />
174
+ );
175
+
176
+ case "state":
177
+ return (
178
+ <StateEventView id={id} event={node.event} className={className} />
179
+ );
180
+
181
+ case "step":
182
+ return (
183
+ <StepEventView
184
+ id={id}
185
+ event={node.event}
186
+ children={node.children}
187
+ className={className}
188
+ />
189
+ );
190
+
191
+ case "store":
192
+ return (
193
+ <StateEventView
194
+ id={id}
195
+ event={node.event}
196
+ className={className}
197
+ isStore={true}
198
+ />
199
+ );
200
+
201
+ case "subtask":
202
+ return (
203
+ <SubtaskEventView
204
+ id={id}
205
+ event={node.event}
206
+ className={className}
207
+ depth={node.depth}
208
+ />
209
+ );
210
+
211
+ case "tool":
212
+ return (
213
+ <ToolEventView
214
+ id={id}
215
+ event={node.event}
216
+ className={className}
217
+ depth={node.depth}
218
+ />
219
+ );
220
+
221
+ case "input":
222
+ return (
223
+ <InputEventView id={id} event={node.event} className={className} />
224
+ );
225
+
226
+ case "error":
227
+ return (
228
+ <ErrorEventView id={id} event={node.event} className={className} />
229
+ );
230
+
231
+ case "approval":
232
+ return <ApprovalEventView event={node.event} className={className} />;
233
+
234
+ case "sandbox":
235
+ return (
236
+ <SandboxEventView id={id} event={node.event} className={className} />
237
+ );
238
+
239
+ default:
240
+ return null;
241
+ }
242
+ },
243
+ );
409
244
 
410
245
  /**
411
246
  * Normalizes event content
412
247
  */
413
- const fixupEventStream = (events: Events) => {
248
+ const fixupEventStream = (events: Events, filterPending: boolean = true) => {
414
249
  const initEventIndex = events.findIndex((e) => {
415
250
  return e.event === "sample_init";
416
251
  });
417
252
  const initEvent = events[initEventIndex];
418
253
 
419
- // Filter pending events
420
- const finalEvents = events.filter((e) => !e.pending);
421
-
422
- // See if the find an init step
254
+ // If filtering pending, just remove all pending events
255
+ // otherise, collapse sequential pending events of the same
256
+ // type
257
+ const collapsed = filterPending
258
+ ? events.filter((e) => !e.pending)
259
+ : events.reduce<Events>((acc, event) => {
260
+ // Collapse sequential pending events of the same type
261
+ if (!event.pending) {
262
+ // Not a pending event
263
+ acc.push(event);
264
+ } else {
265
+ // For pending events, replace previous pending or add new
266
+ const lastIndex = acc.length - 1;
267
+ if (
268
+ lastIndex >= 0 &&
269
+ acc[lastIndex].pending &&
270
+ acc[lastIndex].event === event.event
271
+ ) {
272
+ // Replace previous pending with current one (if they're of the same type)
273
+ acc[lastIndex] = event;
274
+ } else {
275
+ // First event or follows non-pending
276
+ acc.push(event);
277
+ }
278
+ }
279
+ return acc;
280
+ }, []);
281
+ // See if the events have an init step
423
282
  const hasInitStep =
424
- events.findIndex((e) => {
283
+ collapsed.findIndex((e) => {
425
284
  return e.event === "step" && e.name === "init";
426
285
  }) !== -1;
427
286
 
428
- const fixedUp = [...finalEvents];
287
+ const fixedUp = [...collapsed];
429
288
  if (!hasInitStep && initEvent) {
430
289
  fixedUp.splice(initEventIndex, 0, {
431
290
  timestamp: initEvent.timestamp,
@@ -0,0 +1,16 @@
1
+ .darkenedBg {
2
+ background-color: var(--bs-light-bg-subtle);
3
+ }
4
+
5
+ .normalBg {
6
+ background-color: var(--bs-body-bg);
7
+ }
8
+
9
+ .node.first {
10
+ padding-top: 0.5em;
11
+ }
12
+
13
+ .node {
14
+ padding-top: 0;
15
+ padding-bottom: 0.5em;
16
+ }
@@ -0,0 +1,44 @@
1
+ import clsx from "clsx";
2
+ import { FC, RefObject, useCallback } from "react";
3
+ import { RenderedEventNode } from "./TranscriptView";
4
+ import { EventNode } from "./types";
5
+
6
+ import { LiveVirtualList } from "../../components/LiveVirtualList";
7
+ import styles from "./TranscriptVirtualListComponent.module.css";
8
+
9
+ interface TranscriptVirtualListComponentProps {
10
+ id: string;
11
+ eventNodes: EventNode[];
12
+ scrollRef?: RefObject<HTMLDivElement | null>;
13
+ running?: boolean;
14
+ }
15
+
16
+ /**
17
+ * Renders the Transcript component.
18
+ */
19
+ export const TranscriptVirtualListComponent: FC<
20
+ TranscriptVirtualListComponentProps
21
+ > = ({ id, eventNodes, scrollRef, running }) => {
22
+ const renderRow = useCallback((index: number, item: EventNode) => {
23
+ const bgClass = item.depth % 2 == 0 ? styles.darkenedBg : styles.normalBg;
24
+ const paddingClass = index === 0 ? styles.first : undefined;
25
+
26
+ const eventId = `${id}-event-${index}`;
27
+
28
+ return (
29
+ <div key={eventId} className={clsx(styles.node, paddingClass)}>
30
+ <RenderedEventNode id={eventId} node={item} className={clsx(bgClass)} />
31
+ </div>
32
+ );
33
+ }, []);
34
+
35
+ return (
36
+ <LiveVirtualList<EventNode>
37
+ id={id}
38
+ scrollRef={scrollRef}
39
+ data={eventNodes}
40
+ renderRow={renderRow}
41
+ live={running}
42
+ />
43
+ );
44
+ };