inspect-ai 0.3.96__py3-none-any.whl → 0.3.97__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.
- inspect_ai/_eval/eval.py +10 -2
- inspect_ai/_eval/task/util.py +32 -3
- inspect_ai/_util/registry.py +7 -0
- inspect_ai/_util/timer.py +13 -0
- inspect_ai/_view/www/dist/assets/index.css +275 -195
- inspect_ai/_view/www/dist/assets/index.js +8568 -7376
- inspect_ai/_view/www/src/app/App.css +1 -0
- inspect_ai/_view/www/src/app/App.tsx +27 -10
- inspect_ai/_view/www/src/app/appearance/icons.ts +5 -0
- inspect_ai/_view/www/src/app/content/RecordTree.module.css +22 -0
- inspect_ai/_view/www/src/app/content/RecordTree.tsx +370 -0
- inspect_ai/_view/www/src/app/content/RenderedContent.module.css +5 -0
- inspect_ai/_view/www/src/app/content/RenderedContent.tsx +32 -19
- inspect_ai/_view/www/src/app/content/record_processors/store.ts +101 -0
- inspect_ai/_view/www/src/app/content/record_processors/types.ts +3 -0
- inspect_ai/_view/www/src/app/content/types.ts +5 -0
- inspect_ai/_view/www/src/app/log-view/LogView.tsx +1 -0
- inspect_ai/_view/www/src/app/log-view/LogViewContainer.tsx +35 -28
- inspect_ai/_view/www/src/app/log-view/LogViewLayout.tsx +1 -8
- inspect_ai/_view/www/src/app/log-view/navbar/PrimaryBar.tsx +2 -4
- inspect_ai/_view/www/src/app/log-view/navbar/ResultsPanel.tsx +13 -3
- inspect_ai/_view/www/src/app/log-view/navbar/ScoreGrid.module.css +15 -0
- inspect_ai/_view/www/src/app/log-view/navbar/ScoreGrid.tsx +14 -10
- inspect_ai/_view/www/src/app/log-view/tabs/InfoTab.tsx +9 -3
- inspect_ai/_view/www/src/app/log-view/tabs/JsonTab.tsx +1 -3
- inspect_ai/_view/www/src/app/log-view/tabs/SamplesTab.tsx +8 -2
- inspect_ai/_view/www/src/app/log-view/types.ts +1 -0
- inspect_ai/_view/www/src/app/plan/ModelCard.module.css +7 -0
- inspect_ai/_view/www/src/app/plan/ModelCard.tsx +5 -2
- inspect_ai/_view/www/src/app/plan/PlanCard.tsx +13 -8
- inspect_ai/_view/www/src/app/routing/navigationHooks.ts +63 -8
- inspect_ai/_view/www/src/app/routing/url.ts +45 -0
- inspect_ai/_view/www/src/app/samples/InlineSampleDisplay.module.css +2 -1
- inspect_ai/_view/www/src/app/samples/InlineSampleDisplay.tsx +15 -8
- inspect_ai/_view/www/src/app/samples/SampleDialog.module.css +3 -0
- inspect_ai/_view/www/src/app/samples/SampleDialog.tsx +16 -5
- inspect_ai/_view/www/src/app/samples/SampleDisplay.module.css +9 -1
- inspect_ai/_view/www/src/app/samples/SampleDisplay.tsx +68 -31
- inspect_ai/_view/www/src/app/samples/chat/ChatMessage.module.css +12 -7
- inspect_ai/_view/www/src/app/samples/chat/ChatMessage.tsx +17 -5
- inspect_ai/_view/www/src/app/samples/chat/ChatMessageRow.module.css +9 -0
- inspect_ai/_view/www/src/app/samples/chat/ChatMessageRow.tsx +48 -18
- inspect_ai/_view/www/src/app/samples/chat/ChatView.tsx +0 -1
- inspect_ai/_view/www/src/app/samples/chat/ChatViewVirtualList.module.css +4 -0
- inspect_ai/_view/www/src/app/samples/chat/ChatViewVirtualList.tsx +41 -1
- inspect_ai/_view/www/src/app/samples/chat/messages.ts +7 -0
- inspect_ai/_view/www/src/app/samples/chat/tools/ToolCallView.module.css +0 -3
- inspect_ai/_view/www/src/app/samples/chat/tools/ToolCallView.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/chat/tools/ToolInput.module.css +1 -1
- inspect_ai/_view/www/src/app/samples/chat/tools/ToolOutput.module.css +1 -1
- inspect_ai/_view/www/src/app/samples/descriptor/score/NumericScoreDescriptor.tsx +5 -1
- inspect_ai/_view/www/src/app/samples/descriptor/score/PassFailScoreDescriptor.tsx +11 -6
- inspect_ai/_view/www/src/app/samples/list/SampleList.tsx +7 -0
- inspect_ai/_view/www/src/app/samples/list/SampleRow.tsx +5 -18
- inspect_ai/_view/www/src/app/samples/sample-tools/SortFilter.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/scores/SampleScoresGrid.tsx +18 -5
- inspect_ai/_view/www/src/app/samples/scores/SampleScoresView.module.css +0 -6
- inspect_ai/_view/www/src/app/samples/scores/SampleScoresView.tsx +4 -1
- inspect_ai/_view/www/src/app/samples/transcript/ApprovalEventView.tsx +4 -2
- inspect_ai/_view/www/src/app/samples/transcript/ErrorEventView.tsx +6 -4
- inspect_ai/_view/www/src/app/samples/transcript/InfoEventView.module.css +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/InfoEventView.tsx +13 -6
- inspect_ai/_view/www/src/app/samples/transcript/InputEventView.tsx +6 -4
- inspect_ai/_view/www/src/app/samples/transcript/LoggerEventView.tsx +4 -2
- inspect_ai/_view/www/src/app/samples/transcript/ModelEventView.tsx +11 -8
- inspect_ai/_view/www/src/app/samples/transcript/SampleInitEventView.tsx +14 -8
- inspect_ai/_view/www/src/app/samples/transcript/SampleLimitEventView.tsx +13 -8
- inspect_ai/_view/www/src/app/samples/transcript/SandboxEventView.tsx +25 -16
- inspect_ai/_view/www/src/app/samples/transcript/ScoreEventView.tsx +7 -5
- inspect_ai/_view/www/src/app/samples/transcript/SpanEventView.tsx +11 -28
- inspect_ai/_view/www/src/app/samples/transcript/StepEventView.tsx +12 -20
- inspect_ai/_view/www/src/app/samples/transcript/SubtaskEventView.tsx +12 -31
- inspect_ai/_view/www/src/app/samples/transcript/ToolEventView.tsx +25 -29
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualList.tsx +297 -0
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualListComponent.module.css +0 -8
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualListComponent.tsx +43 -25
- inspect_ai/_view/www/src/app/samples/transcript/event/EventPanel.module.css +43 -0
- inspect_ai/_view/www/src/app/samples/transcript/event/EventPanel.tsx +109 -43
- inspect_ai/_view/www/src/app/samples/transcript/state/StateEventView.tsx +19 -8
- inspect_ai/_view/www/src/app/samples/transcript/transform/treeify.ts +128 -60
- inspect_ai/_view/www/src/app/samples/transcript/transform/utils.ts +14 -4
- inspect_ai/_view/www/src/app/samples/transcript/types.ts +6 -4
- inspect_ai/_view/www/src/app/types.ts +12 -1
- inspect_ai/_view/www/src/components/Card.css +6 -3
- inspect_ai/_view/www/src/components/Card.tsx +15 -2
- inspect_ai/_view/www/src/components/CopyButton.tsx +4 -6
- inspect_ai/_view/www/src/components/ExpandablePanel.module.css +20 -14
- inspect_ai/_view/www/src/components/ExpandablePanel.tsx +17 -22
- inspect_ai/_view/www/src/components/LargeModal.tsx +5 -1
- inspect_ai/_view/www/src/components/LiveVirtualList.tsx +25 -1
- inspect_ai/_view/www/src/components/MarkdownDiv.css +4 -0
- inspect_ai/_view/www/src/components/MarkdownDiv.tsx +2 -2
- inspect_ai/_view/www/src/components/TabSet.module.css +6 -1
- inspect_ai/_view/www/src/components/TabSet.tsx +8 -2
- inspect_ai/_view/www/src/state/hooks.ts +83 -13
- inspect_ai/_view/www/src/state/logPolling.ts +2 -2
- inspect_ai/_view/www/src/state/logSlice.ts +1 -2
- inspect_ai/_view/www/src/state/logsSlice.ts +9 -9
- inspect_ai/_view/www/src/state/samplePolling.ts +1 -1
- inspect_ai/_view/www/src/state/sampleSlice.ts +134 -7
- inspect_ai/_view/www/src/state/scoring.ts +1 -1
- inspect_ai/_view/www/src/state/scrolling.ts +39 -6
- inspect_ai/_view/www/src/state/store.ts +5 -0
- inspect_ai/_view/www/src/state/store_filter.ts +47 -44
- inspect_ai/_view/www/src/utils/debugging.ts +95 -0
- inspect_ai/_view/www/src/utils/format.ts +2 -2
- inspect_ai/_view/www/src/utils/json.ts +29 -0
- inspect_ai/agent/__init__.py +2 -1
- inspect_ai/agent/_agent.py +12 -0
- inspect_ai/agent/_react.py +184 -48
- inspect_ai/agent/_types.py +14 -1
- inspect_ai/analysis/beta/__init__.py +0 -2
- inspect_ai/analysis/beta/_dataframe/columns.py +11 -16
- inspect_ai/analysis/beta/_dataframe/evals/table.py +65 -40
- inspect_ai/analysis/beta/_dataframe/events/table.py +24 -36
- inspect_ai/analysis/beta/_dataframe/messages/table.py +24 -15
- inspect_ai/analysis/beta/_dataframe/progress.py +35 -5
- inspect_ai/analysis/beta/_dataframe/record.py +13 -9
- inspect_ai/analysis/beta/_dataframe/samples/columns.py +1 -1
- inspect_ai/analysis/beta/_dataframe/samples/table.py +156 -46
- inspect_ai/analysis/beta/_dataframe/util.py +14 -12
- inspect_ai/model/_call_tools.py +1 -1
- inspect_ai/model/_providers/anthropic.py +18 -5
- inspect_ai/model/_providers/azureai.py +7 -2
- inspect_ai/model/_providers/util/llama31.py +3 -3
- {inspect_ai-0.3.96.dist-info → inspect_ai-0.3.97.dist-info}/METADATA +1 -1
- {inspect_ai-0.3.96.dist-info → inspect_ai-0.3.97.dist-info}/RECORD +131 -126
- {inspect_ai-0.3.96.dist-info → inspect_ai-0.3.97.dist-info}/WHEEL +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptView.module.css +0 -48
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptView.tsx +0 -276
- {inspect_ai-0.3.96.dist-info → inspect_ai-0.3.97.dist-info}/entry_points.txt +0 -0
- {inspect_ai-0.3.96.dist-info → inspect_ai-0.3.97.dist-info}/licenses/LICENSE +0 -0
- {inspect_ai-0.3.96.dist-info → inspect_ai-0.3.97.dist-info}/top_level.txt +0 -0
@@ -5,23 +5,33 @@ import {
|
|
5
5
|
ReactElement,
|
6
6
|
ReactNode,
|
7
7
|
useCallback,
|
8
|
+
useState,
|
8
9
|
} from "react";
|
9
10
|
import { ApplicationIcons } from "../../../appearance/icons";
|
10
11
|
import { EventNavs } from "./EventNavs";
|
11
12
|
|
12
|
-
import {
|
13
|
+
import { useParams } from "react-router-dom";
|
14
|
+
import { CopyButton } from "../../../../components/CopyButton";
|
15
|
+
import { useCollapseSampleEvent, useProperty } from "../../../../state/hooks";
|
16
|
+
import {
|
17
|
+
sampleEventUrl,
|
18
|
+
supportsLinking,
|
19
|
+
toFullUrl,
|
20
|
+
} from "../../../routing/url";
|
13
21
|
import styles from "./EventPanel.module.css";
|
14
22
|
|
15
23
|
interface EventPanelProps {
|
16
24
|
id: string;
|
25
|
+
depth: number;
|
17
26
|
className?: string | string[];
|
18
27
|
title?: string;
|
19
28
|
subTitle?: string;
|
20
29
|
text?: string;
|
21
30
|
icon?: string;
|
22
|
-
collapse?: boolean;
|
23
31
|
children?: ReactNode | ReactNode[];
|
24
|
-
|
32
|
+
childIds?: string[];
|
33
|
+
collapsibleContent?: boolean;
|
34
|
+
collapseControl?: "top" | "bottom";
|
25
35
|
}
|
26
36
|
|
27
37
|
interface ChildProps {
|
@@ -33,19 +43,33 @@ interface ChildProps {
|
|
33
43
|
*/
|
34
44
|
export const EventPanel: FC<EventPanelProps> = ({
|
35
45
|
id,
|
46
|
+
depth,
|
36
47
|
className,
|
37
48
|
title,
|
38
49
|
subTitle,
|
39
50
|
text,
|
40
51
|
icon,
|
41
|
-
collapse,
|
42
52
|
children,
|
53
|
+
childIds,
|
54
|
+
collapsibleContent,
|
55
|
+
collapseControl = "top",
|
43
56
|
}) => {
|
44
|
-
const [
|
45
|
-
|
46
|
-
|
57
|
+
const [collapsed, setCollapsed] = useCollapseSampleEvent(id);
|
58
|
+
const isCollapsible = (childIds || []).length > 0 || collapsibleContent;
|
59
|
+
const useBottomDongle = isCollapsible && collapseControl === "bottom";
|
47
60
|
|
48
|
-
|
61
|
+
// Get all URL parameters at component level
|
62
|
+
const { logPath, sampleId, epoch } = useParams<{
|
63
|
+
logPath?: string;
|
64
|
+
tabId?: string;
|
65
|
+
sampleId?: string;
|
66
|
+
epoch?: string;
|
67
|
+
}>();
|
68
|
+
|
69
|
+
const url =
|
70
|
+
logPath && supportsLinking()
|
71
|
+
? toFullUrl(sampleEventUrl(id, logPath, sampleId, epoch))
|
72
|
+
: undefined;
|
49
73
|
|
50
74
|
const pillId = (index: number) => {
|
51
75
|
return `${id}-nav-pill-${index}`;
|
@@ -66,7 +90,7 @@ export const EventPanel: FC<EventPanelProps> = ({
|
|
66
90
|
const gridColumns = [];
|
67
91
|
|
68
92
|
// chevron
|
69
|
-
if (
|
93
|
+
if (isCollapsible && !useBottomDongle) {
|
70
94
|
gridColumns.push("minmax(0, max-content)");
|
71
95
|
}
|
72
96
|
|
@@ -77,31 +101,39 @@ export const EventPanel: FC<EventPanelProps> = ({
|
|
77
101
|
|
78
102
|
// title
|
79
103
|
gridColumns.push("minmax(0, max-content)");
|
104
|
+
// id
|
105
|
+
if (url) {
|
106
|
+
gridColumns.push("minmax(0, max-content)");
|
107
|
+
}
|
80
108
|
gridColumns.push("auto");
|
81
109
|
gridColumns.push("minmax(0, max-content)");
|
82
110
|
gridColumns.push("minmax(0, max-content)");
|
83
111
|
|
84
112
|
const toggleCollapse = useCallback(() => {
|
85
|
-
setCollapsed(!
|
86
|
-
}, [setCollapsed,
|
113
|
+
setCollapsed(!collapsed);
|
114
|
+
}, [setCollapsed, collapsed, childIds]);
|
115
|
+
|
116
|
+
const [mouseOver, setMouseOver] = useState(false);
|
87
117
|
|
88
118
|
const titleEl =
|
89
119
|
title || icon || filteredArrChildren.length > 1 ? (
|
90
120
|
<div
|
91
121
|
title={subTitle}
|
92
|
-
className={clsx("text-size-small")}
|
122
|
+
className={clsx("text-size-small", mouseOver ? styles.hover : "")}
|
93
123
|
style={{
|
94
124
|
display: "grid",
|
95
125
|
gridTemplateColumns: gridColumns.join(" "),
|
96
126
|
columnGap: "0.3em",
|
97
|
-
cursor:
|
127
|
+
cursor: isCollapsible && !useBottomDongle ? "pointer" : undefined,
|
98
128
|
}}
|
129
|
+
onMouseEnter={() => setMouseOver(true)}
|
130
|
+
onMouseLeave={() => setMouseOver(false)}
|
99
131
|
>
|
100
|
-
{
|
132
|
+
{isCollapsible && !useBottomDongle ? (
|
101
133
|
<i
|
102
134
|
onClick={toggleCollapse}
|
103
135
|
className={
|
104
|
-
|
136
|
+
collapsed
|
105
137
|
? ApplicationIcons.chevron.right
|
106
138
|
: ApplicationIcons.chevron.down
|
107
139
|
}
|
@@ -126,17 +158,26 @@ export const EventPanel: FC<EventPanelProps> = ({
|
|
126
158
|
>
|
127
159
|
{title}
|
128
160
|
</div>
|
161
|
+
{url ? (
|
162
|
+
<CopyButton
|
163
|
+
value={url}
|
164
|
+
icon={ApplicationIcons.link}
|
165
|
+
className={clsx(styles.copyLink)}
|
166
|
+
/>
|
167
|
+
) : (
|
168
|
+
""
|
169
|
+
)}
|
129
170
|
<div onClick={toggleCollapse}></div>
|
130
171
|
<div
|
131
172
|
className={clsx("text-style-secondary", styles.label)}
|
132
173
|
onClick={toggleCollapse}
|
133
174
|
>
|
134
|
-
{
|
175
|
+
{collapsed ? text : ""}
|
135
176
|
</div>
|
136
177
|
<div className={styles.navs}>
|
137
|
-
{
|
138
|
-
|
139
|
-
filteredArrChildren.length > 1 ? (
|
178
|
+
{isCollapsible && collapsibleContent && collapsed ? (
|
179
|
+
""
|
180
|
+
) : filteredArrChildren && filteredArrChildren.length > 1 ? (
|
140
181
|
<EventNavs
|
141
182
|
navs={filteredArrChildren.map((child, index) => {
|
142
183
|
const defaultTitle = `Tab ${index}`;
|
@@ -163,33 +204,58 @@ export const EventPanel: FC<EventPanelProps> = ({
|
|
163
204
|
);
|
164
205
|
|
165
206
|
const card = (
|
166
|
-
|
167
|
-
|
168
|
-
|
207
|
+
<div
|
208
|
+
id={id}
|
209
|
+
className={clsx(
|
210
|
+
className,
|
211
|
+
styles.card,
|
212
|
+
depth === 0 ? styles.root : undefined,
|
213
|
+
)}
|
214
|
+
>
|
215
|
+
{titleEl}
|
216
|
+
<div
|
217
|
+
className={clsx(
|
218
|
+
"tab-content",
|
219
|
+
styles.cardContent,
|
220
|
+
isCollapsible && collapsed && collapsibleContent
|
221
|
+
? styles.hidden
|
222
|
+
: undefined,
|
223
|
+
)}
|
224
|
+
>
|
225
|
+
{filteredArrChildren?.map((child, index) => {
|
226
|
+
const id = pillId(index);
|
227
|
+
const isSelected = id === selectedNav;
|
228
|
+
|
229
|
+
return (
|
230
|
+
<div
|
231
|
+
key={`children-${id}-${index}`}
|
232
|
+
id={id}
|
233
|
+
className={clsx("tab-pane", "show", isSelected ? "active" : "")}
|
234
|
+
>
|
235
|
+
{child}
|
236
|
+
</div>
|
237
|
+
);
|
238
|
+
})}
|
239
|
+
</div>
|
240
|
+
|
241
|
+
{isCollapsible && useBottomDongle ? (
|
169
242
|
<div
|
170
|
-
className={clsx(
|
171
|
-
|
172
|
-
styles.cardContent,
|
173
|
-
hasCollapse && isCollapsed ? styles.hidden : undefined,
|
174
|
-
)}
|
243
|
+
className={clsx(styles.bottomDongle, "text-size-smallest")}
|
244
|
+
onClick={toggleCollapse}
|
175
245
|
>
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
{child}
|
187
|
-
</div>
|
188
|
-
);
|
189
|
-
})}
|
246
|
+
<i
|
247
|
+
className={clsx(
|
248
|
+
collapsed
|
249
|
+
? ApplicationIcons.chevron.right
|
250
|
+
: ApplicationIcons.chevron.down,
|
251
|
+
styles.dongleIcon,
|
252
|
+
)}
|
253
|
+
/>
|
254
|
+
transcript ({childIds?.length}{" "}
|
255
|
+
{childIds?.length === 1 ? "event" : "events"})
|
190
256
|
</div>
|
191
|
-
|
192
|
-
|
257
|
+
) : undefined}
|
258
|
+
</div>
|
193
259
|
);
|
194
260
|
return card;
|
195
261
|
};
|
@@ -16,12 +16,13 @@ import {
|
|
16
16
|
StoreSpecificRenderableTypes,
|
17
17
|
} from "./StateEventRenderers";
|
18
18
|
|
19
|
-
import { FC, useMemo } from "react";
|
19
|
+
import { FC, useEffect, useMemo } from "react";
|
20
|
+
import { useStore } from "../../../../state/store";
|
21
|
+
import { EventNode } from "../types";
|
20
22
|
import styles from "./StateEventView.module.css";
|
21
23
|
|
22
24
|
interface StateEventViewProps {
|
23
|
-
|
24
|
-
event: StateEvent | StoreEvent;
|
25
|
+
eventNode: EventNode<StateEvent | StoreEvent>;
|
25
26
|
isStore?: boolean;
|
26
27
|
className?: string | string[];
|
27
28
|
}
|
@@ -30,11 +31,12 @@ interface StateEventViewProps {
|
|
30
31
|
* Renders the StateEventView component.
|
31
32
|
*/
|
32
33
|
export const StateEventView: FC<StateEventViewProps> = ({
|
33
|
-
|
34
|
-
event,
|
35
|
-
isStore = false,
|
34
|
+
eventNode,
|
36
35
|
className,
|
37
36
|
}) => {
|
37
|
+
const event = eventNode.event;
|
38
|
+
const id = eventNode.id;
|
39
|
+
|
38
40
|
const summary = useMemo(() => {
|
39
41
|
return summarizeChanges(event.changes);
|
40
42
|
}, [event.changes]);
|
@@ -56,19 +58,28 @@ export const StateEventView: FC<StateEventViewProps> = ({
|
|
56
58
|
// and as a result may be decorated with additional properties, etc..., resulting in DOM elements
|
57
59
|
// appearing attached to state.
|
58
60
|
const changePreview = useMemo(() => {
|
61
|
+
const isStore = eventNode.event.event === "store";
|
59
62
|
return generatePreview(event.changes, structuredClone(after), isStore);
|
60
|
-
}, [event.changes, after
|
63
|
+
}, [event.changes, after]);
|
61
64
|
// Compute the title
|
62
65
|
const title = event.event === "state" ? "State Updated" : "Store Updated";
|
63
66
|
|
67
|
+
const collapseEvent = useStore((state) => state.sampleActions.collapseEvent);
|
68
|
+
useEffect(() => {
|
69
|
+
if (changePreview === undefined) {
|
70
|
+
collapseEvent(id, true);
|
71
|
+
}
|
72
|
+
}, [changePreview, collapseEvent]);
|
73
|
+
|
64
74
|
return (
|
65
75
|
<EventPanel
|
66
76
|
id={id}
|
77
|
+
depth={eventNode.depth}
|
67
78
|
title={title}
|
68
79
|
className={className}
|
69
80
|
subTitle={formatDateTime(new Date(event.timestamp))}
|
70
81
|
text={!changePreview ? summary : undefined}
|
71
|
-
|
82
|
+
collapsibleContent={true}
|
72
83
|
>
|
73
84
|
{changePreview ? (
|
74
85
|
<div data-name="Summary" className={clsx(styles.summary)}>
|
@@ -2,9 +2,18 @@ import { Events } from "../../../../@types/log";
|
|
2
2
|
import { EventNode, EventType } from "../types";
|
3
3
|
import {
|
4
4
|
ACTION_BEGIN,
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
SPAN_BEGIN,
|
6
|
+
SPAN_END,
|
7
|
+
STATE,
|
8
|
+
STEP,
|
9
|
+
STORE,
|
10
|
+
SUBTASK,
|
11
|
+
TOOL,
|
12
|
+
TYPE_AGENT,
|
13
|
+
TYPE_HANDOFF,
|
14
|
+
TYPE_SOLVER,
|
15
|
+
TYPE_SUBTASK,
|
16
|
+
TYPE_TOOL,
|
8
17
|
hasSpans,
|
9
18
|
} from "./utils";
|
10
19
|
|
@@ -17,19 +26,33 @@ type TreeifyFunction = (
|
|
17
26
|
|
18
27
|
export function treeifyEvents(events: Events, depth: number): EventNode[] {
|
19
28
|
const useSpans = hasSpans(events);
|
20
|
-
const
|
29
|
+
const pathIndices: number[] = [];
|
21
30
|
|
22
31
|
const rootNodes: EventNode[] = [];
|
23
32
|
const stack: EventNode[] = [];
|
24
33
|
|
25
34
|
const addNode = (event: EventType): EventNode => {
|
26
|
-
const
|
35
|
+
const currentDepth = stack.length;
|
36
|
+
|
37
|
+
// Track sibling count for the parent node
|
38
|
+
if (pathIndices.length <= currentDepth) {
|
39
|
+
pathIndices.push(0);
|
40
|
+
} else {
|
41
|
+
pathIndices[currentDepth]++;
|
42
|
+
// Reset deeper levels if coming back up the stack
|
43
|
+
pathIndices.length = currentDepth + 1;
|
44
|
+
}
|
45
|
+
|
46
|
+
// Create a new node
|
47
|
+
const idPath = pathIndices.slice(0, currentDepth + 1).join(".");
|
48
|
+
const node = new EventNode(idPath, event, currentDepth + depth);
|
27
49
|
if (stack.length > 0) {
|
28
50
|
const parentNode = stack[stack.length - 1];
|
29
51
|
parentNode.children.push(node);
|
30
52
|
} else {
|
31
53
|
rootNodes.push(node);
|
32
54
|
}
|
55
|
+
|
33
56
|
return node;
|
34
57
|
};
|
35
58
|
|
@@ -38,13 +61,12 @@ export function treeifyEvents(events: Events, depth: number): EventNode[] {
|
|
38
61
|
};
|
39
62
|
|
40
63
|
const popStack = (): void => {
|
41
|
-
|
42
|
-
|
43
|
-
}
|
64
|
+
stack.pop();
|
65
|
+
pathIndices.pop();
|
44
66
|
};
|
45
67
|
|
46
68
|
events.forEach((event) => {
|
47
|
-
|
69
|
+
treeifyFn(event, addNode, pushStack, popStack);
|
48
70
|
});
|
49
71
|
|
50
72
|
if (useSpans) {
|
@@ -54,14 +76,14 @@ export function treeifyEvents(events: Events, depth: number): EventNode[] {
|
|
54
76
|
}
|
55
77
|
}
|
56
78
|
|
57
|
-
const
|
79
|
+
const treeifyFn: TreeifyFunction = (
|
58
80
|
event: EventType,
|
59
81
|
addNode: (event: EventType) => EventNode,
|
60
82
|
pushStack: (node: EventNode) => void,
|
61
83
|
popStack: () => void,
|
62
84
|
): void => {
|
63
85
|
switch (event.event) {
|
64
|
-
case
|
86
|
+
case STEP:
|
65
87
|
if (event.action === ACTION_BEGIN) {
|
66
88
|
// Starting a new step
|
67
89
|
const node = addNode(event);
|
@@ -71,40 +93,55 @@ const treeifyFnStep: TreeifyFunction = (
|
|
71
93
|
popStack();
|
72
94
|
}
|
73
95
|
break;
|
74
|
-
case
|
75
|
-
// These shoudn't be here, but throw away
|
76
|
-
break;
|
77
|
-
}
|
78
|
-
case ET_SPAN_END: {
|
79
|
-
// These shoudn't be here, but throw away
|
80
|
-
break;
|
81
|
-
}
|
82
|
-
default:
|
83
|
-
// An event
|
84
|
-
addNode(event);
|
85
|
-
break;
|
86
|
-
}
|
87
|
-
};
|
88
|
-
|
89
|
-
const treeifyFnSpan: TreeifyFunction = (
|
90
|
-
event: EventType,
|
91
|
-
addNode: (event: EventType) => EventNode,
|
92
|
-
pushStack: (node: EventNode) => void,
|
93
|
-
popStack: () => void,
|
94
|
-
): void => {
|
95
|
-
switch (event.event) {
|
96
|
-
case ET_STEP:
|
97
|
-
// strip steps
|
98
|
-
break;
|
99
|
-
case ET_SPAN_BEGIN: {
|
96
|
+
case SPAN_BEGIN: {
|
100
97
|
const node = addNode(event);
|
101
98
|
pushStack(node);
|
102
99
|
break;
|
103
100
|
}
|
104
|
-
case
|
101
|
+
case SPAN_END: {
|
105
102
|
popStack();
|
106
103
|
break;
|
107
104
|
}
|
105
|
+
case TOOL:
|
106
|
+
{
|
107
|
+
const node = addNode(event);
|
108
|
+
|
109
|
+
// In the span world, the first child will be a span of type tool
|
110
|
+
if (
|
111
|
+
event.events.length > 0 &&
|
112
|
+
(event.events[0].event !== SPAN_BEGIN ||
|
113
|
+
event.events[0].type !== TYPE_TOOL)
|
114
|
+
) {
|
115
|
+
// Expand the children
|
116
|
+
pushStack(node);
|
117
|
+
for (const child of event.events) {
|
118
|
+
treeifyFn(child, addNode, pushStack, popStack);
|
119
|
+
}
|
120
|
+
popStack();
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
break;
|
125
|
+
case SUBTASK:
|
126
|
+
{
|
127
|
+
const node = addNode(event);
|
128
|
+
|
129
|
+
// In the span world, the first child will be a span of type tool
|
130
|
+
if (
|
131
|
+
event.events.length > 0 &&
|
132
|
+
(event.events[0].event !== SPAN_BEGIN ||
|
133
|
+
event.events[0].type !== TYPE_SUBTASK)
|
134
|
+
) {
|
135
|
+
// Expand the children
|
136
|
+
pushStack(node);
|
137
|
+
for (const child of event.events) {
|
138
|
+
treeifyFn(child, addNode, pushStack, popStack);
|
139
|
+
}
|
140
|
+
popStack();
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
break;
|
108
145
|
default:
|
109
146
|
// An event
|
110
147
|
addNode(event);
|
@@ -122,50 +159,50 @@ const treeNodeTransformers: TreeNodeTransformer[] = [
|
|
122
159
|
{
|
123
160
|
name: "unwrap_tools",
|
124
161
|
matches: (node) =>
|
125
|
-
node.event.event ===
|
126
|
-
process: (node) => elevateChildNode(node,
|
162
|
+
node.event.event === SPAN_BEGIN && node.event.type === TYPE_TOOL,
|
163
|
+
process: (node) => elevateChildNode(node, TYPE_TOOL) || node,
|
127
164
|
},
|
128
165
|
{
|
129
166
|
name: "unwrap_subtasks",
|
130
167
|
matches: (node) =>
|
131
|
-
node.event.event ===
|
132
|
-
process: (node) => elevateChildNode(node,
|
168
|
+
node.event.event === SPAN_BEGIN && node.event.type === TYPE_SUBTASK,
|
169
|
+
process: (node) => elevateChildNode(node, TYPE_SUBTASK) || node,
|
133
170
|
},
|
134
171
|
{
|
135
172
|
name: "unwrap_agent_solver",
|
136
173
|
matches: (node) =>
|
137
|
-
node.event.event ===
|
138
|
-
node.event["type"] ===
|
174
|
+
node.event.event === SPAN_BEGIN &&
|
175
|
+
node.event["type"] === TYPE_SOLVER &&
|
139
176
|
node.children.length === 2 &&
|
140
|
-
node.children[0].event.event ===
|
141
|
-
node.children[0].event.type ===
|
142
|
-
node.children[1].event.event ===
|
177
|
+
node.children[0].event.event === SPAN_BEGIN &&
|
178
|
+
node.children[0].event.type === TYPE_AGENT &&
|
179
|
+
node.children[1].event.event === STATE,
|
143
180
|
|
144
181
|
process: (node) => skipFirstChildNode(node),
|
145
182
|
},
|
146
183
|
{
|
147
184
|
name: "unwrap_agent_solver w/store",
|
148
185
|
matches: (node) =>
|
149
|
-
node.event.event ===
|
150
|
-
node.event["type"] ===
|
186
|
+
node.event.event === SPAN_BEGIN &&
|
187
|
+
node.event["type"] === TYPE_SOLVER &&
|
151
188
|
node.children.length === 3 &&
|
152
|
-
node.children[0].event.event ===
|
153
|
-
node.children[0].event.type ===
|
154
|
-
node.children[1].event.event ===
|
155
|
-
node.children[2].event.event ===
|
189
|
+
node.children[0].event.event === SPAN_BEGIN &&
|
190
|
+
node.children[0].event.type === TYPE_AGENT &&
|
191
|
+
node.children[1].event.event === STATE &&
|
192
|
+
node.children[2].event.event === STORE,
|
156
193
|
process: (node) => skipFirstChildNode(node),
|
157
194
|
},
|
158
195
|
{
|
159
196
|
name: "unwrap_handoff",
|
160
197
|
matches: (node) =>
|
161
|
-
node.event.event ===
|
162
|
-
node.event["type"] ===
|
198
|
+
node.event.event === SPAN_BEGIN &&
|
199
|
+
node.event["type"] === TYPE_HANDOFF &&
|
163
200
|
node.children.length === 2 &&
|
164
|
-
node.children[0].event.event ===
|
165
|
-
node.children[1].event.event ===
|
201
|
+
node.children[0].event.event === TOOL &&
|
202
|
+
node.children[1].event.event === STORE &&
|
166
203
|
node.children[0].children.length === 2 &&
|
167
|
-
node.children[0].children[0].event.event ===
|
168
|
-
node.children[0].children[0].event.type ===
|
204
|
+
node.children[0].children[0].event.event === SPAN_BEGIN &&
|
205
|
+
node.children[0].children[0].event.type === TYPE_AGENT,
|
169
206
|
process: (node) => skipThisNode(node),
|
170
207
|
},
|
171
208
|
];
|
@@ -217,7 +254,7 @@ const elevateChildNode = (
|
|
217
254
|
|
218
255
|
// Process the remaining children
|
219
256
|
targetNode.depth = node.depth;
|
220
|
-
targetNode.children =
|
257
|
+
targetNode.children = setDepth(remainingChildren, node.depth + 1);
|
221
258
|
|
222
259
|
// No need to update the event itself (events have been deprecated
|
223
260
|
// and more importantly we drive children / transcripts using the tree structure itself
|
@@ -249,3 +286,34 @@ const reduceDepth = (nodes: EventNode[], depth: number = 1): EventNode[] => {
|
|
249
286
|
return node;
|
250
287
|
});
|
251
288
|
};
|
289
|
+
|
290
|
+
const setDepth = (nodes: EventNode[], depth: number): EventNode[] => {
|
291
|
+
return nodes.map((node) => {
|
292
|
+
if (node.children.length > 0) {
|
293
|
+
node.children = setDepth(node.children, depth + 1);
|
294
|
+
}
|
295
|
+
node.depth = depth;
|
296
|
+
return node;
|
297
|
+
});
|
298
|
+
};
|
299
|
+
|
300
|
+
/**
|
301
|
+
* Flatten the tree structure into a flat array of EventNode objects
|
302
|
+
* Each node in the result will have its children set properly
|
303
|
+
* @param events - The events to flatten
|
304
|
+
* @param depth - The current depth in the tree
|
305
|
+
* @returns An array of EventNode objects
|
306
|
+
*/
|
307
|
+
export const flatTree = (
|
308
|
+
eventNodes: EventNode[],
|
309
|
+
collapsed: Record<string, true> | null,
|
310
|
+
): EventNode[] => {
|
311
|
+
const result: EventNode[] = [];
|
312
|
+
for (const node of eventNodes) {
|
313
|
+
result.push(node);
|
314
|
+
if (collapsed === null || collapsed[node.id] !== true) {
|
315
|
+
result.push(...flatTree(node.children, collapsed));
|
316
|
+
}
|
317
|
+
}
|
318
|
+
return result;
|
319
|
+
};
|
@@ -1,11 +1,21 @@
|
|
1
1
|
import { Events } from "../../../../@types/log";
|
2
2
|
|
3
|
-
export const
|
3
|
+
export const STEP = "step";
|
4
4
|
export const ACTION_BEGIN = "begin";
|
5
5
|
|
6
|
-
export const
|
7
|
-
export const
|
6
|
+
export const SPAN_BEGIN = "span_begin";
|
7
|
+
export const SPAN_END = "span_end";
|
8
|
+
export const TOOL = "tool";
|
9
|
+
export const SUBTASK = "subtask";
|
10
|
+
export const STORE = "store";
|
11
|
+
export const STATE = "state";
|
12
|
+
|
13
|
+
export const TYPE_TOOL = "tool";
|
14
|
+
export const TYPE_SUBTASK = "subtask";
|
15
|
+
export const TYPE_SOLVER = "solver";
|
16
|
+
export const TYPE_AGENT = "agent";
|
17
|
+
export const TYPE_HANDOFF = "handoff";
|
8
18
|
|
9
19
|
export const hasSpans = (events: Events): boolean => {
|
10
|
-
return events.some((event) => event.event ===
|
20
|
+
return events.some((event) => event.event === SPAN_BEGIN);
|
11
21
|
};
|
@@ -45,12 +45,14 @@ export type EventType =
|
|
45
45
|
| SpanBeginEvent
|
46
46
|
| SpanEndEvent;
|
47
47
|
|
48
|
-
export class EventNode {
|
49
|
-
|
50
|
-
|
48
|
+
export class EventNode<T extends EventType = EventType> {
|
49
|
+
id: string;
|
50
|
+
event: T;
|
51
|
+
children: EventNode<EventType>[] = [];
|
51
52
|
depth: number;
|
52
53
|
|
53
|
-
constructor(event:
|
54
|
+
constructor(id: string, event: T, depth: number) {
|
55
|
+
this.id = id;
|
54
56
|
this.event = event;
|
55
57
|
this.depth = depth;
|
56
58
|
}
|
@@ -58,6 +58,7 @@ export interface LogsState {
|
|
58
58
|
logHeaders: Record<string, EvalLogHeader>;
|
59
59
|
headersLoading: boolean;
|
60
60
|
selectedLogIndex: number;
|
61
|
+
selectedLogFile?: string;
|
61
62
|
}
|
62
63
|
|
63
64
|
export interface LogState {
|
@@ -78,13 +79,23 @@ export interface LogState {
|
|
78
79
|
|
79
80
|
export type SampleStatus = "ok" | "loading" | "streaming" | "error";
|
80
81
|
|
82
|
+
export type SampleIdentifier = {
|
83
|
+
id: string | number;
|
84
|
+
epoch: number;
|
85
|
+
};
|
86
|
+
|
81
87
|
export interface SampleState {
|
82
|
-
|
88
|
+
sample_identifier: SampleIdentifier | undefined;
|
89
|
+
sampleInState: boolean;
|
90
|
+
selectedSampleObject?: EvalSample;
|
83
91
|
sampleStatus: SampleStatus;
|
84
92
|
sampleError: Error | undefined;
|
93
|
+
sampleNeedsReload: number;
|
85
94
|
|
86
95
|
// Events and attachments
|
87
96
|
runningEvents: Event[];
|
97
|
+
collapsedEvents: Record<string, true> | null;
|
98
|
+
collapsedIdBuckets: Record<string, Record<string, boolean>>;
|
88
99
|
}
|
89
100
|
|
90
101
|
export type Event =
|