inspect-ai 0.3.94__py3-none-any.whl → 0.3.95__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/loader.py +1 -1
- inspect_ai/_eval/task/run.py +12 -6
- inspect_ai/_util/exception.py +4 -0
- inspect_ai/_util/hash.py +39 -0
- inspect_ai/_util/path.py +22 -0
- inspect_ai/_util/trace.py +1 -1
- inspect_ai/_util/working.py +4 -0
- inspect_ai/_view/www/dist/assets/index.css +9 -9
- inspect_ai/_view/www/dist/assets/index.js +117 -120
- inspect_ai/_view/www/package.json +1 -1
- inspect_ai/_view/www/src/app/log-view/navbar/SecondaryBar.tsx +2 -2
- inspect_ai/_view/www/src/app/log-view/tabs/SamplesTab.tsx +1 -4
- inspect_ai/_view/www/src/app/samples/SamplesTools.tsx +3 -13
- inspect_ai/_view/www/src/app/samples/sample-tools/SelectScorer.tsx +45 -48
- inspect_ai/_view/www/src/app/samples/sample-tools/filters.ts +16 -15
- inspect_ai/_view/www/src/app/samples/sample-tools/sample-filter/SampleFilter.tsx +47 -75
- inspect_ai/_view/www/src/app/samples/sample-tools/sample-filter/completions.ts +9 -9
- inspect_ai/_view/www/src/app/types.ts +12 -2
- inspect_ai/_view/www/src/components/ExpandablePanel.module.css +1 -1
- inspect_ai/_view/www/src/components/ExpandablePanel.tsx +5 -5
- inspect_ai/_view/www/src/state/hooks.ts +19 -3
- inspect_ai/_view/www/src/state/logSlice.ts +23 -5
- inspect_ai/_view/www/yarn.lock +9 -9
- inspect_ai/agent/_bridge/patch.py +1 -3
- inspect_ai/analysis/__init__.py +0 -0
- inspect_ai/analysis/beta/__init__.py +57 -0
- inspect_ai/analysis/beta/_dataframe/__init__.py +0 -0
- inspect_ai/analysis/beta/_dataframe/columns.py +145 -0
- inspect_ai/analysis/beta/_dataframe/evals/__init__.py +0 -0
- inspect_ai/analysis/beta/_dataframe/evals/columns.py +132 -0
- inspect_ai/analysis/beta/_dataframe/evals/extract.py +23 -0
- inspect_ai/analysis/beta/_dataframe/evals/table.py +140 -0
- inspect_ai/analysis/beta/_dataframe/events/__init__.py +0 -0
- inspect_ai/analysis/beta/_dataframe/events/columns.py +37 -0
- inspect_ai/analysis/beta/_dataframe/events/table.py +14 -0
- inspect_ai/analysis/beta/_dataframe/extract.py +54 -0
- inspect_ai/analysis/beta/_dataframe/messages/__init__.py +0 -0
- inspect_ai/analysis/beta/_dataframe/messages/columns.py +60 -0
- inspect_ai/analysis/beta/_dataframe/messages/extract.py +21 -0
- inspect_ai/analysis/beta/_dataframe/messages/table.py +87 -0
- inspect_ai/analysis/beta/_dataframe/record.py +377 -0
- inspect_ai/analysis/beta/_dataframe/samples/__init__.py +0 -0
- inspect_ai/analysis/beta/_dataframe/samples/columns.py +73 -0
- inspect_ai/analysis/beta/_dataframe/samples/extract.py +82 -0
- inspect_ai/analysis/beta/_dataframe/samples/table.py +329 -0
- inspect_ai/analysis/beta/_dataframe/util.py +157 -0
- inspect_ai/analysis/beta/_dataframe/validate.py +171 -0
- inspect_ai/log/_file.py +1 -1
- inspect_ai/log/_log.py +21 -1
- inspect_ai/model/_call_tools.py +2 -1
- inspect_ai/model/_model.py +6 -4
- inspect_ai/model/_openai_responses.py +17 -18
- inspect_ai/model/_providers/anthropic.py +30 -5
- inspect_ai/model/_providers/providers.py +1 -1
- inspect_ai/solver/_multiple_choice.py +4 -1
- inspect_ai/solver/_task_state.py +7 -3
- inspect_ai/tool/_mcp/_context.py +3 -5
- inspect_ai/tool/_mcp/server.py +1 -1
- inspect_ai/tool/_tools/_think.py +1 -1
- inspect_ai/tool/_tools/_web_search/__init__.py +3 -0
- inspect_ai/tool/_tools/{_web_search.py → _web_search/_google.py} +56 -103
- inspect_ai/tool/_tools/_web_search/_tavily.py +77 -0
- inspect_ai/tool/_tools/_web_search/_web_search.py +85 -0
- inspect_ai/util/_sandbox/events.py +3 -2
- {inspect_ai-0.3.94.dist-info → inspect_ai-0.3.95.dist-info}/METADATA +8 -1
- {inspect_ai-0.3.94.dist-info → inspect_ai-0.3.95.dist-info}/RECORD +70 -43
- {inspect_ai-0.3.94.dist-info → inspect_ai-0.3.95.dist-info}/WHEEL +1 -1
- {inspect_ai-0.3.94.dist-info → inspect_ai-0.3.95.dist-info}/entry_points.txt +0 -0
- {inspect_ai-0.3.94.dist-info → inspect_ai-0.3.95.dist-info}/licenses/LICENSE +0 -0
- {inspect_ai-0.3.94.dist-info → inspect_ai-0.3.95.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
import clsx from "clsx";
|
2
2
|
import { ScoreLabel } from "../../../app/types";
|
3
3
|
|
4
|
-
import { ChangeEvent, FC, useCallback } from "react";
|
4
|
+
import { ChangeEvent, FC, useCallback, useMemo } from "react";
|
5
5
|
import styles from "./SelectScorer.module.css";
|
6
6
|
|
7
7
|
interface SelectScorerProps {
|
@@ -15,23 +15,18 @@ export const SelectScorer: FC<SelectScorerProps> = ({
|
|
15
15
|
score,
|
16
16
|
setScore,
|
17
17
|
}) => {
|
18
|
-
const scorers =
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
(index: number) => {
|
31
|
-
setScore(scores[index]);
|
32
|
-
},
|
33
|
-
[setScore, scores],
|
34
|
-
);
|
18
|
+
const scorers = useMemo(() => {
|
19
|
+
return scores.reduce((accum, scorer) => {
|
20
|
+
if (
|
21
|
+
!accum.find((sc) => {
|
22
|
+
return scorer.scorer === sc.scorer;
|
23
|
+
})
|
24
|
+
) {
|
25
|
+
accum.push(scorer);
|
26
|
+
}
|
27
|
+
return accum;
|
28
|
+
}, [] as ScoreLabel[]);
|
29
|
+
}, [scores]);
|
35
30
|
|
36
31
|
if (scorers.length === 1) {
|
37
32
|
// There is only a single scorer in play, just show the list of available scores
|
@@ -50,8 +45,8 @@ export const SelectScorer: FC<SelectScorerProps> = ({
|
|
50
45
|
</span>
|
51
46
|
<ScoreSelector
|
52
47
|
scores={scores}
|
53
|
-
|
54
|
-
|
48
|
+
selectedScore={score}
|
49
|
+
setSelectedScore={setScore}
|
55
50
|
/>
|
56
51
|
</div>
|
57
52
|
);
|
@@ -79,15 +74,15 @@ export const SelectScorer: FC<SelectScorerProps> = ({
|
|
79
74
|
</span>
|
80
75
|
<ScorerSelector
|
81
76
|
scorers={scorers}
|
82
|
-
|
83
|
-
|
77
|
+
selectedScore={score}
|
78
|
+
setSelectedScore={setScore}
|
84
79
|
/>
|
85
80
|
{scorerScores.length > 1 ? (
|
86
81
|
<ScoreSelector
|
87
82
|
className={clsx(styles.secondSel)}
|
88
83
|
scores={scorerScores}
|
89
|
-
|
90
|
-
|
84
|
+
selectedScore={score}
|
85
|
+
setSelectedScore={setScore}
|
91
86
|
/>
|
92
87
|
) : undefined}
|
93
88
|
</div>
|
@@ -97,25 +92,33 @@ export const SelectScorer: FC<SelectScorerProps> = ({
|
|
97
92
|
|
98
93
|
interface ScoreSelectorProps {
|
99
94
|
scores: ScoreLabel[];
|
100
|
-
|
101
|
-
|
95
|
+
selectedScore?: ScoreLabel;
|
96
|
+
setSelectedScore: (score: ScoreLabel) => void;
|
102
97
|
className?: string | string[];
|
103
98
|
}
|
104
99
|
|
105
100
|
const ScoreSelector: FC<ScoreSelectorProps> = ({
|
106
101
|
scores,
|
107
|
-
|
108
|
-
|
102
|
+
selectedScore,
|
103
|
+
setSelectedScore,
|
109
104
|
className,
|
110
105
|
}) => {
|
111
106
|
const handleChange = useCallback(
|
112
107
|
(e: ChangeEvent<HTMLSelectElement>) => {
|
113
108
|
const sel = e.target as HTMLSelectElement;
|
114
|
-
|
109
|
+
setSelectedScore(scores[sel.selectedIndex]);
|
115
110
|
},
|
116
|
-
[
|
111
|
+
[setSelectedScore, scores],
|
117
112
|
);
|
118
113
|
|
114
|
+
const index = scores.findIndex((sc) => {
|
115
|
+
return (
|
116
|
+
selectedScore &&
|
117
|
+
sc.name === selectedScore.name &&
|
118
|
+
sc.scorer === selectedScore.scorer
|
119
|
+
);
|
120
|
+
});
|
121
|
+
|
119
122
|
return (
|
120
123
|
<select
|
121
124
|
className={clsx(
|
@@ -125,7 +128,7 @@ const ScoreSelector: FC<ScoreSelectorProps> = ({
|
|
125
128
|
className,
|
126
129
|
)}
|
127
130
|
aria-label=".select-scorer-label"
|
128
|
-
value={scores[
|
131
|
+
value={scores[index].name}
|
129
132
|
onChange={handleChange}
|
130
133
|
>
|
131
134
|
{scores.map((score) => {
|
@@ -141,28 +144,32 @@ const ScoreSelector: FC<ScoreSelectorProps> = ({
|
|
141
144
|
|
142
145
|
interface ScorerSelectorProps {
|
143
146
|
scorers: ScoreLabel[];
|
144
|
-
|
145
|
-
|
147
|
+
selectedScore?: ScoreLabel;
|
148
|
+
setSelectedScore: (score: ScoreLabel) => void;
|
146
149
|
}
|
147
150
|
|
148
151
|
const ScorerSelector: FC<ScorerSelectorProps> = ({
|
149
152
|
scorers,
|
150
|
-
|
151
|
-
|
153
|
+
selectedScore,
|
154
|
+
setSelectedScore,
|
152
155
|
}) => {
|
153
156
|
const handleChange = useCallback(
|
154
157
|
(e: ChangeEvent<HTMLSelectElement>) => {
|
155
158
|
const sel = e.target as HTMLSelectElement;
|
156
|
-
|
159
|
+
setSelectedScore(scorers[sel.selectedIndex]);
|
157
160
|
},
|
158
|
-
[
|
161
|
+
[setSelectedScore, scorers],
|
159
162
|
);
|
160
163
|
|
164
|
+
const index = scorers.findIndex((sc) => {
|
165
|
+
return selectedScore && sc.scorer === selectedScore.scorer;
|
166
|
+
});
|
167
|
+
|
161
168
|
return (
|
162
169
|
<select
|
163
170
|
className={clsx("form-select", "form-select-sm", "text-size-smaller")}
|
164
171
|
aria-label=".epoch-filter-label"
|
165
|
-
value={scorers[
|
172
|
+
value={scorers[index].scorer}
|
166
173
|
onChange={handleChange}
|
167
174
|
>
|
168
175
|
{scorers.map((scorer) => {
|
@@ -175,13 +182,3 @@ const ScorerSelector: FC<ScorerSelectorProps> = ({
|
|
175
182
|
</select>
|
176
183
|
);
|
177
184
|
};
|
178
|
-
|
179
|
-
const scoreIndex = (scores: ScoreLabel[], score?: ScoreLabel) =>
|
180
|
-
scores.findIndex((sc) => {
|
181
|
-
return score && sc.name === score.name && sc.scorer === score.scorer;
|
182
|
-
});
|
183
|
-
|
184
|
-
const scorerIndex = (scores: ScoreLabel[], score?: ScoreLabel) =>
|
185
|
-
scores.findIndex((sc) => {
|
186
|
-
return score && sc.scorer === score.scorer;
|
187
|
-
});
|
@@ -1,19 +1,12 @@
|
|
1
1
|
import { compileExpression } from "filtrex";
|
2
2
|
import { Scores1 } from "../../../@types/log";
|
3
|
-
import { ScoreLabel } from "../../../app/types";
|
3
|
+
import { FilterError, ScoreLabel } from "../../../app/types";
|
4
4
|
import { SampleSummary } from "../../../client/api/types";
|
5
5
|
import { kScoreTypeBoolean } from "../../../constants";
|
6
6
|
import { inputString } from "../../../utils/format";
|
7
7
|
import { EvalDescriptor, ScoreDescriptor } from "../descriptor/types";
|
8
8
|
|
9
|
-
export interface
|
10
|
-
from: number;
|
11
|
-
to: number;
|
12
|
-
message: string;
|
13
|
-
severity: "warning" | "error";
|
14
|
-
}
|
15
|
-
|
16
|
-
export interface ScoreFilterItem {
|
9
|
+
export interface SampleFilterItem {
|
17
10
|
shortName?: string;
|
18
11
|
qualifiedName?: string;
|
19
12
|
canonicalName: string;
|
@@ -120,10 +113,10 @@ const sampleVariables = (sample: SampleSummary): Record<string, unknown> => {
|
|
120
113
|
* Child metrics are accessed using dot notation (e.g. `scorer_name.score_name`) or
|
121
114
|
* directly by name when it is unique.
|
122
115
|
*/
|
123
|
-
export const
|
116
|
+
export const sampleFilterItems = (
|
124
117
|
evalDescriptor: EvalDescriptor,
|
125
|
-
):
|
126
|
-
const items:
|
118
|
+
): SampleFilterItem[] => {
|
119
|
+
const items: SampleFilterItem[] = [];
|
127
120
|
const bannedShortNames = bannedShortScoreNames(evalDescriptor.scores);
|
128
121
|
const valueToString = (value: unknown) =>
|
129
122
|
typeof value === "string" ? `"${value}"` : String(value);
|
@@ -296,8 +289,13 @@ export const filterSamples = (
|
|
296
289
|
evalDescriptor: EvalDescriptor,
|
297
290
|
samples: SampleSummary[],
|
298
291
|
filterValue: string,
|
299
|
-
): {
|
300
|
-
|
292
|
+
): {
|
293
|
+
result: SampleSummary[];
|
294
|
+
error: FilterError | undefined;
|
295
|
+
allErrors: boolean;
|
296
|
+
} => {
|
297
|
+
let error = undefined;
|
298
|
+
let errorCount = 0;
|
301
299
|
const result = samples.filter((sample) => {
|
302
300
|
if (filterValue) {
|
303
301
|
const { matches, error: sampleError } = filterExpression(
|
@@ -306,10 +304,13 @@ export const filterSamples = (
|
|
306
304
|
filterValue,
|
307
305
|
);
|
308
306
|
error ||= sampleError;
|
307
|
+
if (sampleError) {
|
308
|
+
errorCount++;
|
309
|
+
}
|
309
310
|
return matches;
|
310
311
|
} else {
|
311
312
|
return true;
|
312
313
|
}
|
313
314
|
});
|
314
|
-
return { result, error };
|
315
|
+
return { result, error, allErrors: errorCount === samples.length };
|
315
316
|
};
|
@@ -14,28 +14,18 @@ import {
|
|
14
14
|
import { tags } from "@lezer/highlight";
|
15
15
|
import clsx from "clsx";
|
16
16
|
import { EditorView, minimalSetup } from "codemirror";
|
17
|
-
import { FC, useEffect, useMemo, useRef
|
17
|
+
import { FC, useCallback, useEffect, useMemo, useRef } from "react";
|
18
18
|
|
19
|
-
import { ScoreFilter } from "../../../../app/types";
|
20
|
-
import { SampleSummary } from "../../../../client/api/types";
|
21
19
|
import { useEvalDescriptor } from "../../../../state/hooks";
|
22
|
-
import {
|
23
|
-
import {
|
20
|
+
import { useStore } from "../../../../state/store";
|
21
|
+
import { debounce } from "../../../../utils/sync";
|
22
|
+
import { FilterError } from "../../../types";
|
23
|
+
import { sampleFilterItems } from "../filters";
|
24
24
|
import { getCompletions } from "./completions";
|
25
25
|
import styles from "./SampleFilter.module.css";
|
26
26
|
import { language } from "./tokenize";
|
27
27
|
|
28
|
-
|
29
|
-
interface FilteringResult {
|
30
|
-
numSamples: number;
|
31
|
-
error?: FilterError;
|
32
|
-
}
|
33
|
-
|
34
|
-
interface SampleFilterProps {
|
35
|
-
samples: SampleSummary[];
|
36
|
-
scoreFilter: ScoreFilter;
|
37
|
-
setScoreFilter: (filter: ScoreFilter) => void;
|
38
|
-
}
|
28
|
+
interface SampleFilterProps {}
|
39
29
|
|
40
30
|
// Constants
|
41
31
|
const FILTER_TOOLTIP = `
|
@@ -105,20 +95,6 @@ const editorTheme = EditorView.theme({
|
|
105
95
|
},
|
106
96
|
});
|
107
97
|
|
108
|
-
// Helper functions
|
109
|
-
const getFilteringResult = (
|
110
|
-
evalDescriptor: EvalDescriptor,
|
111
|
-
sampleSummaries: SampleSummary[],
|
112
|
-
filterValue: string,
|
113
|
-
): FilteringResult => {
|
114
|
-
const { result, error } = filterSamples(
|
115
|
-
evalDescriptor,
|
116
|
-
sampleSummaries,
|
117
|
-
filterValue,
|
118
|
-
);
|
119
|
-
return { numSamples: result.length, error };
|
120
|
-
};
|
121
|
-
|
122
98
|
const ensureOneLine = (tr: Transaction): TransactionSpec => {
|
123
99
|
const newDoc = tr.newDoc.toString();
|
124
100
|
if (!newDoc.includes("\n")) return tr;
|
@@ -154,11 +130,7 @@ const getLints = (
|
|
154
130
|
};
|
155
131
|
|
156
132
|
// Main component
|
157
|
-
export const SampleFilter: FC<SampleFilterProps> = ({
|
158
|
-
samples,
|
159
|
-
scoreFilter,
|
160
|
-
setScoreFilter,
|
161
|
-
}) => {
|
133
|
+
export const SampleFilter: FC<SampleFilterProps> = () => {
|
162
134
|
const editorRef = useRef<HTMLDivElement>(null);
|
163
135
|
const editorViewRef = useRef<EditorView>(null);
|
164
136
|
const linterCompartment = useRef<Compartment>(new Compartment());
|
@@ -167,43 +139,51 @@ export const SampleFilter: FC<SampleFilterProps> = ({
|
|
167
139
|
const evalDescriptor = useEvalDescriptor();
|
168
140
|
|
169
141
|
const filterItems = useMemo(
|
170
|
-
() => (evalDescriptor ?
|
142
|
+
() => (evalDescriptor ? sampleFilterItems(evalDescriptor) : []),
|
171
143
|
[evalDescriptor],
|
172
144
|
);
|
173
145
|
|
174
|
-
const
|
175
|
-
|
146
|
+
const filter = useStore((state) => state.log.filter);
|
147
|
+
const filterError = useStore((state) => state.log.filterError);
|
148
|
+
const setFilter = useStore((state) => state.logActions.setFilter);
|
176
149
|
|
177
|
-
const handleFocus = (event: FocusEvent, view: EditorView) => {
|
150
|
+
const handleFocus = useCallback((event: FocusEvent, view: EditorView) => {
|
178
151
|
if (event.isTrusted && view.state.doc.toString() === "") {
|
179
152
|
setTimeout(() => startCompletion(view), 0);
|
180
153
|
}
|
181
|
-
};
|
154
|
+
}, []);
|
182
155
|
|
183
|
-
const makeAutocompletion = (
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
156
|
+
const makeAutocompletion = useCallback(
|
157
|
+
() =>
|
158
|
+
autocompletion({
|
159
|
+
override: [(context) => getCompletions(context, filterItems)],
|
160
|
+
activateOnCompletion: (c) => c.label.endsWith(" "),
|
161
|
+
}),
|
162
|
+
[],
|
163
|
+
);
|
188
164
|
|
189
|
-
const makeLinter = (
|
190
|
-
linter((view) => getLints(view,
|
165
|
+
const makeLinter = useCallback(
|
166
|
+
() => linter((view) => getLints(view, filterError)),
|
167
|
+
[filterError],
|
168
|
+
);
|
191
169
|
|
192
|
-
const
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
170
|
+
const debounceSetFilter = useCallback(
|
171
|
+
debounce((value: string) => {
|
172
|
+
setFilter(value);
|
173
|
+
}, 200),
|
174
|
+
[setFilter],
|
175
|
+
);
|
176
|
+
|
177
|
+
const makeUpdateListener = useCallback(
|
178
|
+
() =>
|
179
|
+
EditorView.updateListener.of((update) => {
|
180
|
+
if (update.docChanged && evalDescriptor) {
|
181
|
+
const newValue = update.state.doc.toString();
|
182
|
+
debounceSetFilter(newValue);
|
203
183
|
}
|
204
|
-
|
205
|
-
|
206
|
-
|
184
|
+
}),
|
185
|
+
[setFilter],
|
186
|
+
);
|
207
187
|
|
208
188
|
// Initialize editor
|
209
189
|
useEffect(() => {
|
@@ -212,7 +192,7 @@ export const SampleFilter: FC<SampleFilterProps> = ({
|
|
212
192
|
editorViewRef.current = new EditorView({
|
213
193
|
parent: editorRef.current ?? undefined,
|
214
194
|
state: EditorState.create({
|
215
|
-
doc:
|
195
|
+
doc: filter || "",
|
216
196
|
extensions: [
|
217
197
|
minimalSetup,
|
218
198
|
bracketMatching(),
|
@@ -236,21 +216,16 @@ export const SampleFilter: FC<SampleFilterProps> = ({
|
|
236
216
|
if (!editorViewRef.current) return;
|
237
217
|
|
238
218
|
const currentValue = editorViewRef.current.state.doc.toString();
|
239
|
-
if (
|
219
|
+
if (filter === currentValue) return;
|
240
220
|
|
241
|
-
if (evalDescriptor) {
|
242
|
-
setFilteringResultInstant(
|
243
|
-
getFilteringResult(evalDescriptor, samples, scoreFilter.value || ""),
|
244
|
-
);
|
245
|
-
}
|
246
221
|
editorViewRef.current.dispatch({
|
247
222
|
changes: {
|
248
223
|
from: 0,
|
249
224
|
to: currentValue.length,
|
250
|
-
insert:
|
225
|
+
insert: filter || "",
|
251
226
|
},
|
252
227
|
});
|
253
|
-
}, [
|
228
|
+
}, [filter]);
|
254
229
|
|
255
230
|
// Update compartments when dependencies change
|
256
231
|
useEffect(() => {
|
@@ -271,7 +246,7 @@ export const SampleFilter: FC<SampleFilterProps> = ({
|
|
271
246
|
editorViewRef.current?.dispatch({
|
272
247
|
effects: linterCompartment.current.reconfigure(makeLinter()),
|
273
248
|
});
|
274
|
-
}, [
|
249
|
+
}, [filterError]);
|
275
250
|
|
276
251
|
return (
|
277
252
|
<div style={{ display: "flex" }}>
|
@@ -288,10 +263,7 @@ export const SampleFilter: FC<SampleFilterProps> = ({
|
|
288
263
|
</span>
|
289
264
|
<div
|
290
265
|
ref={editorRef}
|
291
|
-
className={clsx(
|
292
|
-
filteringResultInstant?.error && "filter-pending",
|
293
|
-
styles.input,
|
294
|
-
)}
|
266
|
+
className={clsx(filterError && "filter-pending", styles.input)}
|
295
267
|
/>
|
296
268
|
<span
|
297
269
|
className={clsx("bi", "bi-question-circle", styles.help)}
|
@@ -12,7 +12,7 @@ import {
|
|
12
12
|
kScoreTypeOther,
|
13
13
|
kScoreTypePassFail,
|
14
14
|
} from "../../../../constants";
|
15
|
-
import {
|
15
|
+
import { SampleFilterItem } from "../filters";
|
16
16
|
import {
|
17
17
|
KEYWORDS,
|
18
18
|
MATH_FUNCTIONS,
|
@@ -29,7 +29,7 @@ interface CompletionOptions {
|
|
29
29
|
}
|
30
30
|
|
31
31
|
interface CanonicalNameCompletionProps {
|
32
|
-
autoSpaceIf?: (item:
|
32
|
+
autoSpaceIf?: (item: SampleFilterItem) => boolean;
|
33
33
|
}
|
34
34
|
|
35
35
|
const isLiteral = (token: Token): boolean =>
|
@@ -98,7 +98,7 @@ const makeLiteralCompletion = (k: string): Completion => ({
|
|
98
98
|
});
|
99
99
|
|
100
100
|
const makeCanonicalNameCompletion = (
|
101
|
-
item:
|
101
|
+
item: SampleFilterItem,
|
102
102
|
{ autoSpaceIf = () => false }: CanonicalNameCompletionProps = {},
|
103
103
|
): Completion => ({
|
104
104
|
label: item.canonicalName + (autoSpaceIf(item) ? " " : ""),
|
@@ -107,7 +107,7 @@ const makeCanonicalNameCompletion = (
|
|
107
107
|
boost: 30,
|
108
108
|
});
|
109
109
|
|
110
|
-
const makeMemberAccessCompletion = (item:
|
110
|
+
const makeMemberAccessCompletion = (item: SampleFilterItem): Completion => ({
|
111
111
|
label: item.qualifiedName?.split(".")[1] || "",
|
112
112
|
type: "variable",
|
113
113
|
info: item.tooltip,
|
@@ -115,9 +115,9 @@ const makeMemberAccessCompletion = (item: ScoreFilterItem): Completion => ({
|
|
115
115
|
});
|
116
116
|
|
117
117
|
const getMemberScoreItems = (
|
118
|
-
filterItems:
|
118
|
+
filterItems: SampleFilterItem[],
|
119
119
|
scorer: string,
|
120
|
-
):
|
120
|
+
): SampleFilterItem[] =>
|
121
121
|
filterItems.filter((item) => item?.qualifiedName?.startsWith(`${scorer}.`));
|
122
122
|
|
123
123
|
/**
|
@@ -136,7 +136,7 @@ const getMemberScoreItems = (
|
|
136
136
|
*/
|
137
137
|
export function getCompletions(
|
138
138
|
context: CompletionContext,
|
139
|
-
filterItems:
|
139
|
+
filterItems: SampleFilterItem[],
|
140
140
|
): CompletionResult | null {
|
141
141
|
const keywordCompletionItems = KEYWORDS.map(makeKeywordCompletion);
|
142
142
|
const mathFunctionCompletionItems = MATH_FUNCTIONS.map(
|
@@ -177,7 +177,7 @@ export function getCompletions(
|
|
177
177
|
const completionStart = currentToken ? currentToken.from : context.pos;
|
178
178
|
const completingAtEnd = context.pos === doc.length;
|
179
179
|
|
180
|
-
const findFilterItem = (endIndex: number):
|
180
|
+
const findFilterItem = (endIndex: number): SampleFilterItem | undefined => {
|
181
181
|
if (prevToken(endIndex)?.type !== "variable") return undefined;
|
182
182
|
|
183
183
|
let name = prevToken(endIndex).text;
|
@@ -267,7 +267,7 @@ export function getCompletions(
|
|
267
267
|
|
268
268
|
const variableCompletions = () => makeCompletions(variableCompletionItems);
|
269
269
|
|
270
|
-
const memberAccessCompletions = (items:
|
270
|
+
const memberAccessCompletions = (items: SampleFilterItem[]) =>
|
271
271
|
makeCompletions(items.map(makeMemberAccessCompletion), {
|
272
272
|
autocompleteInTheMiddle: true,
|
273
273
|
includeDefault: false,
|
@@ -67,7 +67,9 @@ export interface LogState {
|
|
67
67
|
selectedLogSummary?: EvalSummary;
|
68
68
|
pendingSampleSummaries?: PendingSamples;
|
69
69
|
|
70
|
-
filter:
|
70
|
+
filter: string;
|
71
|
+
filterError?: FilterError;
|
72
|
+
|
71
73
|
epoch: string;
|
72
74
|
sort: string;
|
73
75
|
score?: ScoreLabel;
|
@@ -122,8 +124,16 @@ export interface ScoreLabel {
|
|
122
124
|
scorer: string;
|
123
125
|
}
|
124
126
|
|
125
|
-
export interface
|
127
|
+
export interface SampleFilter {
|
126
128
|
value?: string;
|
129
|
+
error?: FilterError;
|
130
|
+
}
|
131
|
+
|
132
|
+
export interface FilterError {
|
133
|
+
from: number;
|
134
|
+
to: number;
|
135
|
+
message: string;
|
136
|
+
severity: "warning" | "error";
|
127
137
|
}
|
128
138
|
|
129
139
|
export type SampleMode = "none" | "single" | "many";
|
@@ -27,19 +27,19 @@ export const ExpandablePanel: FC<ExpandablePanelProps> = memo(
|
|
27
27
|
const [collapsed, setCollapsed] = useCollapsedState(id, collapse);
|
28
28
|
|
29
29
|
const [showToggle, setShowToggle] = useState(false);
|
30
|
-
const
|
30
|
+
const baseFontSizeRef = useRef<number>(0);
|
31
31
|
|
32
32
|
const checkOverflow = useCallback(
|
33
33
|
(entry: ResizeObserverEntry) => {
|
34
34
|
const element = entry.target as HTMLDivElement;
|
35
35
|
|
36
36
|
// Calculate line height if we haven't yet
|
37
|
-
if (
|
37
|
+
if (baseFontSizeRef.current === 0) {
|
38
38
|
const computedStyle = window.getComputedStyle(element);
|
39
|
-
|
39
|
+
const rootFontSize = parseFloat(computedStyle.fontSize);
|
40
|
+
baseFontSizeRef.current = rootFontSize;
|
40
41
|
}
|
41
|
-
|
42
|
-
const maxCollapsedHeight = lines * lineHeightRef.current;
|
42
|
+
const maxCollapsedHeight = baseFontSizeRef.current * lines;
|
43
43
|
const contentHeight = element.scrollHeight;
|
44
44
|
|
45
45
|
setShowToggle(contentHeight > maxCollapsedHeight);
|
@@ -132,6 +132,11 @@ export const useFilteredSamples = () => {
|
|
132
132
|
const evalDescriptor = useEvalDescriptor();
|
133
133
|
const sampleSummaries = useSampleSummaries();
|
134
134
|
const filter = useStore((state) => state.log.filter);
|
135
|
+
const setFilterError = useStore((state) => state.logActions.setFilterError);
|
136
|
+
const clearFilterError = useStore(
|
137
|
+
(state) => state.logActions.clearFilterError,
|
138
|
+
);
|
139
|
+
|
135
140
|
const epoch = useStore((state) => state.log.epoch);
|
136
141
|
const sort = useStore((state) => state.log.sort);
|
137
142
|
const samplesDescriptor = useSampleDescriptor();
|
@@ -139,10 +144,19 @@ export const useFilteredSamples = () => {
|
|
139
144
|
|
140
145
|
return useMemo(() => {
|
141
146
|
// Apply filters
|
147
|
+
const { result, error, allErrors } =
|
148
|
+
evalDescriptor && filter
|
149
|
+
? filterSamples(evalDescriptor, sampleSummaries, filter)
|
150
|
+
: { result: sampleSummaries, error: undefined, allErrors: false };
|
151
|
+
|
152
|
+
if (error && allErrors) {
|
153
|
+
setFilterError(error);
|
154
|
+
} else {
|
155
|
+
clearFilterError();
|
156
|
+
}
|
157
|
+
|
142
158
|
const prefiltered =
|
143
|
-
|
144
|
-
? filterSamples(evalDescriptor, sampleSummaries, filter.value).result
|
145
|
-
: sampleSummaries;
|
159
|
+
error === undefined || !allErrors ? result : sampleSummaries;
|
146
160
|
|
147
161
|
// Filter epochs
|
148
162
|
const filtered =
|
@@ -160,6 +174,8 @@ export const useFilteredSamples = () => {
|
|
160
174
|
evalDescriptor,
|
161
175
|
sampleSummaries,
|
162
176
|
filter,
|
177
|
+
setFilterError,
|
178
|
+
clearFilterError,
|
163
179
|
epoch,
|
164
180
|
sort,
|
165
181
|
samplesDescriptor,
|