inspect-ai 0.3.99__py3-none-any.whl → 0.3.100__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/_display/core/config.py +11 -5
- inspect_ai/_display/core/panel.py +66 -2
- inspect_ai/_display/core/textual.py +5 -2
- inspect_ai/_display/plain/display.py +1 -0
- inspect_ai/_display/rich/display.py +2 -2
- inspect_ai/_display/textual/widgets/transcript.py +37 -9
- inspect_ai/_eval/score.py +2 -4
- inspect_ai/_eval/task/run.py +59 -81
- inspect_ai/_util/content.py +11 -6
- inspect_ai/_util/interrupt.py +2 -2
- inspect_ai/_util/text.py +7 -0
- inspect_ai/_util/working.py +8 -37
- inspect_ai/_view/__init__.py +0 -0
- inspect_ai/_view/schema.py +2 -1
- inspect_ai/_view/www/CLAUDE.md +15 -0
- inspect_ai/_view/www/dist/assets/index.css +263 -159
- inspect_ai/_view/www/dist/assets/index.js +22153 -19093
- inspect_ai/_view/www/log-schema.json +77 -3
- inspect_ai/_view/www/package.json +5 -1
- inspect_ai/_view/www/src/@types/log.d.ts +9 -0
- inspect_ai/_view/www/src/app/App.tsx +1 -15
- inspect_ai/_view/www/src/app/appearance/icons.ts +4 -1
- inspect_ai/_view/www/src/app/content/MetaDataGrid.tsx +24 -6
- inspect_ai/_view/www/src/app/content/MetadataGrid.module.css +0 -5
- inspect_ai/_view/www/src/app/content/RenderedContent.tsx +220 -205
- inspect_ai/_view/www/src/app/log-view/LogViewContainer.tsx +2 -1
- inspect_ai/_view/www/src/app/log-view/tabs/SamplesTab.tsx +5 -0
- inspect_ai/_view/www/src/app/routing/url.ts +84 -4
- inspect_ai/_view/www/src/app/samples/InlineSampleDisplay.module.css +0 -5
- inspect_ai/_view/www/src/app/samples/SampleDialog.module.css +1 -1
- inspect_ai/_view/www/src/app/samples/SampleDisplay.module.css +7 -0
- inspect_ai/_view/www/src/app/samples/SampleDisplay.tsx +24 -17
- inspect_ai/_view/www/src/app/samples/SampleSummaryView.module.css +1 -2
- inspect_ai/_view/www/src/app/samples/chat/ChatMessage.tsx +8 -6
- inspect_ai/_view/www/src/app/samples/chat/ChatMessageRow.tsx +0 -4
- inspect_ai/_view/www/src/app/samples/chat/ChatViewVirtualList.tsx +3 -2
- inspect_ai/_view/www/src/app/samples/chat/MessageContent.tsx +2 -0
- inspect_ai/_view/www/src/app/samples/chat/MessageContents.tsx +2 -0
- inspect_ai/_view/www/src/app/samples/chat/messages.ts +1 -0
- inspect_ai/_view/www/src/app/samples/chat/tools/ToolCallView.tsx +1 -0
- inspect_ai/_view/www/src/app/samples/list/SampleRow.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/ErrorEventView.tsx +1 -2
- inspect_ai/_view/www/src/app/samples/transcript/InfoEventView.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/InputEventView.tsx +1 -2
- inspect_ai/_view/www/src/app/samples/transcript/ModelEventView.module.css +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/ModelEventView.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/SampleInitEventView.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/SampleLimitEventView.tsx +3 -2
- inspect_ai/_view/www/src/app/samples/transcript/SandboxEventView.tsx +4 -5
- inspect_ai/_view/www/src/app/samples/transcript/ScoreEventView.tsx +1 -1
- inspect_ai/_view/www/src/app/samples/transcript/SpanEventView.tsx +1 -2
- inspect_ai/_view/www/src/app/samples/transcript/StepEventView.tsx +1 -3
- inspect_ai/_view/www/src/app/samples/transcript/SubtaskEventView.tsx +1 -2
- inspect_ai/_view/www/src/app/samples/transcript/ToolEventView.tsx +3 -4
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptPanel.module.css +42 -0
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptPanel.tsx +77 -0
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualList.tsx +27 -71
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualListComponent.module.css +13 -3
- inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualListComponent.tsx +27 -2
- inspect_ai/_view/www/src/app/samples/transcript/event/EventPanel.module.css +1 -0
- inspect_ai/_view/www/src/app/samples/transcript/event/EventPanel.tsx +21 -22
- inspect_ai/_view/www/src/app/samples/transcript/outline/OutlineRow.module.css +45 -0
- inspect_ai/_view/www/src/app/samples/transcript/outline/OutlineRow.tsx +223 -0
- inspect_ai/_view/www/src/app/samples/transcript/outline/TranscriptOutline.module.css +10 -0
- inspect_ai/_view/www/src/app/samples/transcript/outline/TranscriptOutline.tsx +258 -0
- inspect_ai/_view/www/src/app/samples/transcript/outline/tree-visitors.ts +187 -0
- inspect_ai/_view/www/src/app/samples/transcript/state/StateEventRenderers.tsx +8 -1
- inspect_ai/_view/www/src/app/samples/transcript/state/StateEventView.tsx +3 -4
- inspect_ai/_view/www/src/app/samples/transcript/transform/hooks.ts +78 -0
- inspect_ai/_view/www/src/app/samples/transcript/transform/treeify.ts +340 -135
- inspect_ai/_view/www/src/app/samples/transcript/transform/utils.ts +3 -0
- inspect_ai/_view/www/src/app/samples/transcript/types.ts +2 -0
- inspect_ai/_view/www/src/app/types.ts +5 -1
- inspect_ai/_view/www/src/client/api/api-browser.ts +2 -2
- inspect_ai/_view/www/src/components/LiveVirtualList.tsx +6 -1
- inspect_ai/_view/www/src/components/MarkdownDiv.tsx +1 -1
- inspect_ai/_view/www/src/components/PopOver.tsx +422 -0
- inspect_ai/_view/www/src/components/PulsingDots.module.css +9 -9
- inspect_ai/_view/www/src/components/PulsingDots.tsx +4 -1
- inspect_ai/_view/www/src/components/StickyScroll.tsx +183 -0
- inspect_ai/_view/www/src/components/TabSet.tsx +4 -0
- inspect_ai/_view/www/src/state/hooks.ts +52 -2
- inspect_ai/_view/www/src/state/logSlice.ts +4 -3
- inspect_ai/_view/www/src/state/samplePolling.ts +8 -0
- inspect_ai/_view/www/src/state/sampleSlice.ts +53 -9
- inspect_ai/_view/www/src/state/scrolling.ts +152 -0
- inspect_ai/_view/www/src/utils/attachments.ts +7 -0
- inspect_ai/_view/www/src/utils/python.ts +18 -0
- inspect_ai/_view/www/yarn.lock +269 -6
- inspect_ai/agent/_react.py +12 -7
- inspect_ai/agent/_run.py +2 -3
- inspect_ai/analysis/beta/_dataframe/samples/table.py +19 -18
- inspect_ai/log/_log.py +1 -1
- inspect_ai/log/_recorders/file.py +2 -9
- inspect_ai/log/_transcript.py +1 -1
- inspect_ai/model/_call_tools.py +6 -2
- inspect_ai/model/_openai.py +1 -1
- inspect_ai/model/_openai_responses.py +78 -39
- inspect_ai/model/_openai_web_search.py +31 -0
- inspect_ai/model/_providers/azureai.py +72 -3
- inspect_ai/model/_providers/openai.py +2 -1
- inspect_ai/scorer/_metric.py +1 -2
- inspect_ai/solver/_task_state.py +2 -2
- inspect_ai/tool/_tool.py +6 -2
- inspect_ai/tool/_tool_def.py +27 -4
- inspect_ai/tool/_tool_info.py +2 -0
- inspect_ai/tool/_tools/_web_search/_google.py +15 -4
- inspect_ai/tool/_tools/_web_search/_tavily.py +35 -12
- inspect_ai/tool/_tools/_web_search/_web_search.py +214 -45
- inspect_ai/util/__init__.py +4 -0
- inspect_ai/util/_json.py +3 -0
- inspect_ai/util/_limit.py +230 -20
- inspect_ai/util/_sandbox/docker/compose.py +20 -11
- inspect_ai/util/_span.py +1 -1
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.100.dist-info}/METADATA +3 -3
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.100.dist-info}/RECORD +120 -106
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.100.dist-info}/WHEEL +1 -1
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.100.dist-info}/entry_points.txt +0 -0
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.100.dist-info}/licenses/LICENSE +0 -0
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.100.dist-info}/top_level.txt +0 -0
@@ -2,7 +2,6 @@ import { FC, memo, RefObject, useEffect, useMemo } from "react";
|
|
2
2
|
import {
|
3
3
|
ApprovalEvent,
|
4
4
|
ErrorEvent,
|
5
|
-
Events,
|
6
5
|
InfoEvent,
|
7
6
|
InputEvent,
|
8
7
|
LoggerEvent,
|
@@ -32,20 +31,22 @@ import { StateEventView } from "./state/StateEventView";
|
|
32
31
|
import { StepEventView } from "./StepEventView";
|
33
32
|
import { SubtaskEventView } from "./SubtaskEventView";
|
34
33
|
import { ToolEventView } from "./ToolEventView";
|
35
|
-
import { EventNode } from "./types";
|
34
|
+
import { EventNode, kTranscriptCollapseScope } from "./types";
|
36
35
|
|
37
36
|
import { useStore } from "../../../state/store";
|
38
37
|
import { SpanEventView } from "./SpanEventView";
|
39
38
|
import { TranscriptVirtualListComponent } from "./TranscriptVirtualListComponent";
|
40
|
-
import {
|
41
|
-
import { flatTree, treeifyEvents } from "./transform/treeify";
|
39
|
+
import { flatTree } from "./transform/treeify";
|
42
40
|
|
43
41
|
interface TranscriptVirtualListProps {
|
44
42
|
id: string;
|
45
|
-
|
43
|
+
eventNodes: EventNode[];
|
44
|
+
defaultCollapsedIds: Record<string, boolean>;
|
46
45
|
initialEventId: string | null;
|
46
|
+
offsetTop?: number;
|
47
47
|
scrollRef: RefObject<HTMLDivElement | null>;
|
48
48
|
running?: boolean;
|
49
|
+
className?: string | string[];
|
49
50
|
}
|
50
51
|
|
51
52
|
/**
|
@@ -53,7 +54,16 @@ interface TranscriptVirtualListProps {
|
|
53
54
|
*/
|
54
55
|
export const TranscriptVirtualList: FC<TranscriptVirtualListProps> = memo(
|
55
56
|
(props) => {
|
56
|
-
let {
|
57
|
+
let {
|
58
|
+
id,
|
59
|
+
scrollRef,
|
60
|
+
eventNodes,
|
61
|
+
defaultCollapsedIds,
|
62
|
+
running,
|
63
|
+
initialEventId,
|
64
|
+
offsetTop,
|
65
|
+
className,
|
66
|
+
} = props;
|
57
67
|
|
58
68
|
// The list of events that have been collapsed
|
59
69
|
const collapsedEvents = useStore((state) => state.sample.collapsedEvents);
|
@@ -61,93 +71,39 @@ export const TranscriptVirtualList: FC<TranscriptVirtualListProps> = memo(
|
|
61
71
|
(state) => state.sampleActions.setCollapsedEvents,
|
62
72
|
);
|
63
73
|
|
64
|
-
|
65
|
-
const { eventNodes, defaultCollapsedIds } = useMemo(() => {
|
66
|
-
// Apply fixups to the event string
|
67
|
-
const resolvedEvents = fixupEventStream(events, !running);
|
68
|
-
|
69
|
-
// Build the event tree
|
70
|
-
const eventTree = treeifyEvents(resolvedEvents, 0);
|
71
|
-
|
72
|
-
// Apply collapse filters to the event tree
|
73
|
-
const defaultCollapsedIds: Record<string, true> = {};
|
74
|
-
const findCollapsibleEvents = (nodes: EventNode[]) => {
|
75
|
-
for (const node of nodes) {
|
76
|
-
if (
|
77
|
-
(node.event.event === "step" ||
|
78
|
-
node.event.event === "span_begin" ||
|
79
|
-
node.event.event === "tool" ||
|
80
|
-
node.event.event === "subtask") &&
|
81
|
-
collapseFilters.some((filter) =>
|
82
|
-
filter(
|
83
|
-
node.event as
|
84
|
-
| StepEvent
|
85
|
-
| SpanBeginEvent
|
86
|
-
| ToolEvent
|
87
|
-
| SubtaskEvent,
|
88
|
-
),
|
89
|
-
)
|
90
|
-
) {
|
91
|
-
defaultCollapsedIds[node.id] = true;
|
92
|
-
}
|
93
|
-
|
94
|
-
// Recursively check children
|
95
|
-
findCollapsibleEvents(node.children);
|
96
|
-
}
|
97
|
-
};
|
98
|
-
findCollapsibleEvents(eventTree);
|
99
|
-
|
74
|
+
const flattenedNodes = useMemo(() => {
|
100
75
|
// flattten the event tree
|
101
|
-
|
102
|
-
|
103
|
-
collapsedEvents
|
76
|
+
return flatTree(
|
77
|
+
eventNodes,
|
78
|
+
(collapsedEvents
|
79
|
+
? collapsedEvents[kTranscriptCollapseScope]
|
80
|
+
: undefined) || defaultCollapsedIds,
|
104
81
|
);
|
105
|
-
|
106
|
-
return { eventNodes, defaultCollapsedIds };
|
107
|
-
}, [events, running, collapsedEvents]);
|
82
|
+
}, [eventNodes, collapsedEvents, defaultCollapsedIds]);
|
108
83
|
|
109
84
|
// Update the collapsed events when the default collapsed IDs change
|
110
85
|
// This effect only depends on defaultCollapsedIds, not eventNodes
|
111
86
|
useEffect(() => {
|
112
87
|
// Only initialize collapsedEvents if it's empty
|
113
88
|
if (!collapsedEvents && Object.keys(defaultCollapsedIds).length > 0) {
|
114
|
-
setCollapsedEvents(defaultCollapsedIds);
|
89
|
+
setCollapsedEvents(kTranscriptCollapseScope, defaultCollapsedIds);
|
115
90
|
}
|
116
91
|
}, [defaultCollapsedIds, collapsedEvents, setCollapsedEvents]);
|
117
92
|
|
118
93
|
return (
|
119
94
|
<TranscriptVirtualListComponent
|
120
95
|
id={id}
|
121
|
-
eventNodes={
|
96
|
+
eventNodes={flattenedNodes}
|
122
97
|
initialEventId={initialEventId}
|
98
|
+
offsetTop={offsetTop}
|
123
99
|
scrollRef={scrollRef}
|
124
100
|
running={running}
|
101
|
+
className={className}
|
125
102
|
/>
|
126
103
|
);
|
127
104
|
},
|
128
105
|
);
|
129
106
|
|
130
|
-
const collapseFilters: Array<
|
131
|
-
(event: StepEvent | SpanBeginEvent | ToolEvent | SubtaskEvent) => boolean
|
132
|
-
> = [
|
133
|
-
(event: StepEvent | SpanBeginEvent | ToolEvent | SubtaskEvent) =>
|
134
|
-
event.type === "solver" && event.name === "system_message",
|
135
|
-
(event: StepEvent | SpanBeginEvent | ToolEvent | SubtaskEvent) => {
|
136
|
-
if (event.event === "step" || event.event === "span_begin") {
|
137
|
-
return (
|
138
|
-
event.name === kSandboxSignalName ||
|
139
|
-
event.name === "init" ||
|
140
|
-
event.name === "sample_init"
|
141
|
-
);
|
142
|
-
}
|
143
|
-
return false;
|
144
|
-
},
|
145
|
-
(event: StepEvent | SpanBeginEvent | ToolEvent | SubtaskEvent) =>
|
146
|
-
event.event === "tool" && !event.agent && !event.failed,
|
147
|
-
(event: StepEvent | SpanBeginEvent | ToolEvent | SubtaskEvent) =>
|
148
|
-
event.event === "subtask",
|
149
|
-
];
|
150
|
-
|
151
107
|
interface RenderedEventNodeProps {
|
152
108
|
node: EventNode;
|
153
109
|
className?: string | string[];
|
@@ -1,9 +1,19 @@
|
|
1
1
|
.node {
|
2
|
-
padding-top: 0.
|
3
|
-
padding-bottom: 1px;
|
2
|
+
padding-top: 0.8rem;
|
4
3
|
}
|
5
4
|
|
6
5
|
.attached {
|
7
6
|
padding-top: 0rem;
|
8
|
-
|
7
|
+
}
|
8
|
+
|
9
|
+
.attachedParent {
|
10
|
+
padding-bottom: 0px;
|
11
|
+
border-bottom-left-radius: 0;
|
12
|
+
border-bottom-right-radius: 0;
|
13
|
+
border-bottom: none;
|
14
|
+
}
|
15
|
+
|
16
|
+
.attachedChild {
|
17
|
+
border-top-left-radius: 0;
|
18
|
+
border-top-right-radius: 0;
|
9
19
|
}
|
@@ -10,8 +10,10 @@ interface TranscriptVirtualListComponentProps {
|
|
10
10
|
id: string;
|
11
11
|
eventNodes: EventNode[];
|
12
12
|
initialEventId?: string | null;
|
13
|
+
offsetTop?: number;
|
13
14
|
scrollRef?: RefObject<HTMLDivElement | null>;
|
14
15
|
running?: boolean;
|
16
|
+
className?: string | string[];
|
15
17
|
}
|
16
18
|
|
17
19
|
/**
|
@@ -19,7 +21,15 @@ interface TranscriptVirtualListComponentProps {
|
|
19
21
|
*/
|
20
22
|
export const TranscriptVirtualListComponent: FC<
|
21
23
|
TranscriptVirtualListComponentProps
|
22
|
-
> = ({
|
24
|
+
> = ({
|
25
|
+
id,
|
26
|
+
eventNodes,
|
27
|
+
scrollRef,
|
28
|
+
running,
|
29
|
+
initialEventId,
|
30
|
+
offsetTop,
|
31
|
+
className,
|
32
|
+
}) => {
|
23
33
|
const initialEventIndex = useMemo(() => {
|
24
34
|
if (initialEventId === null || initialEventId === undefined) {
|
25
35
|
return undefined;
|
@@ -35,14 +45,24 @@ export const TranscriptVirtualListComponent: FC<
|
|
35
45
|
const paddingClass = index === 0 ? styles.first : undefined;
|
36
46
|
|
37
47
|
const previousIndex = index - 1;
|
48
|
+
const nextIndex = index + 1;
|
38
49
|
const previous =
|
39
50
|
previousIndex > 0 && previousIndex <= eventNodes.length
|
40
51
|
? eventNodes[previousIndex]
|
41
52
|
: undefined;
|
53
|
+
const next =
|
54
|
+
nextIndex < eventNodes.length ? eventNodes[nextIndex] : undefined;
|
42
55
|
const attached =
|
43
56
|
item.event.event === "tool" &&
|
44
57
|
(previous?.event.event === "tool" || previous?.event.event === "model");
|
58
|
+
|
59
|
+
const attachedParent =
|
60
|
+
item.event.event === "model" && next?.event.event === "tool";
|
45
61
|
const attachedClass = attached ? styles.attached : undefined;
|
62
|
+
const attachedChildClass = attached ? styles.attachedChild : undefined;
|
63
|
+
const attachedParentClass = attachedParent
|
64
|
+
? styles.attachedParent
|
65
|
+
: undefined;
|
46
66
|
|
47
67
|
return (
|
48
68
|
<div
|
@@ -54,7 +74,10 @@ export const TranscriptVirtualListComponent: FC<
|
|
54
74
|
paddingRight: `${item.depth === 0 ? undefined : ".7em"} `,
|
55
75
|
}}
|
56
76
|
>
|
57
|
-
<RenderedEventNode
|
77
|
+
<RenderedEventNode
|
78
|
+
node={item}
|
79
|
+
className={clsx(attachedParentClass, attachedChildClass)}
|
80
|
+
/>
|
58
81
|
</div>
|
59
82
|
);
|
60
83
|
},
|
@@ -63,10 +86,12 @@ export const TranscriptVirtualListComponent: FC<
|
|
63
86
|
|
64
87
|
return (
|
65
88
|
<LiveVirtualList<EventNode>
|
89
|
+
className={className}
|
66
90
|
id={id}
|
67
91
|
scrollRef={scrollRef}
|
68
92
|
data={eventNodes}
|
69
93
|
initialTopMostItemIndex={initialEventIndex}
|
94
|
+
offsetTop={offsetTop}
|
70
95
|
renderRow={renderRow}
|
71
96
|
live={running}
|
72
97
|
/>
|
@@ -10,18 +10,18 @@ import {
|
|
10
10
|
import { ApplicationIcons } from "../../../appearance/icons";
|
11
11
|
import { EventNavs } from "./EventNavs";
|
12
12
|
|
13
|
-
import { useParams } from "react-router-dom";
|
14
13
|
import { CopyButton } from "../../../../components/CopyButton";
|
15
14
|
import { useCollapseSampleEvent, useProperty } from "../../../../state/hooks";
|
16
15
|
import {
|
17
|
-
sampleEventUrl,
|
18
16
|
supportsLinking,
|
19
17
|
toFullUrl,
|
18
|
+
useSampleEventUrl,
|
20
19
|
} from "../../../routing/url";
|
20
|
+
import { kTranscriptCollapseScope } from "../types";
|
21
21
|
import styles from "./EventPanel.module.css";
|
22
22
|
|
23
23
|
interface EventPanelProps {
|
24
|
-
|
24
|
+
eventNodeId: string;
|
25
25
|
depth: number;
|
26
26
|
className?: string | string[];
|
27
27
|
title?: string;
|
@@ -42,7 +42,7 @@ interface ChildProps {
|
|
42
42
|
* Renders the StateEventView component.
|
43
43
|
*/
|
44
44
|
export const EventPanel: FC<EventPanelProps> = ({
|
45
|
-
|
45
|
+
eventNodeId,
|
46
46
|
depth,
|
47
47
|
className,
|
48
48
|
title,
|
@@ -54,26 +54,21 @@ export const EventPanel: FC<EventPanelProps> = ({
|
|
54
54
|
collapsibleContent,
|
55
55
|
collapseControl = "top",
|
56
56
|
}) => {
|
57
|
-
const [collapsed, setCollapsed] = useCollapseSampleEvent(
|
57
|
+
const [collapsed, setCollapsed] = useCollapseSampleEvent(
|
58
|
+
kTranscriptCollapseScope,
|
59
|
+
eventNodeId,
|
60
|
+
);
|
58
61
|
const isCollapsible = (childIds || []).length > 0 || collapsibleContent;
|
59
62
|
const useBottomDongle = isCollapsible && collapseControl === "bottom";
|
60
63
|
|
61
|
-
|
62
|
-
const { logPath, sampleId, epoch } = useParams<{
|
63
|
-
logPath?: string;
|
64
|
-
tabId?: string;
|
65
|
-
sampleId?: string;
|
66
|
-
epoch?: string;
|
67
|
-
}>();
|
68
|
-
|
64
|
+
const sampleEventUrl = useSampleEventUrl(eventNodeId);
|
69
65
|
const url =
|
70
|
-
|
71
|
-
? toFullUrl(sampleEventUrl(id, logPath, sampleId, epoch))
|
72
|
-
: undefined;
|
66
|
+
supportsLinking() && sampleEventUrl ? toFullUrl(sampleEventUrl) : undefined;
|
73
67
|
|
74
68
|
const pillId = (index: number) => {
|
75
|
-
return `${
|
69
|
+
return `${eventNodeId}-nav-pill-${index}`;
|
76
70
|
};
|
71
|
+
|
77
72
|
const filteredArrChildren = (
|
78
73
|
Array.isArray(children) ? children : [children]
|
79
74
|
).filter((child) => !!child);
|
@@ -83,9 +78,13 @@ export const EventPanel: FC<EventPanelProps> = ({
|
|
83
78
|
});
|
84
79
|
const defaultPillId = defaultPill !== -1 ? pillId(defaultPill) : pillId(0);
|
85
80
|
|
86
|
-
const [selectedNav, setSelectedNav] = useProperty(
|
87
|
-
|
88
|
-
|
81
|
+
const [selectedNav, setSelectedNav] = useProperty(
|
82
|
+
eventNodeId,
|
83
|
+
"selectedNav",
|
84
|
+
{
|
85
|
+
defaultValue: defaultPillId,
|
86
|
+
},
|
87
|
+
);
|
89
88
|
|
90
89
|
const gridColumns = [];
|
91
90
|
|
@@ -186,7 +185,7 @@ export const EventPanel: FC<EventPanelProps> = ({
|
|
186
185
|
? (child.props as ChildProps)["data-name"] || defaultTitle
|
187
186
|
: defaultTitle;
|
188
187
|
return {
|
189
|
-
id: `eventpanel-${
|
188
|
+
id: `eventpanel-${eventNodeId}-${index}`,
|
190
189
|
title: title,
|
191
190
|
target: pillId(index),
|
192
191
|
};
|
@@ -205,7 +204,7 @@ export const EventPanel: FC<EventPanelProps> = ({
|
|
205
204
|
|
206
205
|
const card = (
|
207
206
|
<div
|
208
|
-
id={
|
207
|
+
id={`event-panel-${eventNodeId}`}
|
209
208
|
className={clsx(
|
210
209
|
className,
|
211
210
|
styles.card,
|
@@ -0,0 +1,45 @@
|
|
1
|
+
.eventRow {
|
2
|
+
display: grid;
|
3
|
+
grid-template-columns: 10px 1fr;
|
4
|
+
column-gap: 3px;
|
5
|
+
cursor: pointer;
|
6
|
+
}
|
7
|
+
|
8
|
+
.eventRow.selected {
|
9
|
+
font-weight: 800;
|
10
|
+
}
|
11
|
+
|
12
|
+
.eventRow .toggle {
|
13
|
+
font-size: 0.7em;
|
14
|
+
margin-top: 4px;
|
15
|
+
}
|
16
|
+
|
17
|
+
.eventLink {
|
18
|
+
color: var(--bs-body);
|
19
|
+
text-decoration: none;
|
20
|
+
cursor: pointer;
|
21
|
+
}
|
22
|
+
|
23
|
+
.eventLink:hover {
|
24
|
+
text-decoration: underline;
|
25
|
+
color: var(--bs-link-hover-color);
|
26
|
+
}
|
27
|
+
|
28
|
+
.label {
|
29
|
+
white-space: nowrap;
|
30
|
+
overflow: hidden;
|
31
|
+
text-overflow: ellipsis;
|
32
|
+
}
|
33
|
+
|
34
|
+
.icon {
|
35
|
+
margin-right: 3px;
|
36
|
+
}
|
37
|
+
|
38
|
+
.progress {
|
39
|
+
margin-left: 0.3em !important;
|
40
|
+
}
|
41
|
+
|
42
|
+
.popover {
|
43
|
+
min-width: 300px;
|
44
|
+
max-width: 80%;
|
45
|
+
}
|
@@ -0,0 +1,223 @@
|
|
1
|
+
import clsx from "clsx";
|
2
|
+
import { FC, ReactNode, useRef } from "react";
|
3
|
+
import { Link } from "react-router-dom";
|
4
|
+
import { PopOver } from "../../../../components/PopOver";
|
5
|
+
import { PulsingDots } from "../../../../components/PulsingDots";
|
6
|
+
import {
|
7
|
+
useCollapseSampleEvent,
|
8
|
+
useSamplePopover,
|
9
|
+
} from "../../../../state/hooks";
|
10
|
+
import { formatDateTime, formatTime } from "../../../../utils/format";
|
11
|
+
import { parsePackageName } from "../../../../utils/python";
|
12
|
+
import { ApplicationIcons } from "../../../appearance/icons";
|
13
|
+
import { MetaDataGrid } from "../../../content/MetaDataGrid";
|
14
|
+
import { useSampleEventUrl } from "../../../routing/url";
|
15
|
+
import { kSandboxSignalName } from "../transform/fixups";
|
16
|
+
import { EventNode } from "../types";
|
17
|
+
import styles from "./OutlineRow.module.css";
|
18
|
+
|
19
|
+
export interface OutlineRowProps {
|
20
|
+
node: EventNode;
|
21
|
+
collapseScope: string;
|
22
|
+
running?: boolean;
|
23
|
+
selected?: boolean;
|
24
|
+
}
|
25
|
+
|
26
|
+
export const OutlineRow: FC<OutlineRowProps> = ({
|
27
|
+
node,
|
28
|
+
collapseScope,
|
29
|
+
running,
|
30
|
+
selected,
|
31
|
+
}) => {
|
32
|
+
const [collapsed, setCollapsed] = useCollapseSampleEvent(
|
33
|
+
collapseScope,
|
34
|
+
node.id,
|
35
|
+
);
|
36
|
+
const icon = iconForNode(node);
|
37
|
+
const toggle = toggleIcon(node, collapsed);
|
38
|
+
|
39
|
+
const popoverId = `${node.id}-popover`;
|
40
|
+
const { isShowing } = useSamplePopover(popoverId);
|
41
|
+
|
42
|
+
const ref = useRef(null);
|
43
|
+
|
44
|
+
// Get all URL parameters at component level
|
45
|
+
const sampleEventUrl = useSampleEventUrl(node.id);
|
46
|
+
|
47
|
+
return (
|
48
|
+
<>
|
49
|
+
<div
|
50
|
+
className={clsx(
|
51
|
+
styles.eventRow,
|
52
|
+
"text-size-smallest",
|
53
|
+
selected ? styles.selected : "",
|
54
|
+
)}
|
55
|
+
style={{ paddingLeft: `${node.depth * 0.4}em` }}
|
56
|
+
>
|
57
|
+
<div
|
58
|
+
className={clsx(styles.toggle)}
|
59
|
+
onClick={() => {
|
60
|
+
setCollapsed(!collapsed);
|
61
|
+
}}
|
62
|
+
>
|
63
|
+
{toggle ? <i className={clsx(toggle)} /> : undefined}
|
64
|
+
</div>
|
65
|
+
<div className={clsx(styles.label)} data-depth={node.depth}>
|
66
|
+
{icon ? <i className={clsx(icon, styles.icon)} /> : undefined}
|
67
|
+
{sampleEventUrl ? (
|
68
|
+
<Link
|
69
|
+
to={sampleEventUrl}
|
70
|
+
className={clsx(styles.eventLink)}
|
71
|
+
ref={ref}
|
72
|
+
>
|
73
|
+
{parsePackageName(labelForNode(node)).module}
|
74
|
+
</Link>
|
75
|
+
) : (
|
76
|
+
<span ref={ref}>{parsePackageName(labelForNode(node)).module}</span>
|
77
|
+
)}
|
78
|
+
{running ? (
|
79
|
+
<PulsingDots
|
80
|
+
size="small"
|
81
|
+
className={clsx(styles.progress)}
|
82
|
+
subtle={false}
|
83
|
+
/>
|
84
|
+
) : undefined}
|
85
|
+
</div>
|
86
|
+
</div>
|
87
|
+
<PopOver
|
88
|
+
id={`${node.id}-popover`}
|
89
|
+
positionEl={ref.current}
|
90
|
+
isOpen={isShowing}
|
91
|
+
className={clsx(styles.popper)}
|
92
|
+
placement="auto-end"
|
93
|
+
>
|
94
|
+
{summarizeNode(node)}
|
95
|
+
</PopOver>
|
96
|
+
</>
|
97
|
+
);
|
98
|
+
};
|
99
|
+
|
100
|
+
const toggleIcon = (
|
101
|
+
node: EventNode,
|
102
|
+
collapsed: boolean,
|
103
|
+
): string | undefined => {
|
104
|
+
if (node.children.length > 0) {
|
105
|
+
return collapsed
|
106
|
+
? ApplicationIcons.chevron.right
|
107
|
+
: ApplicationIcons.chevron.down;
|
108
|
+
}
|
109
|
+
};
|
110
|
+
|
111
|
+
const iconForNode = (node: EventNode): string | undefined => {
|
112
|
+
switch (node.event.event) {
|
113
|
+
case "sample_limit":
|
114
|
+
return ApplicationIcons.limits.custom;
|
115
|
+
|
116
|
+
case "score":
|
117
|
+
return ApplicationIcons.scorer;
|
118
|
+
|
119
|
+
case "error":
|
120
|
+
return ApplicationIcons.error;
|
121
|
+
}
|
122
|
+
};
|
123
|
+
|
124
|
+
const labelForNode = (node: EventNode): string => {
|
125
|
+
if (node.event.event === "span_begin") {
|
126
|
+
switch (node.event.type) {
|
127
|
+
case "solver":
|
128
|
+
return node.event.name;
|
129
|
+
case "tool":
|
130
|
+
return node.event.name;
|
131
|
+
default: {
|
132
|
+
if (node.event.name === kSandboxSignalName) {
|
133
|
+
return "sandbox events";
|
134
|
+
}
|
135
|
+
return node.event.name;
|
136
|
+
}
|
137
|
+
}
|
138
|
+
} else {
|
139
|
+
switch (node.event.event) {
|
140
|
+
case "subtask":
|
141
|
+
return node.event.name;
|
142
|
+
case "approval":
|
143
|
+
switch (node.event.decision) {
|
144
|
+
case "approve":
|
145
|
+
return "approved";
|
146
|
+
case "reject":
|
147
|
+
return "rejected";
|
148
|
+
case "escalate":
|
149
|
+
return "escalated";
|
150
|
+
case "modify":
|
151
|
+
return "modified";
|
152
|
+
case "terminate":
|
153
|
+
return "terminated";
|
154
|
+
default:
|
155
|
+
return node.event.decision;
|
156
|
+
}
|
157
|
+
case "model":
|
158
|
+
return `model${node.event.role ? ` (${node.event.role})` : ""}`;
|
159
|
+
case "score":
|
160
|
+
return "scoring";
|
161
|
+
case "step":
|
162
|
+
if (node.event.name === kSandboxSignalName) {
|
163
|
+
return "sandbox events";
|
164
|
+
}
|
165
|
+
return node.event.name;
|
166
|
+
|
167
|
+
default:
|
168
|
+
return node.event.event;
|
169
|
+
}
|
170
|
+
}
|
171
|
+
};
|
172
|
+
|
173
|
+
export const summarizeNode = (node: EventNode): ReactNode => {
|
174
|
+
let entries: Record<string, unknown> = {};
|
175
|
+
switch (node.event.event) {
|
176
|
+
case "sample_init":
|
177
|
+
entries = {
|
178
|
+
sample_id: node.event.sample.id,
|
179
|
+
sandbox: node.event.sample.sandbox?.type,
|
180
|
+
started: formatDateTime(new Date(node.event.timestamp)),
|
181
|
+
working_start: formatTime(node.event.working_start),
|
182
|
+
};
|
183
|
+
break;
|
184
|
+
|
185
|
+
case "sample_limit":
|
186
|
+
entries = {
|
187
|
+
type: node.event.type,
|
188
|
+
message: node.event.message,
|
189
|
+
limit: node.event.limit,
|
190
|
+
started: formatDateTime(new Date(node.event.timestamp)),
|
191
|
+
working_start: formatTime(node.event.working_start),
|
192
|
+
};
|
193
|
+
break;
|
194
|
+
case "score":
|
195
|
+
entries = {
|
196
|
+
answer: node.event.score.answer,
|
197
|
+
score: node.event.score.value,
|
198
|
+
started: formatDateTime(new Date(node.event.timestamp)),
|
199
|
+
working_start: formatTime(node.event.working_start),
|
200
|
+
};
|
201
|
+
break;
|
202
|
+
case "span_begin":
|
203
|
+
entries = {
|
204
|
+
name: node.event.name,
|
205
|
+
started: formatDateTime(new Date(node.event.timestamp)),
|
206
|
+
working_start: formatTime(node.event.working_start),
|
207
|
+
};
|
208
|
+
break;
|
209
|
+
default:
|
210
|
+
entries = {
|
211
|
+
started: formatDateTime(new Date(node.event.timestamp)),
|
212
|
+
working_start: formatTime(node.event.working_start),
|
213
|
+
};
|
214
|
+
}
|
215
|
+
|
216
|
+
return (
|
217
|
+
<MetaDataGrid
|
218
|
+
entries={entries}
|
219
|
+
size="mini"
|
220
|
+
className={clsx(styles.popover, "text-size-smallest")}
|
221
|
+
/>
|
222
|
+
);
|
223
|
+
};
|