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
@@ -0,0 +1,32 @@
|
|
1
|
+
.contents {
|
2
|
+
margin-top: 0.5em;
|
3
|
+
}
|
4
|
+
|
5
|
+
.contents > :last-child {
|
6
|
+
margin-bottom: 0;
|
7
|
+
}
|
8
|
+
|
9
|
+
.twoColumn {
|
10
|
+
display: grid;
|
11
|
+
grid-template-columns: auto 1fr;
|
12
|
+
column-gap: 1.5em;
|
13
|
+
}
|
14
|
+
|
15
|
+
.exec {
|
16
|
+
margin-top: 0.5em;
|
17
|
+
}
|
18
|
+
|
19
|
+
.result {
|
20
|
+
margin-top: 0.5em;
|
21
|
+
}
|
22
|
+
|
23
|
+
.fileLabel {
|
24
|
+
margin-top: 0;
|
25
|
+
margin-bottom: 0;
|
26
|
+
}
|
27
|
+
|
28
|
+
.wrapPre {
|
29
|
+
white-space: pre-wrap;
|
30
|
+
word-wrap: break-word;
|
31
|
+
overflow-wrap: break-word;
|
32
|
+
}
|
@@ -0,0 +1,153 @@
|
|
1
|
+
import { ApplicationIcons } from "../../appearance/icons";
|
2
|
+
import ExpandablePanel from "../../components/ExpandablePanel";
|
3
|
+
import { MarkdownDiv } from "../../components/MarkdownDiv";
|
4
|
+
import { MetaDataGrid } from "../../metadata/MetaDataGrid";
|
5
|
+
import { SandboxEvent } from "../../types/log";
|
6
|
+
import { EventPanel } from "./event/EventPanel";
|
7
|
+
import { EventSection } from "./event/EventSection";
|
8
|
+
import { TranscriptEventState } from "./types";
|
9
|
+
|
10
|
+
import clsx from "clsx";
|
11
|
+
import { FC } from "react";
|
12
|
+
import styles from "./SandboxEventView.module.css";
|
13
|
+
import { formatTiming } from "./event/utils";
|
14
|
+
|
15
|
+
interface SandboxEventViewProps {
|
16
|
+
id: string;
|
17
|
+
event: SandboxEvent;
|
18
|
+
eventState: TranscriptEventState;
|
19
|
+
setEventState: (state: TranscriptEventState) => void;
|
20
|
+
className?: string | string[];
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Renders the SandboxEventView component.
|
25
|
+
*/
|
26
|
+
export const SandboxEventView: FC<SandboxEventViewProps> = ({
|
27
|
+
id,
|
28
|
+
event,
|
29
|
+
eventState,
|
30
|
+
setEventState,
|
31
|
+
className,
|
32
|
+
}) => {
|
33
|
+
return (
|
34
|
+
<EventPanel
|
35
|
+
id={id}
|
36
|
+
className={className}
|
37
|
+
title={`Sandbox: ${event.action}`}
|
38
|
+
icon={ApplicationIcons.sandbox}
|
39
|
+
subTitle={formatTiming(event.timestamp, event.working_start)}
|
40
|
+
selectedNav={eventState.selectedNav || ""}
|
41
|
+
setSelectedNav={(selectedNav) => {
|
42
|
+
setEventState({ ...eventState, selectedNav });
|
43
|
+
}}
|
44
|
+
collapsed={eventState.collapsed}
|
45
|
+
setCollapsed={(collapsed) => {
|
46
|
+
setEventState({ ...eventState, collapsed });
|
47
|
+
}}
|
48
|
+
>
|
49
|
+
{event.action === "exec" ? (
|
50
|
+
<ExecView event={event} />
|
51
|
+
) : event.action === "read_file" ? (
|
52
|
+
<ReadFileView event={event} />
|
53
|
+
) : (
|
54
|
+
<WriteFileView event={event} />
|
55
|
+
)}
|
56
|
+
</EventPanel>
|
57
|
+
);
|
58
|
+
};
|
59
|
+
|
60
|
+
interface ExecViewProps {
|
61
|
+
event: SandboxEvent;
|
62
|
+
}
|
63
|
+
|
64
|
+
const ExecView: FC<ExecViewProps> = ({ event }) => {
|
65
|
+
if (event.cmd === null) {
|
66
|
+
return undefined;
|
67
|
+
}
|
68
|
+
const cmd = event.cmd;
|
69
|
+
const options = event.options;
|
70
|
+
const input = event.input;
|
71
|
+
const result = event.result;
|
72
|
+
const output = event.output;
|
73
|
+
|
74
|
+
return (
|
75
|
+
<div className={clsx(styles.exec)}>
|
76
|
+
<EventSection title={`Command`}>
|
77
|
+
<div className={clsx(styles.twoColumn)}>
|
78
|
+
<pre className={clsx(styles.wrapPre)}>{cmd}</pre>
|
79
|
+
<pre className={clsx(styles.wrapPre)}>
|
80
|
+
{input !== null ? input?.trim() : undefined}
|
81
|
+
</pre>
|
82
|
+
|
83
|
+
{options !== null ? (
|
84
|
+
<EventSection title={`Options`}>
|
85
|
+
<MetaDataGrid
|
86
|
+
entries={options as Record<string, unknown>}
|
87
|
+
plain={true}
|
88
|
+
/>
|
89
|
+
</EventSection>
|
90
|
+
) : undefined}
|
91
|
+
</div>
|
92
|
+
</EventSection>
|
93
|
+
<EventSection title={`Result`}>
|
94
|
+
{output ? (
|
95
|
+
<ExpandablePanel collapse={false}>
|
96
|
+
<MarkdownDiv markdown={output} />
|
97
|
+
</ExpandablePanel>
|
98
|
+
) : undefined}
|
99
|
+
<div className={clsx(styles.result)}>Exited with code {result}</div>
|
100
|
+
</EventSection>
|
101
|
+
</div>
|
102
|
+
);
|
103
|
+
};
|
104
|
+
|
105
|
+
interface ReadFileViewProps {
|
106
|
+
event: SandboxEvent;
|
107
|
+
}
|
108
|
+
|
109
|
+
const ReadFileView: FC<ReadFileViewProps> = ({ event }) => {
|
110
|
+
if (event.file === null) {
|
111
|
+
return undefined;
|
112
|
+
}
|
113
|
+
const file = event.file;
|
114
|
+
const output = event.output;
|
115
|
+
return <FileView file={file} contents={output?.trim()} />;
|
116
|
+
};
|
117
|
+
|
118
|
+
interface WriteFileViewProps {
|
119
|
+
event: SandboxEvent;
|
120
|
+
}
|
121
|
+
|
122
|
+
const WriteFileView: FC<WriteFileViewProps> = ({ event }) => {
|
123
|
+
if (event.file === null) {
|
124
|
+
return undefined;
|
125
|
+
}
|
126
|
+
const file = event.file;
|
127
|
+
const input = event.input;
|
128
|
+
|
129
|
+
return <FileView file={file} contents={input?.trim()} />;
|
130
|
+
};
|
131
|
+
|
132
|
+
interface FileViewProps {
|
133
|
+
file: string;
|
134
|
+
contents?: string;
|
135
|
+
}
|
136
|
+
|
137
|
+
const FileView: FC<FileViewProps> = ({ file, contents }) => {
|
138
|
+
return (
|
139
|
+
<div>
|
140
|
+
<EventSection title="File">
|
141
|
+
<pre className={clsx(styles.fileLabel)}>{file}</pre>
|
142
|
+
</EventSection>
|
143
|
+
|
144
|
+
{contents ? (
|
145
|
+
<EventSection title="Contents">
|
146
|
+
<ExpandablePanel collapse={false}>
|
147
|
+
<pre>{contents}</pre>
|
148
|
+
</ExpandablePanel>
|
149
|
+
</EventSection>
|
150
|
+
) : undefined}
|
151
|
+
</div>
|
152
|
+
);
|
153
|
+
};
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Fragment } from "react";
|
1
|
+
import { FC, Fragment } from "react";
|
2
2
|
import { ApplicationIcons } from "../../appearance/icons";
|
3
3
|
import { MarkdownDiv } from "../../components/MarkdownDiv";
|
4
4
|
import { MetaDataGrid } from "../../metadata/MetaDataGrid";
|
@@ -21,7 +21,7 @@ interface ScoreEventViewProps {
|
|
21
21
|
/**
|
22
22
|
* Renders the ScoreEventView component.
|
23
23
|
*/
|
24
|
-
export const ScoreEventView:
|
24
|
+
export const ScoreEventView: FC<ScoreEventViewProps> = ({
|
25
25
|
id,
|
26
26
|
event,
|
27
27
|
eventState,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
-
import { RefObject, useCallback, useState } from "react";
|
2
|
+
import { FC, RefObject, useCallback, useState } from "react";
|
3
3
|
import { StepEvent } from "../../types/log";
|
4
4
|
import { formatDateTime } from "../../utils/format";
|
5
5
|
import { EventPanel } from "./event/EventPanel";
|
@@ -18,7 +18,7 @@ interface StepEventViewProps {
|
|
18
18
|
/**
|
19
19
|
* Renders the StepEventView component.
|
20
20
|
*/
|
21
|
-
export const StepEventView:
|
21
|
+
export const StepEventView: FC<StepEventViewProps> = ({
|
22
22
|
event,
|
23
23
|
eventState,
|
24
24
|
setEventState,
|
@@ -37,7 +37,7 @@ export const StepEventView: React.FC<StepEventViewProps> = ({
|
|
37
37
|
(state: TranscriptEventState) => {
|
38
38
|
setTranscriptState({ ...state });
|
39
39
|
},
|
40
|
-
[
|
40
|
+
[setTranscriptState],
|
41
41
|
);
|
42
42
|
|
43
43
|
return (
|
@@ -47,7 +47,7 @@ export const StepEventView: React.FC<StepEventViewProps> = ({
|
|
47
47
|
title={title}
|
48
48
|
subTitle={formatDateTime(new Date(event.timestamp))}
|
49
49
|
icon={descriptor.icon}
|
50
|
-
collapse={
|
50
|
+
collapse={descriptor.collapse}
|
51
51
|
text={text}
|
52
52
|
selectedNav={eventState.selectedNav || ""}
|
53
53
|
setSelectedNav={(selectedNav) => {
|
@@ -115,7 +115,7 @@ const summarize = (children: EventNode[]) => {
|
|
115
115
|
*/
|
116
116
|
const stepDescriptor = (
|
117
117
|
event: StepEvent,
|
118
|
-
): { icon?: string; name?: string; endSpace?: boolean } => {
|
118
|
+
): { icon?: string; name?: string; endSpace?: boolean; collapse?: boolean } => {
|
119
119
|
const rootStepDescriptor = {
|
120
120
|
endSpace: true,
|
121
121
|
};
|
@@ -161,6 +161,13 @@ const stepDescriptor = (
|
|
161
161
|
return {
|
162
162
|
...rootStepDescriptor,
|
163
163
|
name: "Sample Init",
|
164
|
+
collapse: true,
|
165
|
+
};
|
166
|
+
case "init":
|
167
|
+
return {
|
168
|
+
...rootStepDescriptor,
|
169
|
+
name: "Init",
|
170
|
+
collapse: true,
|
164
171
|
};
|
165
172
|
default:
|
166
173
|
return {
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
-
import { Fragment } from "react";
|
2
|
+
import { FC, Fragment } from "react";
|
3
3
|
import { ApplicationIcons } from "../../appearance/icons";
|
4
4
|
import { MetaDataView } from "../../metadata/MetaDataView";
|
5
|
-
import { Input2,
|
6
|
-
import { formatDateTime } from "../../utils/format";
|
5
|
+
import { Input2, Input5, Result2, SubtaskEvent } from "../../types/log";
|
7
6
|
import { EventPanel } from "./event/EventPanel";
|
7
|
+
import { formatTiming, formatTitle } from "./event/utils";
|
8
8
|
import styles from "./SubtaskEventView.module.css";
|
9
9
|
import { TranscriptView } from "./TranscriptView";
|
10
10
|
import { TranscriptEventState } from "./types";
|
@@ -21,7 +21,7 @@ interface SubtaskEventViewProps {
|
|
21
21
|
/**
|
22
22
|
* Renders the StateEventView component.
|
23
23
|
*/
|
24
|
-
export const SubtaskEventView:
|
24
|
+
export const SubtaskEventView: FC<SubtaskEventViewProps> = ({
|
25
25
|
id,
|
26
26
|
event,
|
27
27
|
eventState,
|
@@ -73,8 +73,12 @@ export const SubtaskEventView: React.FC<SubtaskEventViewProps> = ({
|
|
73
73
|
<EventPanel
|
74
74
|
id={id}
|
75
75
|
className={className}
|
76
|
-
title={
|
77
|
-
|
76
|
+
title={formatTitle(
|
77
|
+
`${type}: ${event.name}`,
|
78
|
+
undefined,
|
79
|
+
event.working_time,
|
80
|
+
)}
|
81
|
+
subTitle={formatTiming(event.timestamp, event.working_start)}
|
78
82
|
collapse={false}
|
79
83
|
selectedNav={eventState.selectedNav || ""}
|
80
84
|
setSelectedNav={(selectedNav) => {
|
@@ -91,25 +95,25 @@ export const SubtaskEventView: React.FC<SubtaskEventViewProps> = ({
|
|
91
95
|
};
|
92
96
|
|
93
97
|
interface SubtaskSummaryProps {
|
94
|
-
input: Input2 |
|
95
|
-
result:
|
98
|
+
input: Input2 | Input5;
|
99
|
+
result: Result2;
|
96
100
|
}
|
97
101
|
/**
|
98
102
|
* Renders the StateEventView component.
|
99
103
|
*/
|
100
|
-
const SubtaskSummary:
|
101
|
-
|
104
|
+
const SubtaskSummary: FC<SubtaskSummaryProps> = ({ input, result }) => {
|
105
|
+
const output = typeof result === "object" ? result : { result };
|
102
106
|
return (
|
103
107
|
<div className={clsx(styles.subtaskSummary)}>
|
104
108
|
<div className={clsx("text-style-label")}>Input</div>
|
105
109
|
<div className={clsx("text-size-large", styles.subtaskLabel)}></div>
|
106
110
|
<div className={clsx("text-style-label")}>Output</div>
|
107
|
-
<Rendered values={input} />
|
111
|
+
{input ? <Rendered values={input} /> : undefined}
|
108
112
|
<div className={clsx("text-size-title-secondary", styles.subtaskLabel)}>
|
109
113
|
<i className={ApplicationIcons.arrows.right} />
|
110
114
|
</div>
|
111
115
|
<div>
|
112
|
-
<Rendered values={
|
116
|
+
<Rendered values={output} />
|
113
117
|
</div>
|
114
118
|
</div>
|
115
119
|
);
|
@@ -123,7 +127,7 @@ interface RenderedProps {
|
|
123
127
|
* Recursively renders content based on the type of `values`.
|
124
128
|
value.
|
125
129
|
*/
|
126
|
-
const Rendered:
|
130
|
+
const Rendered: FC<RenderedProps> = ({ values }) => {
|
127
131
|
if (Array.isArray(values)) {
|
128
132
|
return values.map((val) => {
|
129
133
|
return <Rendered values={val} />;
|
@@ -139,7 +143,7 @@ const Rendered: React.FC<RenderedProps> = ({ values }) => {
|
|
139
143
|
}
|
140
144
|
};
|
141
145
|
|
142
|
-
const None:
|
146
|
+
const None: FC = () => {
|
143
147
|
return (
|
144
148
|
<span className={clsx("text-size-small", "text-style-secondary")}>
|
145
149
|
[None]
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import { ApplicationIcons } from "../../appearance/icons";
|
2
2
|
import { ToolEvent } from "../../types/log";
|
3
|
-
import { formatDateTime } from "../../utils/format";
|
4
3
|
import { resolveToolInput } from "../chat/tools/tool";
|
5
4
|
import { ToolCallView } from "../chat/tools/ToolCallView";
|
6
5
|
import { ApprovalEventView } from "./ApprovalEventView";
|
@@ -8,7 +7,8 @@ import { EventPanel } from "./event/EventPanel";
|
|
8
7
|
import { TranscriptView } from "./TranscriptView";
|
9
8
|
import { TranscriptEventState } from "./types";
|
10
9
|
|
11
|
-
import { useMemo } from "react";
|
10
|
+
import { FC, useMemo } from "react";
|
11
|
+
import { formatTiming, formatTitle } from "./event/utils";
|
12
12
|
import styles from "./ToolEventView.module.css";
|
13
13
|
|
14
14
|
interface ToolEventViewProps {
|
@@ -23,7 +23,7 @@ interface ToolEventViewProps {
|
|
23
23
|
/**
|
24
24
|
* Renders the ToolEventView component.
|
25
25
|
*/
|
26
|
-
export const ToolEventView:
|
26
|
+
export const ToolEventView: FC<ToolEventViewProps> = ({
|
27
27
|
id,
|
28
28
|
event,
|
29
29
|
eventState,
|
@@ -46,9 +46,9 @@ export const ToolEventView: React.FC<ToolEventViewProps> = ({
|
|
46
46
|
return (
|
47
47
|
<EventPanel
|
48
48
|
id={id}
|
49
|
-
title={title}
|
49
|
+
title={formatTitle(title, undefined, event.working_time)}
|
50
50
|
className={className}
|
51
|
-
subTitle={
|
51
|
+
subTitle={formatTiming(event.timestamp, event.working_start)}
|
52
52
|
icon={ApplicationIcons.solvers.use_tools}
|
53
53
|
selectedNav={eventState.selectedNav || ""}
|
54
54
|
setSelectedNav={(selectedNav) => {
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import React, { RefObject, useCallback, useState } from "react";
|
2
|
-
import { VirtualList } from "../../components/VirtualList";
|
3
2
|
import { Events } from "../../types/log";
|
4
3
|
import { ApprovalEventView } from "./ApprovalEventView";
|
5
4
|
import { ErrorEventView } from "./ErrorEventView";
|
@@ -17,6 +16,8 @@ import { ToolEventView } from "./ToolEventView";
|
|
17
16
|
import { EventNode, EventType, TranscriptEventState } from "./types";
|
18
17
|
|
19
18
|
import clsx from "clsx";
|
19
|
+
import { Virtuoso } from "react-virtuoso";
|
20
|
+
import { SandboxEventView } from "./SandboxEventView";
|
20
21
|
import styles from "./TranscriptView.module.css";
|
21
22
|
|
22
23
|
interface TranscriptViewProps {
|
@@ -83,7 +84,7 @@ export const TranscriptVirtualList: React.FC<TranscriptVirtualListProps> = (
|
|
83
84
|
(state: TranscriptEventState) => {
|
84
85
|
setTranscriptState(state);
|
85
86
|
},
|
86
|
-
[
|
87
|
+
[setTranscriptState],
|
87
88
|
);
|
88
89
|
|
89
90
|
return (
|
@@ -115,9 +116,11 @@ export const TranscriptVirtualListComponent: React.FC<
|
|
115
116
|
(eventId: string, state: TranscriptEventState) => {
|
116
117
|
setTranscriptState({ ...transcriptState, [eventId]: state });
|
117
118
|
},
|
118
|
-
[setTranscriptState],
|
119
|
+
[transcriptState, setTranscriptState],
|
119
120
|
);
|
120
121
|
|
122
|
+
const [followOutput, setFollowOutput] = useState(false);
|
123
|
+
|
121
124
|
const renderRow = (item: EventNode, index: number) => {
|
122
125
|
const bgClass = item.depth % 2 == 0 ? styles.darkenedBg : styles.normalBg;
|
123
126
|
const paddingClass = index === 0 ? styles.first : undefined;
|
@@ -139,12 +142,24 @@ export const TranscriptVirtualListComponent: React.FC<
|
|
139
142
|
};
|
140
143
|
|
141
144
|
return (
|
142
|
-
<
|
145
|
+
<Virtuoso
|
146
|
+
customScrollParent={scrollRef?.current ? scrollRef.current : undefined}
|
147
|
+
style={{ height: "100%", width: "100%" }}
|
143
148
|
data={eventNodes}
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
149
|
+
itemContent={(index: number, data: EventNode) => {
|
150
|
+
return renderRow(data, index);
|
151
|
+
}}
|
152
|
+
increaseViewportBy={{ top: 1000, bottom: 1000 }}
|
153
|
+
overscan={{
|
154
|
+
main: 10,
|
155
|
+
reverse: 10,
|
156
|
+
}}
|
157
|
+
followOutput={followOutput}
|
158
|
+
atBottomStateChange={(atBottom: boolean) => {
|
159
|
+
setFollowOutput(atBottom);
|
160
|
+
}}
|
161
|
+
skipAnimationFrameInResizeObserver={true}
|
162
|
+
className={clsx("transcript")}
|
148
163
|
/>
|
149
164
|
);
|
150
165
|
};
|
@@ -164,6 +179,13 @@ export const TranscriptComponent: React.FC<TranscriptComponentProps> = ({
|
|
164
179
|
setTranscriptState,
|
165
180
|
eventNodes,
|
166
181
|
}) => {
|
182
|
+
const setEventState = useCallback(
|
183
|
+
(state: TranscriptEventState, eventId: string) => {
|
184
|
+
setTranscriptState({ ...transcriptState, [eventId]: state });
|
185
|
+
},
|
186
|
+
[setTranscriptState, transcriptState],
|
187
|
+
);
|
188
|
+
|
167
189
|
const rows = eventNodes.map((eventNode, index) => {
|
168
190
|
const clz = [styles.eventNode];
|
169
191
|
if (eventNode.depth % 2 == 0) {
|
@@ -174,12 +196,6 @@ export const TranscriptComponent: React.FC<TranscriptComponentProps> = ({
|
|
174
196
|
}
|
175
197
|
|
176
198
|
const eventId = `${id}-event${index}`;
|
177
|
-
const setEventState = useCallback(
|
178
|
-
(state: TranscriptEventState) => {
|
179
|
-
setTranscriptState({ ...transcriptState, [eventId]: state });
|
180
|
-
},
|
181
|
-
[setTranscriptState, transcriptState],
|
182
|
-
);
|
183
199
|
|
184
200
|
const row = (
|
185
201
|
<div
|
@@ -194,7 +210,9 @@ export const TranscriptComponent: React.FC<TranscriptComponentProps> = ({
|
|
194
210
|
node={eventNode}
|
195
211
|
className={clsx(clz)}
|
196
212
|
eventState={transcriptState[eventId] || {}}
|
197
|
-
setEventState={
|
213
|
+
setEventState={(state: TranscriptEventState) => {
|
214
|
+
setEventState(state, eventId);
|
215
|
+
}}
|
198
216
|
/>
|
199
217
|
</div>
|
200
218
|
);
|
@@ -373,6 +391,17 @@ export const RenderedEventNode: React.FC<RenderedEventNodeProps> = ({
|
|
373
391
|
case "approval":
|
374
392
|
return <ApprovalEventView event={node.event} className={className} />;
|
375
393
|
|
394
|
+
case "sandbox":
|
395
|
+
return (
|
396
|
+
<SandboxEventView
|
397
|
+
id={id}
|
398
|
+
event={node.event}
|
399
|
+
className={className}
|
400
|
+
eventState={eventState}
|
401
|
+
setEventState={setEventState}
|
402
|
+
/>
|
403
|
+
);
|
404
|
+
|
376
405
|
default:
|
377
406
|
return null;
|
378
407
|
}
|
@@ -390,8 +419,14 @@ const fixupEventStream = (events: Events) => {
|
|
390
419
|
// Filter pending events
|
391
420
|
const finalEvents = events.filter((e) => !e.pending);
|
392
421
|
|
422
|
+
// See if the find an init step
|
423
|
+
const hasInitStep =
|
424
|
+
events.findIndex((e) => {
|
425
|
+
return e.event === "step" && e.name === "init";
|
426
|
+
}) !== -1;
|
427
|
+
|
393
428
|
const fixedUp = [...finalEvents];
|
394
|
-
if (initEvent) {
|
429
|
+
if (!hasInitStep && initEvent) {
|
395
430
|
fixedUp.splice(initEventIndex, 0, {
|
396
431
|
timestamp: initEvent.timestamp,
|
397
432
|
event: "step",
|
@@ -399,6 +434,7 @@ const fixupEventStream = (events: Events) => {
|
|
399
434
|
type: null,
|
400
435
|
name: "sample_init",
|
401
436
|
pending: false,
|
437
|
+
working_start: 0,
|
402
438
|
});
|
403
439
|
|
404
440
|
fixedUp.splice(initEventIndex + 2, 0, {
|
@@ -408,6 +444,7 @@ const fixupEventStream = (events: Events) => {
|
|
408
444
|
type: null,
|
409
445
|
name: "sample_init",
|
410
446
|
pending: false,
|
447
|
+
working_start: 0,
|
411
448
|
});
|
412
449
|
}
|
413
450
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import clsx from "clsx";
|
2
2
|
|
3
|
+
import { FC } from "react";
|
3
4
|
import styles from "./EventNav.module.css";
|
4
5
|
|
5
6
|
interface EventNavProps {
|
@@ -11,7 +12,7 @@ interface EventNavProps {
|
|
11
12
|
/**
|
12
13
|
* Component to render a single navigation item.
|
13
14
|
*/
|
14
|
-
export const EventNav:
|
15
|
+
export const EventNav: FC<EventNavProps> = ({
|
15
16
|
target,
|
16
17
|
title,
|
17
18
|
selectedNav,
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import clsx from "clsx";
|
2
2
|
import { EventNav } from "./EventNav";
|
3
3
|
|
4
|
+
import { FC } from "react";
|
4
5
|
import styles from "./EventNavs.module.css";
|
5
6
|
|
6
7
|
interface EventNavsProps {
|
@@ -12,7 +13,7 @@ interface EventNavsProps {
|
|
12
13
|
/**
|
13
14
|
* Component to render navigation items.
|
14
15
|
*/
|
15
|
-
export const EventNavs:
|
16
|
+
export const EventNavs: FC<EventNavsProps> = ({
|
16
17
|
navs,
|
17
18
|
selectedNav,
|
18
19
|
setSelectedNav,
|
@@ -55,16 +55,19 @@ export const EventPanel: React.FC<EventPanelProps> = ({
|
|
55
55
|
const defaultPillId = pillId(0);
|
56
56
|
|
57
57
|
const gridColumns = [];
|
58
|
+
|
59
|
+
// chevron
|
58
60
|
if (hasCollapse) {
|
59
61
|
gridColumns.push("minmax(0, max-content)");
|
60
62
|
}
|
63
|
+
|
64
|
+
// icon
|
61
65
|
if (icon) {
|
62
66
|
gridColumns.push("max-content");
|
63
67
|
}
|
68
|
+
|
69
|
+
// title
|
64
70
|
gridColumns.push("minmax(0, max-content)");
|
65
|
-
if (subTitle) {
|
66
|
-
gridColumns.push("minmax(0, max-content)");
|
67
|
-
}
|
68
71
|
gridColumns.push("auto");
|
69
72
|
gridColumns.push("minmax(0, max-content)");
|
70
73
|
gridColumns.push("minmax(0, max-content)");
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
+
import { FC, ReactNode } from "react";
|
2
3
|
import { ApplicationIcons } from "../../../appearance/icons";
|
3
4
|
import styles from "./EventRow.module.css";
|
4
5
|
|
@@ -6,12 +7,12 @@ interface EventRowProps {
|
|
6
7
|
title: string;
|
7
8
|
icon: string;
|
8
9
|
className?: string | string[];
|
9
|
-
children?:
|
10
|
+
children?: ReactNode | ReactNode[];
|
10
11
|
}
|
11
12
|
/**
|
12
13
|
* Renders the EventRow component.
|
13
14
|
*/
|
14
|
-
export const EventRow:
|
15
|
+
export const EventRow: FC<EventRowProps> = ({
|
15
16
|
title,
|
16
17
|
icon,
|
17
18
|
className,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import clsx from "clsx";
|
2
|
-
import { ReactNode } from "react";
|
2
|
+
import { FC, ReactNode } from "react";
|
3
3
|
import styles from "./EventSection.module.css";
|
4
4
|
|
5
5
|
interface EventSectionProps {
|
@@ -11,7 +11,7 @@ interface EventSectionProps {
|
|
11
11
|
/**
|
12
12
|
* Renders the Event Section component.
|
13
13
|
*/
|
14
|
-
export const EventSection:
|
14
|
+
export const EventSection: FC<EventSectionProps> = ({
|
15
15
|
title,
|
16
16
|
children,
|
17
17
|
className,
|
@@ -0,0 +1,28 @@
|
|
1
|
+
.wrapper {
|
2
|
+
display: grid;
|
3
|
+
grid-template-columns: 0 auto auto;
|
4
|
+
column-gap: 1.5em;
|
5
|
+
row-gap: 0.2em;
|
6
|
+
}
|
7
|
+
|
8
|
+
.col2 {
|
9
|
+
grid-column: 2;
|
10
|
+
}
|
11
|
+
|
12
|
+
.col1_3 {
|
13
|
+
grid-column: 1/3;
|
14
|
+
}
|
15
|
+
|
16
|
+
.col3 {
|
17
|
+
grid-column: 3;
|
18
|
+
}
|
19
|
+
|
20
|
+
.separator {
|
21
|
+
grid-column: -1/1;
|
22
|
+
height: 1px;
|
23
|
+
background-color: var(--bs-light-border-subtle);
|
24
|
+
}
|
25
|
+
|
26
|
+
.topMargin {
|
27
|
+
margin-top: 1em;
|
28
|
+
}
|