Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions apps/report/src/components/sidebar/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@

// Allow tags to shrink
.cache-tag,
.xpath-tag,
.deepthink-tag {
flex-shrink: 0;
white-space: nowrap;
Expand Down Expand Up @@ -395,7 +396,7 @@
}

// Light mode Tag styles
.cache-tag {
.cache-tag, .xpath-tag {
color: #1890ff;
background-color: #e0f5ff;
}
Expand Down Expand Up @@ -558,7 +559,7 @@
}

// Tag styles for dark mode
.cache-tag {
.cache-tag, .xpath-tag {
color: #1890ff !important;
background-color: rgba(24, 144, 255, 0.15) !important;
}
Expand Down
108 changes: 101 additions & 7 deletions apps/report/src/components/sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ const Sidebar = (props: SidebarProps = {}): JSX.Element => {
setReplayAllMode,
} = props;
const groupedDump = useExecutionDump((store) => store.dump);
const playwrightAttributes = useExecutionDump(
(store) => store.playwrightAttributes,
);
const setActiveTask = useExecutionDump((store) => store.setActiveTask);
const activeTask = useExecutionDump((store) => store.activeTask);
const setHoverTask = useExecutionDump((store) => store.setHoverTask);
Expand Down Expand Up @@ -174,6 +177,27 @@ const Sidebar = (props: SidebarProps = {}): JSX.Element => {
) : null;
};

const getXPathTag = (task: ExecutionTaskWithSearchAreaUsage) => {
if (task.hitBy?.from !== 'User expected path') {
return null;
}

return (
<Tag
className="xpath-tag"
style={{
padding: '0 4px',
marginLeft: '4px',
marginRight: 0,
lineHeight: '16px',
}}
bordered={false}
>
XPath
</Tag>
);
};

const getStatusText = (task: ExecutionTaskWithSearchAreaUsage) => {
if (typeof task.timing?.cost === 'number') {
return timeCostStrElement(task.timing.cost);
Expand Down Expand Up @@ -405,6 +429,28 @@ const Sidebar = (props: SidebarProps = {}): JSX.Element => {
0,
);

// Calculate total time cost
// Prefer playwright_test_duration if available (from Playwright test framework)
// Otherwise, sum up all task timing costs
const totalTimeCost = useMemo(() => {
// Use Playwright test duration if available
if (playwrightAttributes?.playwright_test_duration) {
return playwrightAttributes.playwright_test_duration;
}

// Fallback: sum up all task timing costs
if (!groupedDump) return 0;

return groupedDump.executions.reduce((sum, execution) => {
return (
sum +
execution.tasks.reduce((taskSum, task) => {
return taskSum + (task.timing?.cost || 0);
}, 0)
);
}, 0);
}, [groupedDump, playwrightAttributes]);

// Keyboard navigation
useEffect(() => {
// all tasks
Expand Down Expand Up @@ -466,6 +512,7 @@ const Sidebar = (props: SidebarProps = {}): JSX.Element => {
<span>{taskName}</span>
{getTitleIcon(task)}
{getCacheTag(task)}
{getXPathTag(task)}
{getDeepThinkTag(task)}
</div>
);
Expand Down Expand Up @@ -585,10 +632,58 @@ const Sidebar = (props: SidebarProps = {}): JSX.Element => {
</div>

{/* Summary */}
{proModeEnabled && (
<div className="table-summary">
<div className="side-seperator side-seperator-line side-seperator-space-up" />
{(() => {
<div className="table-summary">
<div className="side-seperator side-seperator-line side-seperator-space-up" />
{/* Total time row - always visible */}
<div className="summary-row">
<div
className="summary-cell column-type"
style={{
minWidth: typeColumnMinWidth,
flex: 1,
}}
>
<div className="token-total-label">Total Time</div>
</div>
<div
className="summary-cell column-time"
style={{ width: dynamicWidths.time }}
>
<span className="token-value">
{timeCostStrElement(totalTimeCost)}
</span>
</div>
{proModeEnabled && (
<>
<div
className="summary-cell column-intent"
style={{ width: dynamicWidths.intent }}
/>
<div
className="summary-cell column-model"
style={{ width: dynamicWidths.model }}
/>
<div
className="summary-cell column-prompt"
style={{ width: dynamicWidths.prompt }}
/>
{hasCachedInput && (
<div
className="summary-cell column-cached"
style={{ width: dynamicWidths.cached }}
/>
)}
<div
className="summary-cell column-completion"
style={{ width: dynamicWidths.completion }}
/>
</>
)}
</div>

{/* Token usage rows - only in pro mode */}
{proModeEnabled &&
(() => {
const modelEntries = Array.from(tokensByModel.entries());
const hasMultipleModels = modelEntries.length > 1;

Expand Down Expand Up @@ -648,7 +743,7 @@ const Sidebar = (props: SidebarProps = {}): JSX.Element => {
</div>
))
: [
<div key="total" className="summary-row">
<div key="total-tokens" className="summary-row">
<div
className="summary-cell column-type"
style={{
Expand Down Expand Up @@ -699,8 +794,7 @@ const Sidebar = (props: SidebarProps = {}): JSX.Element => {
</div>,
];
})()}
</div>
)}
</div>
</div>
<div className="executions-tip">
<span className="tip-icon">?</span>
Expand Down