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
@@ -1,5 +1,5 @@
|
|
1
1
|
import { useCallback } from "react";
|
2
|
-
import { useNavigate, useParams } from "react-router-dom";
|
2
|
+
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
|
3
3
|
import { useFilteredSamples } from "../../state/hooks";
|
4
4
|
import { useStore } from "../../state/store";
|
5
5
|
import { directoryRelativeUrl } from "../../utils/uri";
|
@@ -32,6 +32,56 @@ export const useLogNavigation = () => {
|
|
32
32
|
};
|
33
33
|
};
|
34
34
|
|
35
|
+
export const useSampleUrl = () => {
|
36
|
+
const { logPath, tabId, sampleTabId } = useParams<{
|
37
|
+
logPath?: string;
|
38
|
+
tabId?: string;
|
39
|
+
sampleTabId?: string;
|
40
|
+
}>();
|
41
|
+
|
42
|
+
const logDirectory = useStore((state) => state.logs.logs.log_dir);
|
43
|
+
|
44
|
+
const selectedLogFile = useStore((state) => state.logs.selectedLogFile);
|
45
|
+
|
46
|
+
// Helper function to resolve the log path for URLs
|
47
|
+
const resolveLogPath = useCallback(() => {
|
48
|
+
// If we have a logPath from URL params, use that
|
49
|
+
if (logPath) {
|
50
|
+
return logPath;
|
51
|
+
}
|
52
|
+
|
53
|
+
if (selectedLogFile) {
|
54
|
+
return directoryRelativeUrl(selectedLogFile, logDirectory);
|
55
|
+
}
|
56
|
+
|
57
|
+
return undefined;
|
58
|
+
}, [logPath, selectedLogFile, logDirectory]);
|
59
|
+
|
60
|
+
// Get a sample URL for a specific sample
|
61
|
+
const getSampleUrl = useCallback(
|
62
|
+
(
|
63
|
+
sampleId: string | number,
|
64
|
+
epoch: number,
|
65
|
+
specificSampleTabId?: string,
|
66
|
+
) => {
|
67
|
+
const resolvedPath = resolveLogPath();
|
68
|
+
if (resolvedPath) {
|
69
|
+
const currentSampleTabId = specificSampleTabId || sampleTabId;
|
70
|
+
const url = sampleUrl(
|
71
|
+
resolvedPath,
|
72
|
+
sampleId,
|
73
|
+
epoch,
|
74
|
+
currentSampleTabId,
|
75
|
+
);
|
76
|
+
return url;
|
77
|
+
}
|
78
|
+
return undefined;
|
79
|
+
},
|
80
|
+
[resolveLogPath, tabId, sampleTabId],
|
81
|
+
);
|
82
|
+
return getSampleUrl;
|
83
|
+
};
|
84
|
+
|
35
85
|
/**
|
36
86
|
* Hook that provides sample navigation utilities with proper URL handling
|
37
87
|
* for use across the application
|
@@ -50,9 +100,7 @@ export const useSampleNavigation = () => {
|
|
50
100
|
}>();
|
51
101
|
|
52
102
|
// Get the store access values directly in the hook
|
53
|
-
const
|
54
|
-
(state) => state.logsActions.getSelectedLogFile,
|
55
|
-
);
|
103
|
+
const selectedLogFile = useStore((state) => state.logs.selectedLogFile);
|
56
104
|
|
57
105
|
// Helper function to resolve the log path for URLs
|
58
106
|
const resolveLogPath = useCallback(() => {
|
@@ -61,15 +109,12 @@ export const useSampleNavigation = () => {
|
|
61
109
|
return logPath;
|
62
110
|
}
|
63
111
|
|
64
|
-
// Otherwise use the selected log file
|
65
|
-
const selectedLogFile = getSelectedLogFile();
|
66
|
-
|
67
112
|
if (selectedLogFile) {
|
68
113
|
return directoryRelativeUrl(selectedLogFile, logDirectory);
|
69
114
|
}
|
70
115
|
|
71
116
|
return undefined;
|
72
|
-
}, [logPath,
|
117
|
+
}, [logPath, selectedLogFile, logDirectory]);
|
73
118
|
|
74
119
|
// The samples
|
75
120
|
const sampleSummaries = useFilteredSamples();
|
@@ -180,3 +225,13 @@ export const useSampleNavigation = () => {
|
|
180
225
|
clearSampleUrl,
|
181
226
|
};
|
182
227
|
};
|
228
|
+
|
229
|
+
export const useSampleDetailNavigation = () => {
|
230
|
+
const [searchParams, _setSearchParams] = useSearchParams();
|
231
|
+
const message = searchParams.get("message");
|
232
|
+
const event = searchParams.get("event");
|
233
|
+
return {
|
234
|
+
message,
|
235
|
+
event,
|
236
|
+
};
|
237
|
+
};
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import { kSampleMessagesTabId, kSampleTranscriptTabId } from "../../constants";
|
1
2
|
import { directoryRelativeUrl } from "../../utils/uri";
|
2
3
|
|
3
4
|
export const kLogRouteUrlPattern = "/logs/:logPath/:tabId?/:sampleTabId?";
|
@@ -29,6 +30,38 @@ export const sampleUrl = (
|
|
29
30
|
}
|
30
31
|
};
|
31
32
|
|
33
|
+
export const sampleEventUrl = (
|
34
|
+
eventId: string,
|
35
|
+
logPath: string,
|
36
|
+
sampleId?: string | number,
|
37
|
+
sampleEpoch?: string | number,
|
38
|
+
) => {
|
39
|
+
const baseUrl = sampleUrl(
|
40
|
+
logPath,
|
41
|
+
sampleId,
|
42
|
+
sampleEpoch,
|
43
|
+
kSampleTranscriptTabId,
|
44
|
+
);
|
45
|
+
|
46
|
+
return `${baseUrl}?event=${eventId}`;
|
47
|
+
};
|
48
|
+
|
49
|
+
export const sampleMessageUrl = (
|
50
|
+
messageId: string,
|
51
|
+
logPath: string,
|
52
|
+
sampleId?: string | number,
|
53
|
+
sampleEpoch?: string | number,
|
54
|
+
) => {
|
55
|
+
const baseUrl = sampleUrl(
|
56
|
+
logPath,
|
57
|
+
sampleId,
|
58
|
+
sampleEpoch,
|
59
|
+
kSampleMessagesTabId,
|
60
|
+
);
|
61
|
+
|
62
|
+
return `${baseUrl}?message=${messageId}`;
|
63
|
+
};
|
64
|
+
|
32
65
|
export const logUrl = (log_file: string, log_dir?: string, tabId?: string) => {
|
33
66
|
const pathSegment = directoryRelativeUrl(log_file, log_dir);
|
34
67
|
return logUrlRaw(pathSegment, tabId);
|
@@ -41,3 +74,15 @@ export const logUrlRaw = (log_segment: string, tabId?: string) => {
|
|
41
74
|
return `/logs/${encodeURIComponent(log_segment)}`;
|
42
75
|
}
|
43
76
|
};
|
77
|
+
|
78
|
+
export const supportsLinking = () => {
|
79
|
+
return (
|
80
|
+
location.hostname !== "localhost" &&
|
81
|
+
location.hostname !== "127.0.0.1" &&
|
82
|
+
location.protocol !== "vscode-webview:"
|
83
|
+
);
|
84
|
+
};
|
85
|
+
|
86
|
+
export const toFullUrl = (path: string) => {
|
87
|
+
return `${window.location.origin}${window.location.pathname}#${path}`;
|
88
|
+
};
|
@@ -31,30 +31,37 @@ export const InlineSampleDisplay: FC = () => {
|
|
31
31
|
: true,
|
32
32
|
);
|
33
33
|
const prevLogFile = usePrevious<string | undefined>(logSelection.loadedLog);
|
34
|
+
const prevSampleNeedsReload = usePrevious<number>(
|
35
|
+
sampleData.sampleNeedsReload,
|
36
|
+
);
|
37
|
+
|
34
38
|
useEffect(() => {
|
35
39
|
if (logSelection.logFile && logSelection.sample) {
|
36
40
|
const currentSampleCompleted =
|
37
|
-
logSelection.sample
|
41
|
+
logSelection.sample.completed !== undefined
|
38
42
|
? logSelection.sample.completed
|
39
43
|
: true;
|
40
44
|
|
41
45
|
if (
|
42
|
-
(prevLogFile !== undefined && prevLogFile !== logSelection.
|
43
|
-
sampleData.
|
44
|
-
sampleData.
|
46
|
+
(prevLogFile !== undefined && prevLogFile !== logSelection.logFile) ||
|
47
|
+
sampleData.selectedSampleIdentifier?.id !== logSelection.sample.id ||
|
48
|
+
sampleData.selectedSampleIdentifier?.epoch !==
|
49
|
+
logSelection.sample.epoch ||
|
45
50
|
(prevCompleted !== undefined &&
|
46
|
-
currentSampleCompleted !== prevCompleted)
|
51
|
+
currentSampleCompleted !== prevCompleted) ||
|
52
|
+
prevSampleNeedsReload !== sampleData.sampleNeedsReload
|
47
53
|
) {
|
48
54
|
loadSample(logSelection.logFile, logSelection.sample);
|
49
55
|
}
|
50
56
|
}
|
51
57
|
}, [
|
52
|
-
logSelection.
|
58
|
+
logSelection.logFile,
|
53
59
|
logSelection.sample?.id,
|
54
60
|
logSelection.sample?.epoch,
|
55
61
|
logSelection.sample?.completed,
|
56
|
-
sampleData.
|
57
|
-
sampleData.
|
62
|
+
sampleData.selectedSampleIdentifier?.id,
|
63
|
+
sampleData.selectedSampleIdentifier?.epoch,
|
64
|
+
sampleData.sampleNeedsReload,
|
58
65
|
]);
|
59
66
|
|
60
67
|
// Scroll ref
|
@@ -9,6 +9,8 @@ import { useStore } from "../../state/store";
|
|
9
9
|
import { useSampleNavigation } from "../routing/navigationHooks";
|
10
10
|
import { SampleDisplay } from "./SampleDisplay";
|
11
11
|
|
12
|
+
import styles from "./SampleDialog.module.css";
|
13
|
+
|
12
14
|
interface SampleDialogProps {
|
13
15
|
id: string;
|
14
16
|
title: string;
|
@@ -46,6 +48,9 @@ export const SampleDialog: FC<SampleDialogProps> = ({
|
|
46
48
|
: true,
|
47
49
|
);
|
48
50
|
const prevLogFile = usePrevious<string | undefined>(logSelection.logFile);
|
51
|
+
const prevSampleNeedsReload = usePrevious<number>(
|
52
|
+
sampleData.sampleNeedsReload,
|
53
|
+
);
|
49
54
|
|
50
55
|
useEffect(() => {
|
51
56
|
if (logSelection.logFile && logSelection.sample) {
|
@@ -56,10 +61,12 @@ export const SampleDialog: FC<SampleDialogProps> = ({
|
|
56
61
|
|
57
62
|
if (
|
58
63
|
(prevLogFile !== undefined && prevLogFile !== logSelection.logFile) ||
|
59
|
-
sampleData.
|
60
|
-
sampleData.
|
64
|
+
sampleData.selectedSampleIdentifier?.id !== logSelection.sample.id ||
|
65
|
+
sampleData.selectedSampleIdentifier?.epoch !==
|
66
|
+
logSelection.sample.epoch ||
|
61
67
|
(prevCompleted !== undefined &&
|
62
|
-
currentSampleCompleted !== prevCompleted)
|
68
|
+
currentSampleCompleted !== prevCompleted) ||
|
69
|
+
prevSampleNeedsReload !== sampleData.sampleNeedsReload
|
63
70
|
) {
|
64
71
|
loadSample(logSelection.logFile, logSelection.sample);
|
65
72
|
}
|
@@ -69,8 +76,9 @@ export const SampleDialog: FC<SampleDialogProps> = ({
|
|
69
76
|
logSelection.sample?.id,
|
70
77
|
logSelection.sample?.epoch,
|
71
78
|
logSelection.sample?.completed,
|
72
|
-
sampleData.
|
73
|
-
sampleData.
|
79
|
+
sampleData.selectedSampleIdentifier?.id,
|
80
|
+
sampleData.selectedSampleIdentifier?.epoch,
|
81
|
+
sampleData.sampleNeedsReload,
|
74
82
|
]);
|
75
83
|
|
76
84
|
// Get sample navigation utilities
|
@@ -139,6 +147,9 @@ export const SampleDialog: FC<SampleDialogProps> = ({
|
|
139
147
|
onkeyup={handleKeyUp}
|
140
148
|
visible={showingSampleDialog}
|
141
149
|
onHide={onHide}
|
150
|
+
classNames={{
|
151
|
+
body: styles.modalBody,
|
152
|
+
}}
|
142
153
|
showProgress={
|
143
154
|
sampleData.status === "loading" || sampleData.status === "streaming"
|
144
155
|
}
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import { TabPanel, TabSet } from "../../components/TabSet";
|
2
|
-
import { MetaDataView } from "../content/MetaDataView";
|
3
2
|
|
4
3
|
import { escapeSelector } from "../../utils/html";
|
5
4
|
import { isVscode } from "../../utils/vscode";
|
@@ -34,15 +33,23 @@ import {
|
|
34
33
|
import { useFilteredSamples, useSampleData } from "../../state/hooks";
|
35
34
|
import { useStore } from "../../state/store";
|
36
35
|
import { formatTime } from "../../utils/format";
|
36
|
+
import { estimateSize } from "../../utils/json";
|
37
37
|
import { printHeadingHtml, printHtml } from "../../utils/print";
|
38
|
-
import {
|
38
|
+
import { RecordTree } from "../content/RecordTree";
|
39
|
+
import { useSampleDetailNavigation } from "../routing/navigationHooks";
|
40
|
+
import {
|
41
|
+
sampleMessageUrl,
|
42
|
+
sampleUrl,
|
43
|
+
supportsLinking,
|
44
|
+
toFullUrl,
|
45
|
+
} from "../routing/url";
|
39
46
|
import { ModelTokenTable } from "../usage/ModelTokenTable";
|
40
47
|
import { ChatViewVirtualList } from "./chat/ChatViewVirtualList";
|
41
48
|
import { messagesFromEvents } from "./chat/messages";
|
42
49
|
import styles from "./SampleDisplay.module.css";
|
43
50
|
import { SampleSummaryView } from "./SampleSummaryView";
|
44
51
|
import { SampleScoresView } from "./scores/SampleScoresView";
|
45
|
-
import { TranscriptVirtualList } from "./transcript/
|
52
|
+
import { TranscriptVirtualList } from "./transcript/TranscriptVirtualList";
|
46
53
|
|
47
54
|
interface SampleDisplayProps {
|
48
55
|
id: string;
|
@@ -61,7 +68,10 @@ export const SampleDisplay: FC<SampleDisplayProps> = ({ id, scrollRef }) => {
|
|
61
68
|
);
|
62
69
|
|
63
70
|
const sampleData = useSampleData();
|
64
|
-
const sample =
|
71
|
+
const sample = useMemo(() => {
|
72
|
+
return sampleData.getSelectedSample();
|
73
|
+
}, [sampleData.selectedSampleIdentifier, sampleData.getSelectedSample]);
|
74
|
+
|
65
75
|
const runningSampleData = sampleData.running;
|
66
76
|
|
67
77
|
// Selected tab handling
|
@@ -105,6 +115,12 @@ export const SampleDisplay: FC<SampleDisplayProps> = ({ id, scrollRef }) => {
|
|
105
115
|
epoch?: string;
|
106
116
|
}>();
|
107
117
|
|
118
|
+
const getMessageUrl = (id: string) => {
|
119
|
+
return id && urlLogPath && supportsLinking()
|
120
|
+
? toFullUrl(sampleMessageUrl(id, urlLogPath, urlSampleId, urlEpoch))
|
121
|
+
: undefined;
|
122
|
+
};
|
123
|
+
|
108
124
|
// Tab selection
|
109
125
|
const onSelectedTab = useCallback(
|
110
126
|
(e: MouseEvent<HTMLElement>) => {
|
@@ -129,7 +145,11 @@ export const SampleDisplay: FC<SampleDisplayProps> = ({ id, scrollRef }) => {
|
|
129
145
|
],
|
130
146
|
);
|
131
147
|
|
132
|
-
const sampleMetadatas = metadataViewsForSample(
|
148
|
+
const sampleMetadatas = metadataViewsForSample(
|
149
|
+
`${baseId}-${id}`,
|
150
|
+
scrollRef,
|
151
|
+
sample,
|
152
|
+
);
|
133
153
|
|
134
154
|
const tabsetId = `task-sample-details-tab-${id}`;
|
135
155
|
const targetId = `${tabsetId}-content`;
|
@@ -153,6 +173,8 @@ export const SampleDisplay: FC<SampleDisplayProps> = ({ id, scrollRef }) => {
|
|
153
173
|
// Is the sample running?
|
154
174
|
const running = isRunning(sampleSummary, runningSampleData);
|
155
175
|
|
176
|
+
const sampleDetailNavigation = useSampleDetailNavigation();
|
177
|
+
|
156
178
|
return (
|
157
179
|
<Fragment>
|
158
180
|
{sample || sampleSummary ? (
|
@@ -167,7 +189,7 @@ export const SampleDisplay: FC<SampleDisplayProps> = ({ id, scrollRef }) => {
|
|
167
189
|
<TabPanel
|
168
190
|
key={kSampleTranscriptTabId}
|
169
191
|
id={kSampleTranscriptTabId}
|
170
|
-
className="sample-tab"
|
192
|
+
className={clsx("sample-tab", styles.transcriptContainer)}
|
171
193
|
title="Transcript"
|
172
194
|
onSelected={onSelectedTab}
|
173
195
|
selected={
|
@@ -180,6 +202,7 @@ export const SampleDisplay: FC<SampleDisplayProps> = ({ id, scrollRef }) => {
|
|
180
202
|
key={`${baseId}-transcript-display-${id}`}
|
181
203
|
id={`${baseId}-transcript-display-${id}`}
|
182
204
|
events={sampleEvents || []}
|
205
|
+
initialEventId={sampleDetailNavigation.event}
|
183
206
|
running={running}
|
184
207
|
scrollRef={scrollRef}
|
185
208
|
/>
|
@@ -197,10 +220,12 @@ export const SampleDisplay: FC<SampleDisplayProps> = ({ id, scrollRef }) => {
|
|
197
220
|
key={`${baseId}-chat-${id}`}
|
198
221
|
id={`${baseId}-chat-${id}`}
|
199
222
|
messages={sampleMessages}
|
223
|
+
initialMessageId={sampleDetailNavigation.message}
|
200
224
|
indented={true}
|
201
225
|
scrollRef={scrollRef}
|
202
226
|
toolCallStyle="complete"
|
203
227
|
running={running}
|
228
|
+
getMessageUrl={getMessageUrl}
|
204
229
|
/>
|
205
230
|
</TabPanel>
|
206
231
|
<TabPanel
|
@@ -211,7 +236,11 @@ export const SampleDisplay: FC<SampleDisplayProps> = ({ id, scrollRef }) => {
|
|
211
236
|
onSelected={onSelectedTab}
|
212
237
|
selected={effectiveSelectedTab === kSampleScoringTabId}
|
213
238
|
>
|
214
|
-
<SampleScoresView
|
239
|
+
<SampleScoresView
|
240
|
+
sample={sample}
|
241
|
+
className={styles.padded}
|
242
|
+
scrollRef={scrollRef}
|
243
|
+
/>
|
215
244
|
</TabPanel>
|
216
245
|
<TabPanel
|
217
246
|
id={kSampleMetdataTabId}
|
@@ -220,8 +249,10 @@ export const SampleDisplay: FC<SampleDisplayProps> = ({ id, scrollRef }) => {
|
|
220
249
|
onSelected={onSelectedTab}
|
221
250
|
selected={effectiveSelectedTab === kSampleMetdataTabId}
|
222
251
|
>
|
223
|
-
{sampleMetadatas.length > 0 ? (
|
224
|
-
<div className={clsx(styles.
|
252
|
+
{!sample || sampleMetadatas.length > 0 ? (
|
253
|
+
<div className={clsx(styles.padded, styles.fullWidth)}>
|
254
|
+
{sampleMetadatas}
|
255
|
+
</div>
|
225
256
|
) : (
|
226
257
|
<NoContentsPanel text="No metadata" />
|
227
258
|
)}
|
@@ -280,8 +311,8 @@ export const SampleDisplay: FC<SampleDisplayProps> = ({ id, scrollRef }) => {
|
|
280
311
|
>
|
281
312
|
{!sample ? (
|
282
313
|
<NoContentsPanel text="JSON not available" />
|
283
|
-
) : sample.
|
284
|
-
<NoContentsPanel text="JSON too large
|
314
|
+
) : estimateSize(sample.events) > 250000 ? (
|
315
|
+
<NoContentsPanel text="JSON too large to display" />
|
285
316
|
) : (
|
286
317
|
<div className={clsx(styles.padded, styles.fullWidth)}>
|
287
318
|
<JSONPanel
|
@@ -297,7 +328,11 @@ export const SampleDisplay: FC<SampleDisplayProps> = ({ id, scrollRef }) => {
|
|
297
328
|
);
|
298
329
|
};
|
299
330
|
|
300
|
-
const metadataViewsForSample = (
|
331
|
+
const metadataViewsForSample = (
|
332
|
+
id: string,
|
333
|
+
scrollRef: RefObject<HTMLDivElement | null>,
|
334
|
+
sample?: EvalSample,
|
335
|
+
) => {
|
301
336
|
if (!sample) {
|
302
337
|
return [];
|
303
338
|
}
|
@@ -326,17 +361,16 @@ const metadataViewsForSample = (id: string, sample?: EvalSample) => {
|
|
326
361
|
sampleMetadatas.push(
|
327
362
|
<Card key={`sample-time-${id}`}>
|
328
363
|
<CardHeader label="Time" />
|
329
|
-
<CardBody>
|
330
|
-
<
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
</div>
|
364
|
+
<CardBody padded={false}>
|
365
|
+
<RecordTree
|
366
|
+
id={`task-sample-time-${id}`}
|
367
|
+
record={{
|
368
|
+
Working: formatTime(sample.working_time),
|
369
|
+
Total: formatTime(sample.total_time),
|
370
|
+
}}
|
371
|
+
className={clsx("tab-pane", styles.noTop)}
|
372
|
+
scrollRef={scrollRef}
|
373
|
+
/>
|
340
374
|
</CardBody>
|
341
375
|
</Card>,
|
342
376
|
);
|
@@ -346,11 +380,12 @@ const metadataViewsForSample = (id: string, sample?: EvalSample) => {
|
|
346
380
|
sampleMetadatas.push(
|
347
381
|
<Card key={`sample-metadata-${id}`}>
|
348
382
|
<CardHeader label="Metadata" />
|
349
|
-
<CardBody>
|
350
|
-
<
|
351
|
-
id=
|
352
|
-
|
383
|
+
<CardBody padded={false}>
|
384
|
+
<RecordTree
|
385
|
+
id={`task-sample-metadata-${id}`}
|
386
|
+
record={sample?.metadata as Record<string, unknown>}
|
353
387
|
className={clsx("tab-pane", styles.noTop)}
|
388
|
+
scrollRef={scrollRef}
|
354
389
|
/>
|
355
390
|
</CardBody>
|
356
391
|
</Card>,
|
@@ -361,11 +396,13 @@ const metadataViewsForSample = (id: string, sample?: EvalSample) => {
|
|
361
396
|
sampleMetadatas.push(
|
362
397
|
<Card key={`sample-store-${id}`}>
|
363
398
|
<CardHeader label="Store" />
|
364
|
-
<CardBody>
|
365
|
-
<
|
366
|
-
id=
|
367
|
-
|
399
|
+
<CardBody padded={false}>
|
400
|
+
<RecordTree
|
401
|
+
id={`task-sample-store-${id}`}
|
402
|
+
record={sample?.store as Record<string, unknown>}
|
368
403
|
className={clsx("tab-pane", styles.noTop)}
|
404
|
+
scrollRef={scrollRef}
|
405
|
+
processStore={true}
|
369
406
|
/>
|
370
407
|
</CardBody>
|
371
408
|
</Card>,
|
@@ -5,17 +5,13 @@
|
|
5
5
|
white-space: normal;
|
6
6
|
}
|
7
7
|
|
8
|
-
.padded {
|
9
|
-
padding-bottom: 1em;
|
10
|
-
}
|
11
|
-
|
12
8
|
.systemRole {
|
13
9
|
opacity: 0.7;
|
14
10
|
}
|
15
11
|
|
16
12
|
.messageGrid {
|
17
13
|
display: grid;
|
18
|
-
grid-template-columns: max-content
|
14
|
+
grid-template-columns: max-content max-content max-content;
|
19
15
|
column-gap: 0.3em;
|
20
16
|
font-weight: 500;
|
21
17
|
margin-bottom: 0.3em;
|
@@ -27,6 +23,15 @@
|
|
27
23
|
}
|
28
24
|
|
29
25
|
.messageContents.indented {
|
30
|
-
margin-left:
|
31
|
-
|
26
|
+
margin-left: 0rem;
|
27
|
+
}
|
28
|
+
|
29
|
+
.copyLink {
|
30
|
+
opacity: 0;
|
31
|
+
padding-left: 0;
|
32
|
+
padding-right: 2em;
|
33
|
+
}
|
34
|
+
|
35
|
+
.copyLink:hover {
|
36
|
+
opacity: 1;
|
32
37
|
}
|
@@ -6,10 +6,11 @@ import {
|
|
6
6
|
ChatMessageTool,
|
7
7
|
ChatMessageUser,
|
8
8
|
} from "../../../@types/log";
|
9
|
+
import { CopyButton } from "../../../components/CopyButton";
|
9
10
|
import ExpandablePanel from "../../../components/ExpandablePanel";
|
11
|
+
import { ApplicationIcons } from "../../appearance/icons";
|
10
12
|
import styles from "./ChatMessage.module.css";
|
11
13
|
import { MessageContents } from "./MessageContents";
|
12
|
-
import { iconForMsg } from "./messages";
|
13
14
|
import { ChatViewToolCallStyle } from "./types";
|
14
15
|
|
15
16
|
interface ChatMessageProps {
|
@@ -18,7 +19,7 @@ interface ChatMessageProps {
|
|
18
19
|
toolMessages: ChatMessageTool[];
|
19
20
|
indented?: boolean;
|
20
21
|
toolCallStyle: ChatViewToolCallStyle;
|
21
|
-
|
22
|
+
getMessageUrl?: (id: string) => string | undefined;
|
22
23
|
}
|
23
24
|
|
24
25
|
export const ChatMessage: FC<ChatMessageProps> = ({
|
@@ -27,8 +28,11 @@ export const ChatMessage: FC<ChatMessageProps> = ({
|
|
27
28
|
toolMessages,
|
28
29
|
indented,
|
29
30
|
toolCallStyle,
|
30
|
-
|
31
|
+
getMessageUrl,
|
31
32
|
}) => {
|
33
|
+
const messageUrl =
|
34
|
+
message.id && getMessageUrl ? getMessageUrl(message.id) : undefined;
|
35
|
+
|
32
36
|
const collapse = message.role === "system" || message.role === "user";
|
33
37
|
return (
|
34
38
|
<div
|
@@ -36,13 +40,21 @@ export const ChatMessage: FC<ChatMessageProps> = ({
|
|
36
40
|
message.role,
|
37
41
|
"text-size-base",
|
38
42
|
styles.message,
|
39
|
-
padded ? styles.padded : undefined,
|
40
43
|
message.role === "system" ? styles.systemRole : undefined,
|
44
|
+
message.role === "user" ? styles.userRole : undefined,
|
41
45
|
)}
|
42
46
|
>
|
43
47
|
<div className={clsx(styles.messageGrid, "text-style-label")}>
|
44
|
-
<i className={iconForMsg(message)} />
|
45
48
|
{message.role}
|
49
|
+
{messageUrl ? (
|
50
|
+
<CopyButton
|
51
|
+
icon={ApplicationIcons.link}
|
52
|
+
value={messageUrl}
|
53
|
+
className={clsx(styles.copyLink)}
|
54
|
+
/>
|
55
|
+
) : (
|
56
|
+
""
|
57
|
+
)}
|
46
58
|
</div>
|
47
59
|
<div
|
48
60
|
className={clsx(
|