inspect-ai 0.3.99__py3-none-any.whl → 0.3.101__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/_cli/eval.py +2 -1
- 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/eval.py +13 -1
- inspect_ai/_eval/evalset.py +3 -2
- inspect_ai/_eval/run.py +2 -0
- inspect_ai/_eval/score.py +2 -4
- inspect_ai/_eval/task/log.py +3 -1
- 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 +307 -171
- inspect_ai/_view/www/dist/assets/index.js +24733 -21641
- inspect_ai/_view/www/log-schema.json +77 -3
- inspect_ai/_view/www/package.json +9 -5
- 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/log-view/tabs/grouping.ts +4 -4
- inspect_ai/_view/www/src/app/routing/navigationHooks.ts +22 -25
- 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/SampleList.tsx +17 -5
- 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 +290 -33
- inspect_ai/agent/_react.py +12 -7
- inspect_ai/agent/_run.py +2 -3
- inspect_ai/analysis/beta/__init__.py +2 -0
- inspect_ai/analysis/beta/_dataframe/samples/table.py +19 -18
- inspect_ai/dataset/_sources/csv.py +2 -6
- inspect_ai/dataset/_sources/hf.py +2 -6
- inspect_ai/dataset/_sources/json.py +2 -6
- inspect_ai/dataset/_util.py +23 -0
- inspect_ai/log/_log.py +1 -1
- inspect_ai/log/_recorders/eval.py +4 -3
- inspect_ai/log/_recorders/file.py +2 -9
- inspect_ai/log/_recorders/json.py +1 -0
- inspect_ai/log/_recorders/recorder.py +1 -0
- 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 +85 -41
- inspect_ai/model/_openai_web_search.py +38 -0
- inspect_ai/model/_providers/azureai.py +72 -3
- inspect_ai/model/_providers/openai.py +4 -1
- inspect_ai/model/_providers/openai_responses.py +5 -1
- inspect_ai/scorer/_metric.py +1 -2
- inspect_ai/scorer/_reducer/reducer.py +1 -1
- 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 +43 -15
- inspect_ai/tool/_tools/_web_search/_tavily.py +46 -13
- 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.101.dist-info}/METADATA +3 -3
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.101.dist-info}/RECORD +138 -124
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.101.dist-info}/WHEEL +1 -1
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.101.dist-info}/entry_points.txt +0 -0
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.101.dist-info}/licenses/LICENSE +0 -0
- {inspect_ai-0.3.99.dist-info → inspect_ai-0.3.101.dist-info}/top_level.txt +0 -0
@@ -1,16 +1,14 @@
|
|
1
|
-
import JSON5 from "json5";
|
2
|
-
import { ApplicationIcons } from "../appearance/icons";
|
3
|
-
|
4
|
-
import { ChatMessageRenderer } from "../../app/samples/chat/ChatMessageRenderer";
|
5
|
-
import { ANSIDisplay } from "../../components/AnsiDisplay";
|
6
|
-
import { formatNumber } from "../../utils/format";
|
7
|
-
import { MetaDataView } from "./MetaDataView";
|
8
|
-
|
9
1
|
import clsx from "clsx";
|
2
|
+
import JSON5 from "json5";
|
10
3
|
import { FC, Fragment, isValidElement, JSX, ReactNode } from "react";
|
4
|
+
import { ANSIDisplay } from "../../components/AnsiDisplay";
|
11
5
|
import JSONPanel from "../../components/JsonPanel";
|
12
6
|
import { MarkdownDiv } from "../../components/MarkdownDiv";
|
7
|
+
import { formatNumber } from "../../utils/format";
|
13
8
|
import { isJson } from "../../utils/json";
|
9
|
+
import { ApplicationIcons } from "../appearance/icons";
|
10
|
+
import { ChatMessageRenderer } from "../samples/chat/ChatMessageRenderer";
|
11
|
+
import { MetaDataView } from "./MetaDataView";
|
14
12
|
import styles from "./RenderedContent.module.css";
|
15
13
|
import { Buckets, ContentRenderer, RenderOptions } from "./types";
|
16
14
|
|
@@ -18,6 +16,7 @@ interface RenderedContentProps {
|
|
18
16
|
id: string;
|
19
17
|
entry: { name: string; value: unknown };
|
20
18
|
renderOptions?: RenderOptions;
|
19
|
+
renderObject?(entry: any): ReactNode;
|
21
20
|
}
|
22
21
|
|
23
22
|
/**
|
@@ -27,15 +26,16 @@ export const RenderedContent: FC<RenderedContentProps> = ({
|
|
27
26
|
id,
|
28
27
|
entry,
|
29
28
|
renderOptions = { renderString: "markdown" },
|
29
|
+
renderObject,
|
30
30
|
}): JSX.Element => {
|
31
31
|
// Explicitly specify return type
|
32
32
|
if (entry.value === null) {
|
33
33
|
return <span>[null]</span>;
|
34
34
|
}
|
35
|
-
|
36
|
-
const renderer = Object.keys(
|
35
|
+
const renderers = contentRenderers(renderObject);
|
36
|
+
const renderer = Object.keys(renderers)
|
37
37
|
.map((key) => {
|
38
|
-
return
|
38
|
+
return renderers[key];
|
39
39
|
})
|
40
40
|
.sort((a, b) => {
|
41
41
|
return a.bucket - b.bucket;
|
@@ -70,216 +70,231 @@ export const RenderedContent: FC<RenderedContentProps> = ({
|
|
70
70
|
* Object containing different content renderers.
|
71
71
|
* Each renderer is responsible for rendering a specific type of content.
|
72
72
|
*/
|
73
|
-
const contentRenderers:
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
)
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
canRender: (entry) => {
|
90
|
-
if (typeof entry.value === "string") {
|
91
|
-
const trimmed = entry.value.trim();
|
92
|
-
return isJson(trimmed);
|
93
|
-
}
|
94
|
-
return false;
|
95
|
-
},
|
96
|
-
render: (_id, entry, _options) => {
|
97
|
-
const obj = JSON5.parse(entry.value);
|
98
|
-
return { rendered: <JSONPanel data={obj as Record<string, unknown>} /> };
|
99
|
-
},
|
100
|
-
},
|
101
|
-
|
102
|
-
Model: {
|
103
|
-
bucket: Buckets.intermediate,
|
104
|
-
canRender: (entry) => {
|
105
|
-
return typeof entry.value === "object" && entry.value._model;
|
106
|
-
},
|
107
|
-
render: (_id, entry, _options) => {
|
108
|
-
return {
|
109
|
-
rendered: (
|
110
|
-
<Fragment>
|
111
|
-
<i className={ApplicationIcons.model} /> {entry.value._model}
|
112
|
-
</Fragment>
|
113
|
-
),
|
114
|
-
};
|
115
|
-
},
|
116
|
-
},
|
117
|
-
Boolean: {
|
118
|
-
bucket: Buckets.intermediate,
|
119
|
-
canRender: (entry) => {
|
120
|
-
return typeof entry.value === "boolean";
|
121
|
-
},
|
122
|
-
render: (id, entry, options) => {
|
123
|
-
entry.value = entry.value.toString();
|
124
|
-
return contentRenderers.String.render(id, entry, options);
|
125
|
-
},
|
126
|
-
},
|
127
|
-
Number: {
|
128
|
-
bucket: Buckets.intermediate,
|
129
|
-
canRender: (entry) => {
|
130
|
-
return typeof entry.value === "number";
|
131
|
-
},
|
132
|
-
render: (id, entry, options) => {
|
133
|
-
entry.value = formatNumber(entry.value);
|
134
|
-
return contentRenderers.String.render(id, entry, options);
|
135
|
-
},
|
136
|
-
},
|
137
|
-
String: {
|
138
|
-
bucket: Buckets.final,
|
139
|
-
canRender: (entry) => {
|
140
|
-
return typeof entry.value === "string";
|
73
|
+
const contentRenderers: (
|
74
|
+
renderObject?: (object: any) => ReactNode,
|
75
|
+
) => Record<string, ContentRenderer> = (renderObject) => {
|
76
|
+
const contentRenderers: Record<string, ContentRenderer> = {
|
77
|
+
AnsiString: {
|
78
|
+
bucket: Buckets.first,
|
79
|
+
canRender: (entry) => {
|
80
|
+
return (
|
81
|
+
typeof entry.value === "string" && entry.value.indexOf("\u001b") > -1
|
82
|
+
);
|
83
|
+
},
|
84
|
+
render: (_id, entry, _options) => {
|
85
|
+
return {
|
86
|
+
rendered: <ANSIDisplay output={entry.value} />,
|
87
|
+
};
|
88
|
+
},
|
141
89
|
},
|
142
|
-
|
143
|
-
|
144
|
-
|
90
|
+
JsonString: {
|
91
|
+
bucket: Buckets.first,
|
92
|
+
canRender: (entry) => {
|
93
|
+
if (typeof entry.value === "string") {
|
94
|
+
const trimmed = entry.value.trim();
|
95
|
+
return isJson(trimmed);
|
96
|
+
}
|
97
|
+
return false;
|
98
|
+
},
|
99
|
+
render: (_id, entry, _options) => {
|
100
|
+
const obj = JSON5.parse(entry.value);
|
145
101
|
return {
|
146
|
-
rendered: <
|
102
|
+
rendered: <JSONPanel data={obj as Record<string, unknown>} />,
|
147
103
|
};
|
148
|
-
}
|
104
|
+
},
|
105
|
+
},
|
106
|
+
|
107
|
+
Model: {
|
108
|
+
bucket: Buckets.intermediate,
|
109
|
+
canRender: (entry) => {
|
110
|
+
return typeof entry.value === "object" && entry.value._model;
|
111
|
+
},
|
112
|
+
render: (_id, entry, _options) => {
|
149
113
|
return {
|
150
114
|
rendered: (
|
151
|
-
<
|
152
|
-
{
|
153
|
-
</
|
115
|
+
<Fragment>
|
116
|
+
<i className={ApplicationIcons.model} /> {entry.value._model}
|
117
|
+
</Fragment>
|
154
118
|
),
|
155
119
|
};
|
156
|
-
}
|
120
|
+
},
|
157
121
|
},
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
const types = new Set(
|
168
|
-
entry.value
|
169
|
-
.filter((e: unknown) => e !== null)
|
170
|
-
.map((e: unknown) => {
|
171
|
-
return typeof e;
|
172
|
-
}),
|
173
|
-
);
|
174
|
-
return types.size === 1;
|
175
|
-
} else {
|
176
|
-
return false;
|
177
|
-
}
|
122
|
+
Boolean: {
|
123
|
+
bucket: Buckets.intermediate,
|
124
|
+
canRender: (entry) => {
|
125
|
+
return typeof entry.value === "boolean";
|
126
|
+
},
|
127
|
+
render: (id, entry, options) => {
|
128
|
+
entry.value = entry.value.toString();
|
129
|
+
return contentRenderers.String.render(id, entry, options);
|
130
|
+
},
|
178
131
|
},
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
}
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
className={"font-size-small"}
|
189
|
-
entries={arrayMap}
|
190
|
-
tableOptions="borderless,sm"
|
191
|
-
compact={true}
|
192
|
-
/>
|
193
|
-
);
|
194
|
-
return { rendered: arrayRendered };
|
132
|
+
Number: {
|
133
|
+
bucket: Buckets.intermediate,
|
134
|
+
canRender: (entry) => {
|
135
|
+
return typeof entry.value === "number";
|
136
|
+
},
|
137
|
+
render: (id, entry, options) => {
|
138
|
+
entry.value = formatNumber(entry.value);
|
139
|
+
return contentRenderers.String.render(id, entry, options);
|
140
|
+
},
|
195
141
|
},
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
142
|
+
String: {
|
143
|
+
bucket: Buckets.final,
|
144
|
+
canRender: (entry) => {
|
145
|
+
return typeof entry.value === "string";
|
146
|
+
},
|
147
|
+
render: (_id, entry, options) => {
|
148
|
+
const rendered = entry.value.trim();
|
149
|
+
if (options.renderString === "markdown") {
|
150
|
+
return {
|
151
|
+
rendered: <MarkdownDiv markdown={rendered} />,
|
152
|
+
};
|
153
|
+
} else {
|
154
|
+
return {
|
155
|
+
rendered: (
|
156
|
+
<pre className={clsx(styles.preWrap, styles.preCompact)}>
|
157
|
+
{rendered}
|
158
|
+
</pre>
|
159
|
+
),
|
160
|
+
};
|
161
|
+
}
|
162
|
+
},
|
202
163
|
},
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
164
|
+
Array: {
|
165
|
+
bucket: Buckets.intermediate,
|
166
|
+
canRender: (entry) => {
|
167
|
+
const isArray = Array.isArray(entry.value);
|
168
|
+
if (isArray) {
|
169
|
+
if (entry.value.length === 0 || entry.value.length === 1) {
|
170
|
+
return true;
|
171
|
+
}
|
172
|
+
const types = new Set(
|
173
|
+
entry.value
|
174
|
+
.filter((e: unknown) => e !== null)
|
175
|
+
.map((e: unknown) => {
|
176
|
+
return typeof e;
|
177
|
+
}),
|
216
178
|
);
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
},
|
242
|
-
Html: {
|
243
|
-
bucket: Buckets.intermediate,
|
244
|
-
canRender: (entry) => {
|
245
|
-
return typeof entry.value === "object" && entry.value._html;
|
179
|
+
return types.size === 1;
|
180
|
+
} else {
|
181
|
+
return false;
|
182
|
+
}
|
183
|
+
},
|
184
|
+
render: (id, entry, _options) => {
|
185
|
+
const arrayMap: Record<string, unknown> = {};
|
186
|
+
entry.value.forEach((e: unknown, index: number) => {
|
187
|
+
arrayMap[`[${index}]`] = e;
|
188
|
+
});
|
189
|
+
|
190
|
+
const arrayRendered = renderObject ? (
|
191
|
+
renderObject(arrayMap)
|
192
|
+
) : (
|
193
|
+
<MetaDataView
|
194
|
+
id={id}
|
195
|
+
className={"font-size-small"}
|
196
|
+
entries={arrayMap}
|
197
|
+
tableOptions="borderless,sm"
|
198
|
+
compact={true}
|
199
|
+
/>
|
200
|
+
);
|
201
|
+
return { rendered: arrayRendered };
|
202
|
+
},
|
246
203
|
},
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
204
|
+
ChatMessage: ChatMessageRenderer,
|
205
|
+
web_search: {
|
206
|
+
bucket: Buckets.intermediate,
|
207
|
+
canRender: (entry) => {
|
208
|
+
return typeof entry.value === "object" && entry.name === "web_search";
|
209
|
+
},
|
210
|
+
render: (_id, entry, _options) => {
|
211
|
+
const results: ReactNode[] = [];
|
212
|
+
results.push(
|
213
|
+
<div className={styles.query}>
|
214
|
+
<i className={ApplicationIcons.search}></i> {entry.value.query}
|
215
|
+
</div>,
|
216
|
+
);
|
217
|
+
entry.value.results.forEach(
|
218
|
+
(result: { url: string; summary: string }) => {
|
219
|
+
results.push(
|
220
|
+
<div>
|
221
|
+
<a href={result.url}>{result.url}</a>
|
222
|
+
</div>,
|
223
|
+
);
|
224
|
+
results.push(
|
225
|
+
<div className={clsx("text-size-smaller", styles.summary)}>
|
226
|
+
{result.summary}
|
227
|
+
</div>,
|
228
|
+
);
|
229
|
+
},
|
230
|
+
);
|
231
|
+
return {
|
232
|
+
rendered: results,
|
233
|
+
};
|
234
|
+
},
|
251
235
|
},
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
236
|
+
web_browser: {
|
237
|
+
bucket: Buckets.intermediate,
|
238
|
+
canRender: (entry) => {
|
239
|
+
return (
|
240
|
+
typeof entry.value === "string" &&
|
241
|
+
entry.name?.startsWith("web_browser")
|
242
|
+
);
|
243
|
+
},
|
244
|
+
render: (_id, entry, _options) => {
|
245
|
+
return {
|
246
|
+
rendered: <pre className={styles.preWrap}>{entry.value}</pre>,
|
247
|
+
};
|
248
|
+
},
|
259
249
|
},
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
250
|
+
Html: {
|
251
|
+
bucket: Buckets.intermediate,
|
252
|
+
canRender: (entry) => {
|
253
|
+
return typeof entry.value === "object" && entry.value._html;
|
254
|
+
},
|
255
|
+
render: (_id, entry, _options) => {
|
256
|
+
return {
|
257
|
+
rendered: entry.value._html,
|
258
|
+
};
|
259
|
+
},
|
264
260
|
},
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
261
|
+
Image: {
|
262
|
+
bucket: Buckets.intermediate,
|
263
|
+
canRender: (entry) => {
|
264
|
+
return (
|
265
|
+
typeof entry.value === "string" &&
|
266
|
+
entry.value.startsWith("data:image/")
|
267
|
+
);
|
268
|
+
},
|
269
|
+
render: (_id, entry, _options) => {
|
270
|
+
return {
|
271
|
+
rendered: <img src={entry.value} />,
|
272
|
+
};
|
273
|
+
},
|
270
274
|
},
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
275
|
+
Object: {
|
276
|
+
bucket: Buckets.intermediate,
|
277
|
+
canRender: (entry) => {
|
278
|
+
return typeof entry.value === "object";
|
279
|
+
},
|
280
|
+
render: (id, entry, _options) => {
|
281
|
+
if (renderObject) {
|
282
|
+
return { rendered: renderObject(entry.value) };
|
283
|
+
} else {
|
284
|
+
return {
|
285
|
+
rendered: (
|
286
|
+
<MetaDataView
|
287
|
+
id={id}
|
288
|
+
className={"text-size-smaller"}
|
289
|
+
entries={entry.value}
|
290
|
+
tableOptions="borderless,sm"
|
291
|
+
compact
|
292
|
+
/>
|
293
|
+
),
|
294
|
+
};
|
295
|
+
}
|
296
|
+
},
|
283
297
|
},
|
284
|
-
}
|
298
|
+
};
|
299
|
+
return contentRenderers;
|
285
300
|
};
|
@@ -21,6 +21,7 @@ export const LogViewContainer: FC = () => {
|
|
21
21
|
epoch?: string;
|
22
22
|
sampleTabId?: string;
|
23
23
|
}>();
|
24
|
+
|
24
25
|
const initialState = useStore((state) => state.app.initialState);
|
25
26
|
const clearInitialState = useStore(
|
26
27
|
(state) => state.appActions.clearInitialState,
|
@@ -80,7 +81,7 @@ export const LogViewContainer: FC = () => {
|
|
80
81
|
}
|
81
82
|
|
82
83
|
// Reset the sample
|
83
|
-
if (logPath !== prevLogPath) {
|
84
|
+
if (prevLogPath && logPath !== prevLogPath) {
|
84
85
|
clearSelectedSample();
|
85
86
|
|
86
87
|
clearSelectedLogSummary();
|
@@ -105,6 +105,7 @@ export const SamplesTab: FC<SamplesTabProps> = ({ running }) => {
|
|
105
105
|
const groupBy = useGroupBy();
|
106
106
|
const groupByOrder = useGroupByOrder();
|
107
107
|
const currentScore = useScore();
|
108
|
+
const selectSample = useStore((state) => state.logActions.selectSample);
|
108
109
|
|
109
110
|
const selectedSampleIdentifier = useStore(
|
110
111
|
(state) => state.sample.sample_identifier,
|
@@ -186,6 +187,10 @@ export const SamplesTab: FC<SamplesTabProps> = ({ running }) => {
|
|
186
187
|
})
|
187
188
|
: [],
|
188
189
|
);
|
190
|
+
|
191
|
+
if (sampleSummaries.length === 1) {
|
192
|
+
selectSample(0);
|
193
|
+
}
|
189
194
|
}, [sampleSummaries, sampleProcessor]);
|
190
195
|
|
191
196
|
const title =
|
@@ -47,7 +47,7 @@ const noGrouping = (
|
|
47
47
|
const itemCount = counter.item();
|
48
48
|
return [
|
49
49
|
{
|
50
|
-
label: `Sample ${
|
50
|
+
label: `Sample ${sample.id}`,
|
51
51
|
number: itemCount,
|
52
52
|
index: index,
|
53
53
|
data: sample,
|
@@ -107,10 +107,10 @@ const groupBySample = (
|
|
107
107
|
if (sample.id !== lastId) {
|
108
108
|
counter.incrementGroup();
|
109
109
|
results.push({
|
110
|
-
label: `Sample ${
|
110
|
+
label: `Sample ${sample.id}`,
|
111
111
|
number: counter.group(),
|
112
112
|
index: index,
|
113
|
-
data: `Sample ${
|
113
|
+
data: `Sample ${sample.id}`,
|
114
114
|
type: "separator",
|
115
115
|
} as SeparatorListItem);
|
116
116
|
counter.resetItem();
|
@@ -175,7 +175,7 @@ const groupByEpoch = (
|
|
175
175
|
// Compute the index within the epoch
|
176
176
|
counter.incrementItem();
|
177
177
|
results.push({
|
178
|
-
label: `Sample ${
|
178
|
+
label: `Sample ${sample.id} (Epoch ${sample.epoch})`,
|
179
179
|
number: counter.item(),
|
180
180
|
index: index,
|
181
181
|
data: sample,
|
@@ -130,29 +130,26 @@ export const useSampleNavigation = () => {
|
|
130
130
|
|
131
131
|
// Navigate to a specific sample with index
|
132
132
|
const showSample = useCallback(
|
133
|
-
(
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
// Navigate to the sample URL
|
154
|
-
navigate(url);
|
155
|
-
}
|
133
|
+
(
|
134
|
+
index: number,
|
135
|
+
id: string | number,
|
136
|
+
epoch: number,
|
137
|
+
specifiedSampleTabId?: string,
|
138
|
+
) => {
|
139
|
+
const resolvedPath = resolveLogPath();
|
140
|
+
|
141
|
+
if (resolvedPath) {
|
142
|
+
// Update internal state
|
143
|
+
selectSample(index);
|
144
|
+
setShowingSampleDialog(true);
|
145
|
+
|
146
|
+
// Use specified sampleTabId if provided, otherwise use current sampleTabId from URL params
|
147
|
+
const currentSampleTabId = specifiedSampleTabId || sampleTabId;
|
148
|
+
|
149
|
+
const url = sampleUrl(resolvedPath, id, epoch, currentSampleTabId);
|
150
|
+
|
151
|
+
// Navigate to the sample URL
|
152
|
+
navigate(url);
|
156
153
|
}
|
157
154
|
},
|
158
155
|
[
|
@@ -171,7 +168,7 @@ export const useSampleNavigation = () => {
|
|
171
168
|
const itemsCount = sampleSummaries.length;
|
172
169
|
const next = Math.min(selectedSampleIndex + 1, itemsCount - 1);
|
173
170
|
if (next > -1) {
|
174
|
-
|
171
|
+
selectSample(next);
|
175
172
|
}
|
176
173
|
}, [selectedSampleIndex, showSample, sampleTabId]);
|
177
174
|
|
@@ -179,7 +176,7 @@ export const useSampleNavigation = () => {
|
|
179
176
|
const previousSample = useCallback(() => {
|
180
177
|
const prev = selectedSampleIndex - 1;
|
181
178
|
if (prev > -1) {
|
182
|
-
|
179
|
+
selectSample(prev);
|
183
180
|
}
|
184
181
|
}, [selectedSampleIndex, showSample, sampleTabId]);
|
185
182
|
|