inspect-ai 0.3.69__py3-none-any.whl → 0.3.71__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 +27 -9
- inspect_ai/_display/core/display.py +2 -0
- inspect_ai/_display/core/footer.py +13 -3
- inspect_ai/_display/plain/display.py +6 -2
- inspect_ai/_display/rich/display.py +19 -6
- inspect_ai/_display/textual/app.py +9 -3
- inspect_ai/_display/textual/display.py +4 -0
- inspect_ai/_display/textual/widgets/samples.py +4 -10
- inspect_ai/_display/textual/widgets/transcript.py +35 -18
- inspect_ai/_eval/eval.py +14 -2
- inspect_ai/_eval/evalset.py +6 -1
- inspect_ai/_eval/run.py +6 -0
- inspect_ai/_eval/task/run.py +49 -23
- inspect_ai/_eval/task/task.py +26 -3
- inspect_ai/_util/content.py +20 -1
- inspect_ai/_util/interrupt.py +6 -0
- inspect_ai/_util/logger.py +19 -0
- inspect_ai/_util/rich.py +7 -8
- inspect_ai/_util/text.py +13 -0
- inspect_ai/_util/transcript.py +20 -6
- inspect_ai/_util/working.py +50 -0
- inspect_ai/_view/www/App.css +6 -0
- inspect_ai/_view/www/dist/assets/index.css +171 -99
- inspect_ai/_view/www/dist/assets/index.js +5972 -2770
- inspect_ai/_view/www/eslint.config.mjs +24 -1
- inspect_ai/_view/www/log-schema.json +619 -21
- inspect_ai/_view/www/package.json +8 -3
- inspect_ai/_view/www/src/App.tsx +2 -2
- inspect_ai/_view/www/src/appearance/icons.ts +3 -1
- inspect_ai/_view/www/src/components/AnsiDisplay.tsx +4 -3
- inspect_ai/_view/www/src/components/Card.tsx +9 -8
- inspect_ai/_view/www/src/components/DownloadButton.tsx +2 -1
- inspect_ai/_view/www/src/components/EmptyPanel.tsx +2 -2
- inspect_ai/_view/www/src/components/ErrorPanel.tsx +4 -3
- inspect_ai/_view/www/src/components/ExpandablePanel.tsx +13 -5
- inspect_ai/_view/www/src/components/FindBand.tsx +3 -3
- inspect_ai/_view/www/src/components/HumanBaselineView.tsx +3 -3
- inspect_ai/_view/www/src/components/LabeledValue.tsx +5 -4
- inspect_ai/_view/www/src/components/LargeModal.tsx +18 -13
- inspect_ai/_view/www/src/components/{LightboxCarousel.css → LightboxCarousel.module.css} +22 -18
- inspect_ai/_view/www/src/components/LightboxCarousel.tsx +36 -27
- inspect_ai/_view/www/src/components/MessageBand.tsx +2 -1
- inspect_ai/_view/www/src/components/NavPills.tsx +9 -8
- inspect_ai/_view/www/src/components/ProgressBar.tsx +2 -1
- inspect_ai/_view/www/src/components/TabSet.tsx +21 -15
- inspect_ai/_view/www/src/index.tsx +2 -2
- inspect_ai/_view/www/src/metadata/MetaDataGrid.tsx +11 -9
- inspect_ai/_view/www/src/metadata/MetaDataView.tsx +3 -2
- inspect_ai/_view/www/src/metadata/MetadataGrid.module.css +1 -0
- inspect_ai/_view/www/src/metadata/RenderedContent.tsx +16 -1
- inspect_ai/_view/www/src/plan/DatasetDetailView.tsx +3 -2
- inspect_ai/_view/www/src/plan/DetailStep.tsx +2 -1
- inspect_ai/_view/www/src/plan/PlanCard.tsx +2 -5
- inspect_ai/_view/www/src/plan/PlanDetailView.tsx +6 -9
- inspect_ai/_view/www/src/plan/ScorerDetailView.tsx +2 -1
- inspect_ai/_view/www/src/plan/SolverDetailView.tsx +3 -3
- inspect_ai/_view/www/src/samples/InlineSampleDisplay.tsx +2 -2
- inspect_ai/_view/www/src/samples/SampleDialog.tsx +3 -3
- inspect_ai/_view/www/src/samples/SampleDisplay.module.css +9 -1
- inspect_ai/_view/www/src/samples/SampleDisplay.tsx +30 -3
- inspect_ai/_view/www/src/samples/SampleSummaryView.module.css +4 -0
- inspect_ai/_view/www/src/samples/SampleSummaryView.tsx +25 -4
- inspect_ai/_view/www/src/samples/SamplesTools.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatMessage.tsx +3 -19
- inspect_ai/_view/www/src/samples/chat/ChatMessageRenderer.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatMessageRow.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatView.tsx +2 -1
- inspect_ai/_view/www/src/samples/chat/ChatViewVirtualList.tsx +22 -7
- inspect_ai/_view/www/src/samples/chat/MessageContent.tsx +35 -6
- inspect_ai/_view/www/src/samples/chat/MessageContents.tsx +2 -2
- inspect_ai/_view/www/src/samples/chat/messages.ts +15 -2
- inspect_ai/_view/www/src/samples/chat/tools/ToolCallView.tsx +13 -4
- inspect_ai/_view/www/src/samples/chat/tools/ToolInput.module.css +2 -2
- inspect_ai/_view/www/src/samples/chat/tools/ToolInput.tsx +18 -19
- inspect_ai/_view/www/src/samples/chat/tools/ToolOutput.module.css +1 -1
- inspect_ai/_view/www/src/samples/chat/tools/ToolOutput.tsx +4 -3
- inspect_ai/_view/www/src/samples/chat/tools/ToolTitle.tsx +2 -2
- inspect_ai/_view/www/src/samples/error/FlatSampleErrorView.tsx +2 -3
- inspect_ai/_view/www/src/samples/error/SampleErrorView.tsx +3 -2
- inspect_ai/_view/www/src/samples/list/SampleFooter.tsx +2 -1
- inspect_ai/_view/www/src/samples/list/SampleHeader.tsx +2 -1
- inspect_ai/_view/www/src/samples/list/SampleList.tsx +57 -45
- inspect_ai/_view/www/src/samples/list/SampleRow.tsx +2 -1
- inspect_ai/_view/www/src/samples/list/SampleSeparator.tsx +2 -1
- inspect_ai/_view/www/src/samples/sample-tools/EpochFilter.tsx +2 -2
- inspect_ai/_view/www/src/samples/sample-tools/SelectScorer.tsx +4 -3
- inspect_ai/_view/www/src/samples/sample-tools/SortFilter.tsx +2 -5
- inspect_ai/_view/www/src/samples/sample-tools/sample-filter/SampleFilter.tsx +2 -2
- inspect_ai/_view/www/src/samples/scores/SampleScoreView.tsx +2 -1
- inspect_ai/_view/www/src/samples/scores/SampleScores.tsx +2 -2
- inspect_ai/_view/www/src/samples/transcript/ApprovalEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/ErrorEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/InfoEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/InputEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/LoggerEventView.module.css +4 -0
- inspect_ai/_view/www/src/samples/transcript/LoggerEventView.tsx +12 -2
- inspect_ai/_view/www/src/samples/transcript/ModelEventView.module.css +1 -1
- inspect_ai/_view/www/src/samples/transcript/ModelEventView.tsx +25 -28
- inspect_ai/_view/www/src/samples/transcript/SampleInitEventView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/SampleLimitEventView.tsx +9 -4
- inspect_ai/_view/www/src/samples/transcript/SampleTranscript.tsx +2 -2
- inspect_ai/_view/www/src/samples/transcript/SandboxEventView.module.css +32 -0
- inspect_ai/_view/www/src/samples/transcript/SandboxEventView.tsx +153 -0
- inspect_ai/_view/www/src/samples/transcript/ScoreEventView.tsx +2 -2
- inspect_ai/_view/www/src/samples/transcript/StepEventView.tsx +12 -5
- inspect_ai/_view/www/src/samples/transcript/SubtaskEventView.tsx +18 -14
- inspect_ai/_view/www/src/samples/transcript/ToolEventView.tsx +5 -5
- inspect_ai/_view/www/src/samples/transcript/TranscriptView.tsx +53 -16
- inspect_ai/_view/www/src/samples/transcript/event/EventNav.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/event/EventNavs.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/event/EventPanel.tsx +6 -3
- inspect_ai/_view/www/src/samples/transcript/event/EventRow.tsx +3 -2
- inspect_ai/_view/www/src/samples/transcript/event/EventSection.tsx +2 -2
- inspect_ai/_view/www/src/samples/transcript/event/EventTimingPanel.module.css +28 -0
- inspect_ai/_view/www/src/samples/transcript/event/EventTimingPanel.tsx +115 -0
- inspect_ai/_view/www/src/samples/transcript/event/utils.ts +29 -0
- inspect_ai/_view/www/src/samples/transcript/state/StateDiffView.tsx +2 -1
- inspect_ai/_view/www/src/samples/transcript/state/StateEventRenderers.tsx +3 -3
- inspect_ai/_view/www/src/samples/transcript/state/StateEventView.tsx +11 -8
- inspect_ai/_view/www/src/samples/transcript/types.ts +3 -1
- inspect_ai/_view/www/src/types/log.d.ts +312 -137
- inspect_ai/_view/www/src/usage/ModelTokenTable.tsx +6 -10
- inspect_ai/_view/www/src/usage/ModelUsagePanel.module.css +4 -0
- inspect_ai/_view/www/src/usage/ModelUsagePanel.tsx +32 -9
- inspect_ai/_view/www/src/usage/TokenTable.tsx +4 -6
- inspect_ai/_view/www/src/usage/UsageCard.tsx +2 -1
- inspect_ai/_view/www/src/utils/format.ts +8 -5
- inspect_ai/_view/www/src/utils/json.ts +24 -0
- inspect_ai/_view/www/src/workspace/WorkSpace.tsx +6 -5
- inspect_ai/_view/www/src/workspace/WorkSpaceView.tsx +18 -8
- inspect_ai/_view/www/src/workspace/error/TaskErrorPanel.tsx +2 -1
- inspect_ai/_view/www/src/workspace/navbar/Navbar.tsx +2 -1
- inspect_ai/_view/www/src/workspace/navbar/PrimaryBar.tsx +3 -3
- inspect_ai/_view/www/src/workspace/navbar/ResultsPanel.tsx +4 -3
- inspect_ai/_view/www/src/workspace/navbar/SecondaryBar.tsx +5 -4
- inspect_ai/_view/www/src/workspace/navbar/StatusPanel.tsx +5 -8
- inspect_ai/_view/www/src/workspace/sidebar/EvalStatus.tsx +5 -4
- inspect_ai/_view/www/src/workspace/sidebar/LogDirectoryTitleView.tsx +2 -1
- inspect_ai/_view/www/src/workspace/sidebar/Sidebar.tsx +2 -1
- inspect_ai/_view/www/src/workspace/sidebar/SidebarLogEntry.tsx +2 -2
- inspect_ai/_view/www/src/workspace/sidebar/SidebarScoreView.tsx +2 -1
- inspect_ai/_view/www/src/workspace/sidebar/SidebarScoresView.tsx +2 -2
- inspect_ai/_view/www/src/workspace/tabs/InfoTab.tsx +2 -2
- inspect_ai/_view/www/src/workspace/tabs/JsonTab.tsx +2 -5
- inspect_ai/_view/www/src/workspace/tabs/SamplesTab.tsx +12 -11
- inspect_ai/_view/www/yarn.lock +241 -5
- inspect_ai/log/__init__.py +2 -0
- inspect_ai/log/_condense.py +4 -0
- inspect_ai/log/_log.py +72 -12
- inspect_ai/log/_recorders/eval.py +6 -1
- inspect_ai/log/_samples.py +5 -1
- inspect_ai/log/_transcript.py +89 -2
- inspect_ai/model/__init__.py +2 -0
- inspect_ai/model/_call_tools.py +8 -1
- inspect_ai/model/_chat_message.py +22 -7
- inspect_ai/model/_conversation.py +11 -9
- inspect_ai/model/_generate_config.py +25 -4
- inspect_ai/model/_model.py +164 -72
- inspect_ai/model/_model_call.py +10 -3
- inspect_ai/model/_model_output.py +3 -0
- inspect_ai/model/_openai.py +106 -40
- inspect_ai/model/_providers/anthropic.py +145 -26
- inspect_ai/model/_providers/bedrock.py +7 -0
- inspect_ai/model/_providers/cloudflare.py +20 -7
- inspect_ai/model/_providers/google.py +29 -8
- inspect_ai/model/_providers/groq.py +66 -27
- inspect_ai/model/_providers/hf.py +6 -0
- inspect_ai/model/_providers/mistral.py +78 -51
- inspect_ai/model/_providers/openai.py +66 -4
- inspect_ai/model/_providers/openai_o1.py +10 -0
- inspect_ai/model/_providers/providers.py +2 -2
- inspect_ai/model/_providers/util/tracker.py +92 -0
- inspect_ai/model/_providers/vllm.py +13 -5
- inspect_ai/model/_reasoning.py +15 -2
- inspect_ai/scorer/_model.py +23 -19
- inspect_ai/solver/_basic_agent.py +1 -3
- inspect_ai/solver/_bridge/patch.py +0 -2
- inspect_ai/solver/_human_agent/agent.py +14 -10
- inspect_ai/solver/_human_agent/commands/__init__.py +7 -3
- inspect_ai/solver/_human_agent/commands/submit.py +76 -30
- inspect_ai/solver/_limit.py +4 -4
- inspect_ai/solver/_plan.py +0 -3
- inspect_ai/solver/_task_state.py +7 -0
- inspect_ai/tool/__init__.py +2 -0
- inspect_ai/tool/_tool.py +3 -1
- inspect_ai/tool/_tools/_computer/_resources/tool/_run.py +1 -1
- inspect_ai/tool/_tools/_web_browser/_resources/.pylintrc +8 -0
- inspect_ai/tool/_tools/_web_browser/_resources/.vscode/launch.json +24 -0
- inspect_ai/tool/_tools/_web_browser/_resources/.vscode/settings.json +25 -0
- inspect_ai/tool/_tools/_web_browser/_resources/Dockerfile +5 -6
- inspect_ai/tool/_tools/_web_browser/_resources/README.md +10 -11
- inspect_ai/tool/_tools/_web_browser/_resources/accessibility_tree.py +71 -0
- inspect_ai/tool/_tools/_web_browser/_resources/accessibility_tree_node.py +323 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/__init__.py +5 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/a11y.py +279 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/dom.py +9 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/dom_snapshot.py +293 -0
- inspect_ai/tool/_tools/_web_browser/_resources/cdp/page.py +94 -0
- inspect_ai/tool/_tools/_web_browser/_resources/constants.py +2 -0
- inspect_ai/tool/_tools/_web_browser/_resources/images/usage_diagram.svg +2 -0
- inspect_ai/tool/_tools/_web_browser/_resources/playwright_browser.py +50 -0
- inspect_ai/tool/_tools/_web_browser/_resources/playwright_crawler.py +31 -359
- inspect_ai/tool/_tools/_web_browser/_resources/playwright_page_crawler.py +280 -0
- inspect_ai/tool/_tools/_web_browser/_resources/pyproject.toml +65 -0
- inspect_ai/tool/_tools/_web_browser/_resources/rectangle.py +64 -0
- inspect_ai/tool/_tools/_web_browser/_resources/rpc_client_helpers.py +146 -0
- inspect_ai/tool/_tools/_web_browser/_resources/scale_factor.py +64 -0
- inspect_ai/tool/_tools/_web_browser/_resources/test_accessibility_tree_node.py +180 -0
- inspect_ai/tool/_tools/_web_browser/_resources/test_playwright_crawler.py +15 -9
- inspect_ai/tool/_tools/_web_browser/_resources/test_rectangle.py +15 -0
- inspect_ai/tool/_tools/_web_browser/_resources/test_web_client.py +44 -0
- inspect_ai/tool/_tools/_web_browser/_resources/web_browser_rpc_types.py +39 -0
- inspect_ai/tool/_tools/_web_browser/_resources/web_client.py +198 -48
- inspect_ai/tool/_tools/_web_browser/_resources/web_client_new_session.py +26 -25
- inspect_ai/tool/_tools/_web_browser/_resources/web_server.py +178 -39
- inspect_ai/tool/_tools/_web_browser/_web_browser.py +38 -19
- inspect_ai/tool/_tools/_web_search.py +3 -3
- inspect_ai/util/__init__.py +2 -1
- inspect_ai/util/_concurrency.py +14 -8
- inspect_ai/util/_display.py +12 -0
- inspect_ai/util/_sandbox/context.py +15 -0
- inspect_ai/util/_sandbox/docker/docker.py +7 -5
- inspect_ai/util/_sandbox/environment.py +32 -1
- inspect_ai/util/_sandbox/events.py +183 -0
- inspect_ai/util/_sandbox/local.py +3 -3
- inspect_ai/util/_sandbox/self_check.py +131 -43
- inspect_ai/util/_subtask.py +11 -0
- {inspect_ai-0.3.69.dist-info → inspect_ai-0.3.71.dist-info}/METADATA +3 -3
- {inspect_ai-0.3.69.dist-info → inspect_ai-0.3.71.dist-info}/RECORD +233 -211
- {inspect_ai-0.3.69.dist-info → inspect_ai-0.3.71.dist-info}/WHEEL +1 -1
- inspect_ai/_view/www/src/components/VirtualList.module.css +0 -19
- inspect_ai/_view/www/src/components/VirtualList.tsx +0 -292
- inspect_ai/tool/_tools/_web_browser/_resources/accessibility_node.py +0 -312
- inspect_ai/tool/_tools/_web_browser/_resources/dm_env_servicer.py +0 -275
- inspect_ai/tool/_tools/_web_browser/_resources/images/usage_diagram.png +0 -0
- inspect_ai/tool/_tools/_web_browser/_resources/test_accessibility_node.py +0 -176
- inspect_ai/tool/_tools/_web_browser/_resources/test_dm_env_servicer.py +0 -135
- inspect_ai/tool/_tools/_web_browser/_resources/test_web_environment.py +0 -71
- inspect_ai/tool/_tools/_web_browser/_resources/web_environment.py +0 -184
- {inspect_ai-0.3.69.dist-info → inspect_ai-0.3.71.dist-info}/LICENSE +0 -0
- {inspect_ai-0.3.69.dist-info → inspect_ai-0.3.71.dist-info}/entry_points.txt +0 -0
- {inspect_ai-0.3.69.dist-info → inspect_ai-0.3.71.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,13 @@
|
|
1
|
+
import { FC } from "react";
|
2
|
+
import { ModelUsage, ModelUsage2 } from "../types/log";
|
1
3
|
import { TokenHeader, TokenRow, TokenTable } from "./TokenTable";
|
2
4
|
|
3
|
-
interface
|
4
|
-
model_usage:
|
5
|
+
interface ModelTokenTableProps {
|
6
|
+
model_usage: ModelUsage | ModelUsage2;
|
5
7
|
className?: string | string[];
|
6
8
|
}
|
7
9
|
|
8
|
-
export const ModelTokenTable:
|
10
|
+
export const ModelTokenTable: FC<ModelTokenTableProps> = ({
|
9
11
|
model_usage,
|
10
12
|
className,
|
11
13
|
}) => {
|
@@ -14,13 +16,7 @@ export const ModelTokenTable: React.FC<ModelTokenTable> = ({
|
|
14
16
|
<TokenHeader />
|
15
17
|
<tbody>
|
16
18
|
{Object.keys(model_usage).map((key) => {
|
17
|
-
return
|
18
|
-
<TokenRow
|
19
|
-
key={key}
|
20
|
-
model={`${key}-token-row`}
|
21
|
-
usage={model_usage[key]}
|
22
|
-
/>
|
23
|
-
);
|
19
|
+
return <TokenRow key={key} model={key} usage={model_usage[key]} />;
|
24
20
|
})}
|
25
21
|
</tbody>
|
26
22
|
</TokenTable>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
-
import { Fragment } from "react";
|
2
|
+
import { FC, Fragment } from "react";
|
3
3
|
import { ModelUsage1 } from "../types/log";
|
4
4
|
import { formatNumber } from "../utils/format";
|
5
5
|
import styles from "./ModelUsagePanel.module.css";
|
@@ -13,23 +13,40 @@ interface ModelUsageRow {
|
|
13
13
|
value?: number;
|
14
14
|
secondary?: boolean;
|
15
15
|
bordered?: boolean;
|
16
|
+
padded?: boolean;
|
16
17
|
}
|
17
18
|
|
18
19
|
/**
|
19
20
|
* Renders the ModelUsagePanel component.
|
20
21
|
*/
|
21
|
-
export const ModelUsagePanel:
|
22
|
+
export const ModelUsagePanel: FC<ModelUsageProps> = ({ usage }) => {
|
22
23
|
if (!usage) {
|
23
24
|
return null;
|
24
25
|
}
|
25
26
|
|
26
|
-
const rows: ModelUsageRow[] = [
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
const rows: ModelUsageRow[] = [];
|
28
|
+
|
29
|
+
if (usage.reasoning_tokens) {
|
30
|
+
rows.push({
|
31
|
+
label: "Reasoning",
|
32
|
+
value: usage.reasoning_tokens,
|
33
|
+
secondary: false,
|
34
|
+
bordered: true,
|
35
|
+
});
|
36
|
+
|
37
|
+
rows.push({
|
38
|
+
label: "---",
|
39
|
+
value: undefined,
|
30
40
|
secondary: false,
|
31
|
-
|
32
|
-
|
41
|
+
padded: true,
|
42
|
+
});
|
43
|
+
}
|
44
|
+
|
45
|
+
rows.push({
|
46
|
+
label: "input",
|
47
|
+
value: usage.input_tokens,
|
48
|
+
secondary: false,
|
49
|
+
});
|
33
50
|
|
34
51
|
if (usage.input_tokens_cache_read) {
|
35
52
|
rows.push({
|
@@ -71,7 +88,13 @@ export const ModelUsagePanel: React.FC<ModelUsageProps> = ({ usage }) => {
|
|
71
88
|
{rows.map((row, idx) => {
|
72
89
|
if (row.label === "---") {
|
73
90
|
return (
|
74
|
-
<div
|
91
|
+
<div
|
92
|
+
key={`$usage-sep-${idx}`}
|
93
|
+
className={clsx(
|
94
|
+
styles.separator,
|
95
|
+
row.padded ? styles.padded : undefined,
|
96
|
+
)}
|
97
|
+
></div>
|
75
98
|
);
|
76
99
|
} else {
|
77
100
|
return (
|
@@ -1,17 +1,15 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
+
import { FC, ReactNode } from "react";
|
2
3
|
import { ModelUsage1 } from "../types/log";
|
3
4
|
import { ModelUsagePanel } from "./ModelUsagePanel";
|
4
5
|
import styles from "./TokenTable.module.css";
|
5
6
|
|
6
7
|
interface TokenTableProps {
|
7
8
|
className?: string | string[];
|
8
|
-
children?:
|
9
|
+
children?: ReactNode;
|
9
10
|
}
|
10
11
|
|
11
|
-
export const TokenTable:
|
12
|
-
className,
|
13
|
-
children,
|
14
|
-
}) => {
|
12
|
+
export const TokenTable: FC<TokenTableProps> = ({ className, children }) => {
|
15
13
|
return (
|
16
14
|
<table
|
17
15
|
className={clsx(
|
@@ -77,7 +75,7 @@ interface TokenRowProps {
|
|
77
75
|
usage: ModelUsage1;
|
78
76
|
}
|
79
77
|
|
80
|
-
export const TokenRow:
|
78
|
+
export const TokenRow: FC<TokenRowProps> = ({ model, usage }) => {
|
81
79
|
return (
|
82
80
|
<tr>
|
83
81
|
<td>
|
@@ -7,6 +7,7 @@ import { EvalStats } from "../types/log";
|
|
7
7
|
import { formatDuration } from "../utils/format";
|
8
8
|
import { ModelTokenTable } from "./ModelTokenTable";
|
9
9
|
|
10
|
+
import { FC } from "react";
|
10
11
|
import styles from "./UsageCard.module.css";
|
11
12
|
|
12
13
|
const kUsageCardBodyId = "usage-card-body";
|
@@ -18,7 +19,7 @@ interface UsageCardProps {
|
|
18
19
|
/**
|
19
20
|
* Renders the UsageCard component.
|
20
21
|
*/
|
21
|
-
export const UsageCard:
|
22
|
+
export const UsageCard: FC<UsageCardProps> = ({ stats }) => {
|
22
23
|
if (!stats) {
|
23
24
|
return null;
|
24
25
|
}
|
@@ -77,9 +77,9 @@ export const formatDataset = (
|
|
77
77
|
*/
|
78
78
|
export const formatTime = (seconds: number): string => {
|
79
79
|
if (seconds < 60) {
|
80
|
-
return `${seconds} sec`;
|
80
|
+
return `${formatPrettyDecimal(seconds, 1)} sec`;
|
81
81
|
} else if (seconds < 60 * 60) {
|
82
|
-
return `${Math.floor(seconds / 60)} min ${seconds % 60} sec`;
|
82
|
+
return `${Math.floor(seconds / 60)} min ${Math.floor(seconds % 60)} sec`;
|
83
83
|
} else if (seconds < 60 * 60 * 24) {
|
84
84
|
const hours = Math.floor(seconds / (60 * 60));
|
85
85
|
const minutes = Math.floor((seconds % (60 * 60)) / 60);
|
@@ -97,15 +97,18 @@ export const formatTime = (seconds: number): string => {
|
|
97
97
|
/**
|
98
98
|
* Formats a number to a string with specific decimal places for prettiness.
|
99
99
|
*/
|
100
|
-
export function formatPrettyDecimal(
|
100
|
+
export function formatPrettyDecimal(
|
101
|
+
num: number,
|
102
|
+
maxDecimals: number = 3,
|
103
|
+
): string {
|
101
104
|
const numDecimalPlaces = num.toString().includes(".")
|
102
105
|
? num.toString().split(".")[1].length
|
103
106
|
: 0;
|
104
107
|
|
105
108
|
if (numDecimalPlaces === 0) {
|
106
109
|
return num.toFixed(1);
|
107
|
-
} else if (numDecimalPlaces >
|
108
|
-
return num.toFixed(
|
110
|
+
} else if (numDecimalPlaces > maxDecimals) {
|
111
|
+
return num.toFixed(maxDecimals);
|
109
112
|
} else {
|
110
113
|
return num.toString();
|
111
114
|
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
export const isJson = (text: string): boolean => {
|
2
|
+
text = text.trim();
|
3
|
+
if (text.startsWith("{") && text.endsWith("}")) {
|
4
|
+
try {
|
5
|
+
JSON.parse(text);
|
6
|
+
return true;
|
7
|
+
} catch {
|
8
|
+
return false;
|
9
|
+
}
|
10
|
+
}
|
11
|
+
return false;
|
12
|
+
};
|
13
|
+
|
14
|
+
export const parsedJson = (text: string): unknown | undefined => {
|
15
|
+
text = text.trim();
|
16
|
+
if (text.startsWith("{") && text.endsWith("}")) {
|
17
|
+
try {
|
18
|
+
return JSON.parse(text);
|
19
|
+
} catch {
|
20
|
+
return undefined;
|
21
|
+
}
|
22
|
+
}
|
23
|
+
return undefined;
|
24
|
+
};
|
@@ -5,7 +5,7 @@ import { JsonTab } from "./tabs/JsonTab";
|
|
5
5
|
import { SamplesTab } from "./tabs/SamplesTab";
|
6
6
|
|
7
7
|
import clsx from "clsx";
|
8
|
-
import { MouseEvent, RefObject, useEffect, useMemo, useRef } from "react";
|
8
|
+
import { FC, MouseEvent, RefObject, useEffect, useMemo, useRef } from "react";
|
9
9
|
import { SampleSummary } from "../api/types.ts";
|
10
10
|
import {
|
11
11
|
kEvalWorkspaceTabId,
|
@@ -84,7 +84,7 @@ interface WorkSpaceProps {
|
|
84
84
|
/**
|
85
85
|
* Renders the Main Application
|
86
86
|
*/
|
87
|
-
export const WorkSpace:
|
87
|
+
export const WorkSpace: FC<WorkSpaceProps> = (props) => {
|
88
88
|
const {
|
89
89
|
task_id,
|
90
90
|
evalStatus,
|
@@ -103,9 +103,6 @@ export const WorkSpace: React.FC<WorkSpaceProps> = (props) => {
|
|
103
103
|
workspaceTabScrollPositionRef,
|
104
104
|
setWorkspaceTabScrollPosition,
|
105
105
|
} = props;
|
106
|
-
if (!evalSpec) {
|
107
|
-
return null;
|
108
|
-
}
|
109
106
|
|
110
107
|
const divRef = useRef<HTMLDivElement>(null);
|
111
108
|
|
@@ -118,6 +115,10 @@ export const WorkSpace: React.FC<WorkSpaceProps> = (props) => {
|
|
118
115
|
|
119
116
|
const resolvedTabs = useResolvedTabs(props);
|
120
117
|
|
118
|
+
if (!evalSpec) {
|
119
|
+
return undefined;
|
120
|
+
}
|
121
|
+
|
121
122
|
return (
|
122
123
|
<WorkSpaceView
|
123
124
|
logFileName={logFileName}
|
@@ -1,5 +1,12 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
-
import {
|
2
|
+
import {
|
3
|
+
FC,
|
4
|
+
Fragment,
|
5
|
+
MouseEvent,
|
6
|
+
RefObject,
|
7
|
+
useCallback,
|
8
|
+
useMemo,
|
9
|
+
} from "react";
|
3
10
|
import { SampleSummary } from "../api/types";
|
4
11
|
import { EmptyPanel } from "../components/EmptyPanel";
|
5
12
|
import { TabPanel, TabSet } from "../components/TabSet";
|
@@ -37,7 +44,7 @@ interface WorkSpaceViewProps {
|
|
37
44
|
setWorkspaceTabScrollPosition: (tab: string, pos: number) => void;
|
38
45
|
}
|
39
46
|
|
40
|
-
export const WorkSpaceView:
|
47
|
+
export const WorkSpaceView: FC<WorkSpaceViewProps> = ({
|
41
48
|
logFileName,
|
42
49
|
evalSpec,
|
43
50
|
evalPlan,
|
@@ -78,6 +85,12 @@ export const WorkSpaceView: React.FC<WorkSpaceViewProps> = ({
|
|
78
85
|
},
|
79
86
|
[setSelectedTab],
|
80
87
|
);
|
88
|
+
const handleScroll = useCallback(
|
89
|
+
(tabid: string, position: number) => {
|
90
|
+
onScroll(tabid, position);
|
91
|
+
},
|
92
|
+
[onScroll],
|
93
|
+
);
|
81
94
|
|
82
95
|
if (evalSpec === undefined) {
|
83
96
|
return <EmptyPanel />;
|
@@ -138,12 +151,9 @@ export const WorkSpaceView: React.FC<WorkSpaceViewProps> = ({
|
|
138
151
|
scrollPosition={
|
139
152
|
workspaceTabScrollPositionRef.current?.[tab.id]
|
140
153
|
}
|
141
|
-
setScrollPosition={
|
142
|
-
(position
|
143
|
-
|
144
|
-
},
|
145
|
-
[onScroll],
|
146
|
-
)}
|
154
|
+
setScrollPosition={(position: number) => {
|
155
|
+
handleScroll(tab.id, position);
|
156
|
+
}}
|
147
157
|
>
|
148
158
|
{tab.content()}
|
149
159
|
</TabPanel>
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import { FC } from "react";
|
1
2
|
import { ApplicationIcons } from "../../appearance/icons";
|
2
3
|
|
3
4
|
import { ANSIDisplay } from "../../components/AnsiDisplay";
|
@@ -10,7 +11,7 @@ interface TaskErrorProps {
|
|
10
11
|
error: EvalError;
|
11
12
|
}
|
12
13
|
|
13
|
-
export const TaskErrorCard:
|
14
|
+
export const TaskErrorCard: FC<TaskErrorProps> = ({ error }) => {
|
14
15
|
return (
|
15
16
|
<Card>
|
16
17
|
<CardHeader
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
+
import { FC } from "react";
|
2
3
|
import { SampleSummary } from "../../api/types";
|
3
4
|
import { EvalDescriptor } from "../../samples/descriptor/types";
|
4
5
|
import {
|
@@ -29,7 +30,7 @@ interface NavBarProps {
|
|
29
30
|
/**
|
30
31
|
* Renders the Navbar
|
31
32
|
*/
|
32
|
-
export const Navbar:
|
33
|
+
export const Navbar: FC<NavBarProps> = ({
|
33
34
|
file,
|
34
35
|
evalSpec,
|
35
36
|
evalPlan,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
-
import { useCallback } from "react";
|
2
|
+
import { FC, useCallback } from "react";
|
3
3
|
import { SampleSummary } from "../../api/types";
|
4
4
|
import { ApplicationIcons } from "../../appearance/icons";
|
5
5
|
import { CopyButton } from "../../components/CopyButton";
|
@@ -20,7 +20,7 @@ interface PrimaryBarProps {
|
|
20
20
|
evalSpec?: EvalSpec;
|
21
21
|
}
|
22
22
|
|
23
|
-
export const PrimaryBar:
|
23
|
+
export const PrimaryBar: FC<PrimaryBarProps> = ({
|
24
24
|
showToggle,
|
25
25
|
offcanvas,
|
26
26
|
status,
|
@@ -34,7 +34,7 @@ export const PrimaryBar: React.FC<PrimaryBarProps> = ({
|
|
34
34
|
|
35
35
|
const handleToggle = useCallback(() => {
|
36
36
|
setOffcanvas(!offcanvas);
|
37
|
-
}, [offcanvas]);
|
37
|
+
}, [setOffcanvas, offcanvas]);
|
38
38
|
|
39
39
|
return (
|
40
40
|
<div className={clsx(styles.wrapper)}>
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
+
import { FC } from "react";
|
2
3
|
import { EvalMetric, EvalResults, EvalScore, Reducer } from "../../types/log";
|
3
4
|
import { formatPrettyDecimal } from "../../utils/format";
|
4
5
|
import { metricDisplayName } from "../utils";
|
@@ -13,7 +14,7 @@ interface MetricSummary {
|
|
13
14
|
metric: EvalMetric;
|
14
15
|
}
|
15
16
|
|
16
|
-
export const ResultsPanel:
|
17
|
+
export const ResultsPanel: FC<ResultsPanelProps> = ({ results }) => {
|
17
18
|
// Map the scores into a list of key/values
|
18
19
|
if (results?.scores?.length === 1) {
|
19
20
|
const scorers: Record<string, MetricSummary[]> = {};
|
@@ -75,7 +76,7 @@ interface VerticalMetricProps {
|
|
75
76
|
|
76
77
|
/** Renders a Vertical Metric
|
77
78
|
*/
|
78
|
-
const VerticalMetric:
|
79
|
+
const VerticalMetric: FC<VerticalMetricProps> = ({
|
79
80
|
metricSummary,
|
80
81
|
isFirst,
|
81
82
|
showReducer,
|
@@ -123,7 +124,7 @@ interface MultiScorerMetricProps {
|
|
123
124
|
showReducer: boolean;
|
124
125
|
}
|
125
126
|
|
126
|
-
const MultiScorerMetric:
|
127
|
+
const MultiScorerMetric: FC<MultiScorerMetricProps> = ({
|
127
128
|
scorer,
|
128
129
|
isFirst,
|
129
130
|
showReducer,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
+
import { FC } from "react";
|
2
3
|
import { SampleSummary } from "../../api/types";
|
3
4
|
import { ExpandablePanel } from "../../components/ExpandablePanel";
|
4
5
|
import { LabeledValue } from "../../components/LabeledValue";
|
@@ -27,7 +28,7 @@ interface SecondaryBarProps {
|
|
27
28
|
/**
|
28
29
|
* Renders the SecondaryBar
|
29
30
|
*/
|
30
|
-
export const SecondaryBar:
|
31
|
+
export const SecondaryBar: FC<SecondaryBarProps> = ({
|
31
32
|
evalSpec,
|
32
33
|
evalPlan,
|
33
34
|
evalResults,
|
@@ -152,7 +153,7 @@ interface DatasetSummaryProps {
|
|
152
153
|
/**
|
153
154
|
* A component that displays the dataset
|
154
155
|
*/
|
155
|
-
const DatasetSummary:
|
156
|
+
const DatasetSummary: FC<DatasetSummaryProps> = ({
|
156
157
|
dataset,
|
157
158
|
samples,
|
158
159
|
epochs,
|
@@ -177,7 +178,7 @@ interface ScoreSummaryProps {
|
|
177
178
|
/**
|
178
179
|
* A component that displays a list of scrorers
|
179
180
|
*/
|
180
|
-
const ScorerSummary:
|
181
|
+
const ScorerSummary: FC<ScoreSummaryProps> = ({ evalDescriptor }) => {
|
181
182
|
if (!evalDescriptor) {
|
182
183
|
return null;
|
183
184
|
}
|
@@ -202,7 +203,7 @@ interface ParamSummaryProps {
|
|
202
203
|
/**
|
203
204
|
* A component that displays a summary of parameters.
|
204
205
|
*/
|
205
|
-
const ParamSummary:
|
206
|
+
const ParamSummary: FC<ParamSummaryProps> = ({ params }) => {
|
206
207
|
if (!params) {
|
207
208
|
return null;
|
208
209
|
}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
+
import { FC } from "react";
|
2
3
|
import { ApplicationIcons } from "../../appearance/icons";
|
3
4
|
import styles from "./StatusPanel.module.css";
|
4
5
|
|
@@ -6,7 +7,7 @@ interface StatusProps {
|
|
6
7
|
sampleCount: number;
|
7
8
|
}
|
8
9
|
|
9
|
-
export const CancelledPanel:
|
10
|
+
export const CancelledPanel: FC<StatusProps> = ({ sampleCount }) => {
|
10
11
|
return (
|
11
12
|
<StatusPanel
|
12
13
|
icon={ApplicationIcons.logging["info"]}
|
@@ -16,7 +17,7 @@ export const CancelledPanel: React.FC<StatusProps> = ({ sampleCount }) => {
|
|
16
17
|
);
|
17
18
|
};
|
18
19
|
|
19
|
-
export const ErroredPanel:
|
20
|
+
export const ErroredPanel: FC<StatusProps> = ({ sampleCount }) => {
|
20
21
|
return (
|
21
22
|
<StatusPanel
|
22
23
|
icon={ApplicationIcons.logging["error"]}
|
@@ -26,7 +27,7 @@ export const ErroredPanel: React.FC<StatusProps> = ({ sampleCount }) => {
|
|
26
27
|
);
|
27
28
|
};
|
28
29
|
|
29
|
-
export const RunningPanel:
|
30
|
+
export const RunningPanel: FC<StatusProps> = ({ sampleCount }) => {
|
30
31
|
return (
|
31
32
|
<StatusPanel
|
32
33
|
icon={ApplicationIcons.running}
|
@@ -42,11 +43,7 @@ interface StatusPanelProps {
|
|
42
43
|
sampleCount: number;
|
43
44
|
}
|
44
45
|
|
45
|
-
const StatusPanel:
|
46
|
-
icon,
|
47
|
-
status,
|
48
|
-
sampleCount,
|
49
|
-
}) => {
|
46
|
+
const StatusPanel: FC<StatusPanelProps> = ({ icon, status, sampleCount }) => {
|
50
47
|
return (
|
51
48
|
<div className={styles.statusPanel}>
|
52
49
|
<i className={clsx(icon, styles.statusIcon)} style={{}} />
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
+
import { FC } from "react";
|
2
3
|
import { EvalLogHeader } from "../../api/types";
|
3
4
|
import styles from "./EvalStatus.module.css";
|
4
5
|
import { SidebarScoreView } from "./SidebarScoreView";
|
@@ -8,7 +9,7 @@ interface EvalStatusProps {
|
|
8
9
|
logHeader?: EvalLogHeader;
|
9
10
|
}
|
10
11
|
|
11
|
-
export const EvalStatus:
|
12
|
+
export const EvalStatus: FC<EvalStatusProps> = ({ logHeader }) => {
|
12
13
|
switch (logHeader?.status) {
|
13
14
|
case "error":
|
14
15
|
return <StatusError message="Error" />;
|
@@ -36,7 +37,7 @@ interface StatusProps {
|
|
36
37
|
message: string;
|
37
38
|
}
|
38
39
|
|
39
|
-
const StatusCancelled:
|
40
|
+
const StatusCancelled: FC<StatusProps> = ({ message }) => {
|
40
41
|
return (
|
41
42
|
<div
|
42
43
|
className={clsx(
|
@@ -51,7 +52,7 @@ const StatusCancelled: React.FC<StatusProps> = ({ message }) => {
|
|
51
52
|
);
|
52
53
|
};
|
53
54
|
|
54
|
-
const StatusRunning:
|
55
|
+
const StatusRunning: FC<StatusProps> = ({ message }) => {
|
55
56
|
return (
|
56
57
|
<div
|
57
58
|
className={clsx(
|
@@ -66,6 +67,6 @@ const StatusRunning: React.FC<StatusProps> = ({ message }) => {
|
|
66
67
|
);
|
67
68
|
};
|
68
69
|
|
69
|
-
const StatusError:
|
70
|
+
const StatusError: FC<StatusProps> = ({ message }) => {
|
70
71
|
return <div className={clsx(styles.error, "text-size-small")}>{message}</div>;
|
71
72
|
};
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
+
import { FC } from "react";
|
2
3
|
import styles from "./LogDirectoryTitleView.module.css";
|
3
4
|
|
4
5
|
interface LogDirectoryTitleViewProps {
|
@@ -6,7 +7,7 @@ interface LogDirectoryTitleViewProps {
|
|
6
7
|
offcanvas: boolean;
|
7
8
|
}
|
8
9
|
|
9
|
-
export const LogDirectoryTitleView:
|
10
|
+
export const LogDirectoryTitleView: FC<LogDirectoryTitleViewProps> = ({
|
10
11
|
log_dir,
|
11
12
|
offcanvas,
|
12
13
|
}) => {
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
+
import { FC } from "react";
|
2
3
|
import { Fragment } from "react/jsx-runtime";
|
3
4
|
import { EvalLogHeader, LogFiles } from "../../api/types";
|
4
5
|
import { ApplicationIcons } from "../../appearance/icons";
|
@@ -17,7 +18,7 @@ interface SidebarProps {
|
|
17
18
|
onSelectedIndexChanged: (index: number) => void;
|
18
19
|
}
|
19
20
|
|
20
|
-
export const Sidebar:
|
21
|
+
export const Sidebar: FC<SidebarProps> = ({
|
21
22
|
logs,
|
22
23
|
logHeaders,
|
23
24
|
offcanvas,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
-
import { Fragment } from "react";
|
2
|
+
import { FC, Fragment } from "react";
|
3
3
|
import { EvalLogHeader } from "../../api/types";
|
4
4
|
import { EvalStatus } from "./EvalStatus";
|
5
5
|
import styles from "./SidebarLogEntry.module.css";
|
@@ -9,7 +9,7 @@ interface SidebarLogEntryProps {
|
|
9
9
|
task: string;
|
10
10
|
}
|
11
11
|
|
12
|
-
export const SidebarLogEntry:
|
12
|
+
export const SidebarLogEntry: FC<SidebarLogEntryProps> = ({
|
13
13
|
logHeader,
|
14
14
|
task,
|
15
15
|
}) => {
|
@@ -2,13 +2,14 @@ import clsx from "clsx";
|
|
2
2
|
import { EvalScore } from "../../types/log";
|
3
3
|
import { formatPrettyDecimal } from "../../utils/format";
|
4
4
|
|
5
|
+
import { FC } from "react";
|
5
6
|
import { metricDisplayName } from "../utils";
|
6
7
|
import styles from "./SidebarScoreView.module.css";
|
7
8
|
interface SidebarScoreProps {
|
8
9
|
scorer: EvalScore;
|
9
10
|
}
|
10
11
|
|
11
|
-
export const SidebarScoreView:
|
12
|
+
export const SidebarScoreView: FC<SidebarScoreProps> = ({ scorer }) => {
|
12
13
|
const showReducer = !!scorer.reducer;
|
13
14
|
return (
|
14
15
|
<div className={styles.container}>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
-
import { Fragment } from "react";
|
2
|
+
import { FC, Fragment } from "react";
|
3
3
|
import { Scores } from "../../types/log";
|
4
4
|
import { formatPrettyDecimal } from "../../utils/format";
|
5
5
|
import { metricDisplayName } from "../utils";
|
@@ -9,7 +9,7 @@ interface SidebarScoresProps {
|
|
9
9
|
scores: Scores;
|
10
10
|
}
|
11
11
|
|
12
|
-
export const SidebarScoresView:
|
12
|
+
export const SidebarScoresView: FC<SidebarScoresProps> = ({ scores }) => {
|
13
13
|
const showReducer = scores.findIndex((score) => !!score.reducer) !== -1;
|
14
14
|
return (
|
15
15
|
<div className={styles.container}>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { useEffect, useState } from "react";
|
1
|
+
import { FC, useEffect, useState } from "react";
|
2
2
|
import { SampleSummary } from "../../api/types";
|
3
3
|
import { MessageBand } from "../../components/MessageBand";
|
4
4
|
import { PlanCard } from "../../plan/PlanCard";
|
@@ -22,7 +22,7 @@ interface PlanTabProps {
|
|
22
22
|
evalError?: EvalError;
|
23
23
|
}
|
24
24
|
|
25
|
-
export const InfoTab:
|
25
|
+
export const InfoTab: FC<PlanTabProps> = ({
|
26
26
|
evalSpec,
|
27
27
|
evalPlan,
|
28
28
|
evalResults,
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { filename } from "../../utils/path";
|
2
2
|
|
3
|
+
import { FC } from "react";
|
3
4
|
import { Capabilities } from "../../api/types";
|
4
5
|
import { DownloadPanel } from "../../components/DownloadPanel";
|
5
6
|
import { JSONPanel } from "../../components/JsonPanel";
|
@@ -17,11 +18,7 @@ interface JsonTabProps {
|
|
17
18
|
/**
|
18
19
|
* Renders JSON tab
|
19
20
|
*/
|
20
|
-
export const JsonTab:
|
21
|
-
logFile,
|
22
|
-
capabilities,
|
23
|
-
json,
|
24
|
-
}) => {
|
21
|
+
export const JsonTab: FC<JsonTabProps> = ({ logFile, capabilities, json }) => {
|
25
22
|
if (logFile && json.length > kJsonMaxSize && capabilities.downloadFiles) {
|
26
23
|
// This JSON file is so large we can't really productively render it
|
27
24
|
// we should instead just provide a DL link
|