Skip to content

Evaluation: Show cost#113

Open
AkhileshNegi wants to merge 4 commits intomainfrom
enhancement/evaluation-cost
Open

Evaluation: Show cost#113
AkhileshNegi wants to merge 4 commits intomainfrom
enhancement/evaluation-cost

Conversation

@AkhileshNegi
Copy link
Copy Markdown
Contributor

@AkhileshNegi AkhileshNegi commented Apr 10, 2026

Summary

Target issue is #39

New Features

  • Evaluation run cards now prominently display the total cost of each evaluation for quick reference with tooltip for cost breakdown
image

Summary by CodeRabbit

  • New Features
    • Evaluation run cards now show a total USD cost indicator when cost data is present.
    • Interactive "i" help tooltip shows a detailed cost breakdown with separate response and embedding line items and closes automatically on scroll.
    • Cost values are formatted with appropriate USD precision for readability and consistency.

@AkhileshNegi AkhileshNegi self-assigned this Apr 10, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 10, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c32508a6-abff-45c8-a0ed-20dbb7f5bdb5

📥 Commits

Reviewing files that changed from the base of the PR and between 35771f7 and 27c788c.

📒 Files selected for processing (1)
  • app/components/utils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/components/utils.ts

📝 Walkthrough

Walkthrough

Adds per-run cost data to EvalRunCard with a formatted USD total and an interactive tooltip; introduces cost-related TypeScript types and a utility to format USD amounts.

Changes

Cohort / File(s) Summary
EvalRunCard UI & Tooltip
app/components/evaluations/EvalRunCard.tsx
Conditionally renders cost indicator (total USD) in Row 3, adds an “i” help tooltip showing response/embedding cost breakdowns, manages tooltip open state and position, and closes tooltip on scroll via a useEffect listener.
Type Definitions
app/components/types.ts
Added EvalCostEntry and EvalCost interfaces; extended EvalJob with optional `cost?: EvalCost
Formatting Utility
app/components/utils.ts
Added formatCostUSD(cost: number): string to format USD values with $ prefix, using 4-decimal precision for values < $0.01 and 2-decimal otherwise; returns "N/A" for non-finite inputs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

ready-for-review

Suggested reviewers

  • Prajna1999
  • vprashrex

Poem

🐰 I hopped into code with a hop and a twirl,
Adding pennies and cents to each eval swirl.
Tooltips that sparkle, totals that gleam,
A rabbit's small patch to the UI dream. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Evaluation: Show cost' directly and clearly summarizes the main change: adding cost display functionality to evaluation run cards.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch enhancement/evaluation-cost

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@AkhileshNegi AkhileshNegi requested a review from Ayush8923 April 10, 2026 04:09
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/`(main)/evaluations/[id]/page.tsx:
- Around line 755-757: Reformat the inline JSX conditional that renders token
counts to satisfy Prettier: break the expression onto multiple lines and align
parentheses/spacing around the conditional expression so it matches surrounding
JSX formatting (the block using job.cost.response.input_tokens and
job.cost.response.output_tokens and calling formatTokenCount). Update the
conditional rendering around that span (the JSX that checks
job.cost.response.input_tokens != null && job.cost.response.output_tokens !=
null) to follow Prettier’s preferred line breaks and indentation.
- Around line 698-726: The cost card currently only checks job.cost before
calling formatCostUSD(job.cost.total_cost_usd), which can throw if
total_cost_usd is missing; update the render guard in the Cost Breakdown block
(the JSX that renders Total Cost and calls formatCostUSD) to explicitly verify
total_cost_usd exists and is a valid number (e.g., job.cost?.total_cost_usd !=
null and Number.isFinite(job.cost.total_cost_usd)) before calling formatCostUSD,
and render a fallback (e.g., "—" or "N/A") when it's absent; adjust the
condition that wraps the Total Cost div (where formatCostUSD is invoked) so
formatCostUSD is only called when the value is present and valid.

In `@app/components/utils.ts`:
- Around line 75-80: The function formatCostUSD currently calls toFixed on
possibly invalid inputs and can produce "$NaN" or throw; modify formatCostUSD to
first validate the input (e.g., Number.isFinite(cost)) and if it's not a finite
number return a safe fallback like "$0.00"; only perform the cost < 0.01 branch
and call cost.toFixed(4) / toFixed(2) after the finite check so toFixed is never
invoked on bad values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b9b1507a-6bd0-4b38-a642-0a1ec4400c2e

📥 Commits

Reviewing files that changed from the base of the PR and between 77079eb and bbadd89.

📒 Files selected for processing (4)
  • app/(main)/evaluations/[id]/page.tsx
  • app/components/evaluations/EvalRunCard.tsx
  • app/components/types.ts
  • app/components/utils.ts

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/components/evaluations/EvalRunCard.tsx (1)

149-175: Unify tooltip width/position constants to avoid edge clipping drift.

Line 149 uses tooltipWidth = 280 while Line 171 renders width: "260px". This can mis-clamp near the viewport edge. Consider sharing one constant and clamping top as well.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/evaluations/EvalRunCard.tsx` around lines 149 - 175, The
tooltip width/position math is inconsistent: the onMouseEnter handler declares
tooltipWidth = 280 but the rendered style uses width: "260px", which can cause
clamping drift and edge clipping; update the component to use a single shared
constant for tooltip width (replace the local tooltipWidth and the hard-coded
"260px" with a single constant such as TOOLTIP_WIDTH) and use that same value
when computing clampedLeft and when setting the style, and also clamp/set the
tooltip top (using rect.top/rect.height and window.scrollY or Math.max/Math.min)
before calling setCostTooltipPos so costTooltipPos, setCostTooltipPos,
isCostTooltipOpen and the tooltip style remain consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/components/evaluations/EvalRunCard.tsx`:
- Around line 165-195: The tooltip can end up empty because it only renders
job.cost.response and job.cost.embedding; update the EvalRunCard tooltip
rendering to include a fallback row when neither response nor embedding exist:
inside the isCostTooltipOpen block (where costTooltipPos and formatCostUSD are
used) add a default line that displays a descriptive label like "Total cost" and
formats job.cost.total (or job.cost.cost_usd / computed total) so the tooltip
always shows at least the aggregate cost when EvalCost lacks response/embedding
entries.
- Around line 141-197: The tooltip trigger is a plain div with only mouse
handlers; make it keyboard and touch accessible by replacing or enhancing the
trigger element (the current inline div that references isCostTooltipOpen,
setIsCostTooltipOpen, costTooltipPos, setCostTooltipPos) so it is focusable and
operable: add role="button" or use a real <button>, include tabIndex,
aria-label/aria-describedby (pointing to the tooltip container) and
aria-expanded tied to isCostTooltipOpen, add onFocus/onBlur handlers that mirror
onMouseEnter/onMouseLeave to set costTooltipPos and open/close, implement
onKeyDown to open on Enter/Space and close on Escape, and add onClick to support
touch toggling; ensure the tooltip container is referenced by id for
accessibility and retains pointer-events: none only if you still need it
visually but allow screen readers to access its contents.

---

Nitpick comments:
In `@app/components/evaluations/EvalRunCard.tsx`:
- Around line 149-175: The tooltip width/position math is inconsistent: the
onMouseEnter handler declares tooltipWidth = 280 but the rendered style uses
width: "260px", which can cause clamping drift and edge clipping; update the
component to use a single shared constant for tooltip width (replace the local
tooltipWidth and the hard-coded "260px" with a single constant such as
TOOLTIP_WIDTH) and use that same value when computing clampedLeft and when
setting the style, and also clamp/set the tooltip top (using
rect.top/rect.height and window.scrollY or Math.max/Math.min) before calling
setCostTooltipPos so costTooltipPos, setCostTooltipPos, isCostTooltipOpen and
the tooltip style remain consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b81330e1-c480-433c-b122-4a853d4798ca

📥 Commits

Reviewing files that changed from the base of the PR and between bbadd89 and 35771f7.

📒 Files selected for processing (2)
  • app/components/evaluations/EvalRunCard.tsx
  • app/components/utils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/components/utils.ts

Comment on lines +141 to +197
<div
className="inline-flex items-center justify-center w-4 h-4 rounded-full text-xs font-normal cursor-help"
style={{
backgroundColor: isCostTooltipOpen ? "#171717" : "#fafafa",
color: isCostTooltipOpen ? "#ffffff" : "#737373",
}}
onMouseEnter={(e) => {
const rect = e.currentTarget.getBoundingClientRect();
const tooltipWidth = 280;
const centerX = rect.left + rect.width / 2;
const clampedLeft = Math.min(
Math.max(centerX - tooltipWidth / 2, 8),
window.innerWidth - tooltipWidth - 8,
);
setCostTooltipPos({
top: rect.top - 8,
left: clampedLeft,
});
setIsCostTooltipOpen(true);
}}
onMouseLeave={() => setIsCostTooltipOpen(false)}
>
i
</div>
{isCostTooltipOpen && (
<div
className="fixed z-50 px-3 py-2 rounded-md text-xs whitespace-normal pointer-events-none space-y-1"
style={{
backgroundColor: "#171717",
color: "#ffffff",
width: "260px",
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
top: costTooltipPos.top,
left: costTooltipPos.left,
transform: "translateY(-100%)",
}}
>
{job.cost.response && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>
Response generation
</span>
<span>{formatCostUSD(job.cost.response.cost_usd)}</span>
</div>
)}
{job.cost.embedding && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>
Cosine similarity calculation
</span>
<span>
{formatCostUSD(job.cost.embedding.cost_usd)}
</span>
</div>
)}
</div>
)}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Cost tooltip is mouse-only and not keyboard/touch accessible.

On Lines 147-162, the trigger is a div with hover handlers only. Keyboard and touch users can’t reliably open this tooltip.

Proposed accessibility fix
-                <div
+                <button
+                  type="button"
+                  aria-label="Show cost breakdown"
+                  aria-expanded={isCostTooltipOpen}
+                  aria-describedby={`cost-tooltip-${job.id}`}
                   className="inline-flex items-center justify-center w-4 h-4 rounded-full text-xs font-normal cursor-help"
                   style={{
                     backgroundColor: isCostTooltipOpen ? "#171717" : "#fafafa",
                     color: isCostTooltipOpen ? "#ffffff" : "#737373",
                   }}
                   onMouseEnter={(e) => {
                     const rect = e.currentTarget.getBoundingClientRect();
                     const tooltipWidth = 280;
                     const centerX = rect.left + rect.width / 2;
                     const clampedLeft = Math.min(
                       Math.max(centerX - tooltipWidth / 2, 8),
                       window.innerWidth - tooltipWidth - 8,
                     );
                     setCostTooltipPos({
                       top: rect.top - 8,
                       left: clampedLeft,
                     });
                     setIsCostTooltipOpen(true);
                   }}
                   onMouseLeave={() => setIsCostTooltipOpen(false)}
+                  onFocus={(e) => {
+                    const rect = e.currentTarget.getBoundingClientRect();
+                    const tooltipWidth = 280;
+                    const centerX = rect.left + rect.width / 2;
+                    const clampedLeft = Math.min(
+                      Math.max(centerX - tooltipWidth / 2, 8),
+                      window.innerWidth - tooltipWidth - 8,
+                    );
+                    setCostTooltipPos({ top: rect.top - 8, left: clampedLeft });
+                    setIsCostTooltipOpen(true);
+                  }}
+                  onBlur={() => setIsCostTooltipOpen(false)}
+                  onClick={() => setIsCostTooltipOpen((prev) => !prev)}
                 >
                   i
-                </div>
+                </button>
                 {isCostTooltipOpen && (
                   <div
+                    id={`cost-tooltip-${job.id}`}
+                    role="tooltip"
                     className="fixed z-50 px-3 py-2 rounded-md text-xs whitespace-normal pointer-events-none space-y-1"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div
className="inline-flex items-center justify-center w-4 h-4 rounded-full text-xs font-normal cursor-help"
style={{
backgroundColor: isCostTooltipOpen ? "#171717" : "#fafafa",
color: isCostTooltipOpen ? "#ffffff" : "#737373",
}}
onMouseEnter={(e) => {
const rect = e.currentTarget.getBoundingClientRect();
const tooltipWidth = 280;
const centerX = rect.left + rect.width / 2;
const clampedLeft = Math.min(
Math.max(centerX - tooltipWidth / 2, 8),
window.innerWidth - tooltipWidth - 8,
);
setCostTooltipPos({
top: rect.top - 8,
left: clampedLeft,
});
setIsCostTooltipOpen(true);
}}
onMouseLeave={() => setIsCostTooltipOpen(false)}
>
i
</div>
{isCostTooltipOpen && (
<div
className="fixed z-50 px-3 py-2 rounded-md text-xs whitespace-normal pointer-events-none space-y-1"
style={{
backgroundColor: "#171717",
color: "#ffffff",
width: "260px",
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
top: costTooltipPos.top,
left: costTooltipPos.left,
transform: "translateY(-100%)",
}}
>
{job.cost.response && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>
Response generation
</span>
<span>{formatCostUSD(job.cost.response.cost_usd)}</span>
</div>
)}
{job.cost.embedding && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>
Cosine similarity calculation
</span>
<span>
{formatCostUSD(job.cost.embedding.cost_usd)}
</span>
</div>
)}
</div>
)}
<button
type="button"
aria-label="Show cost breakdown"
aria-expanded={isCostTooltipOpen}
aria-describedby={`cost-tooltip-${job.id}`}
className="inline-flex items-center justify-center w-4 h-4 rounded-full text-xs font-normal cursor-help"
style={{
backgroundColor: isCostTooltipOpen ? "#171717" : "#fafafa",
color: isCostTooltipOpen ? "#ffffff" : "#737373",
}}
onMouseEnter={(e) => {
const rect = e.currentTarget.getBoundingClientRect();
const tooltipWidth = 280;
const centerX = rect.left + rect.width / 2;
const clampedLeft = Math.min(
Math.max(centerX - tooltipWidth / 2, 8),
window.innerWidth - tooltipWidth - 8,
);
setCostTooltipPos({
top: rect.top - 8,
left: clampedLeft,
});
setIsCostTooltipOpen(true);
}}
onMouseLeave={() => setIsCostTooltipOpen(false)}
onFocus={(e) => {
const rect = e.currentTarget.getBoundingClientRect();
const tooltipWidth = 280;
const centerX = rect.left + rect.width / 2;
const clampedLeft = Math.min(
Math.max(centerX - tooltipWidth / 2, 8),
window.innerWidth - tooltipWidth - 8,
);
setCostTooltipPos({ top: rect.top - 8, left: clampedLeft });
setIsCostTooltipOpen(true);
}}
onBlur={() => setIsCostTooltipOpen(false)}
onClick={() => setIsCostTooltipOpen((prev) => !prev)}
>
i
</button>
{isCostTooltipOpen && (
<div
id={`cost-tooltip-${job.id}`}
role="tooltip"
className="fixed z-50 px-3 py-2 rounded-md text-xs whitespace-normal pointer-events-none space-y-1"
style={{
backgroundColor: "#171717",
color: "#ffffff",
width: "260px",
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
top: costTooltipPos.top,
left: costTooltipPos.left,
transform: "translateY(-100%)",
}}
>
{job.cost.response && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>
Response generation
</span>
<span>{formatCostUSD(job.cost.response.cost_usd)}</span>
</div>
)}
{job.cost.embedding && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>
Cosine similarity calculation
</span>
<span>
{formatCostUSD(job.cost.embedding.cost_usd)}
</span>
</div>
)}
</div>
)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/evaluations/EvalRunCard.tsx` around lines 141 - 197, The
tooltip trigger is a plain div with only mouse handlers; make it keyboard and
touch accessible by replacing or enhancing the trigger element (the current
inline div that references isCostTooltipOpen, setIsCostTooltipOpen,
costTooltipPos, setCostTooltipPos) so it is focusable and operable: add
role="button" or use a real <button>, include tabIndex,
aria-label/aria-describedby (pointing to the tooltip container) and
aria-expanded tied to isCostTooltipOpen, add onFocus/onBlur handlers that mirror
onMouseEnter/onMouseLeave to set costTooltipPos and open/close, implement
onKeyDown to open on Enter/Space and close on Escape, and add onClick to support
touch toggling; ensure the tooltip container is referenced by id for
accessibility and retains pointer-events: none only if you still need it
visually but allow screen readers to access its contents.

Comment on lines +165 to +195
{isCostTooltipOpen && (
<div
className="fixed z-50 px-3 py-2 rounded-md text-xs whitespace-normal pointer-events-none space-y-1"
style={{
backgroundColor: "#171717",
color: "#ffffff",
width: "260px",
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
top: costTooltipPos.top,
left: costTooltipPos.left,
transform: "translateY(-100%)",
}}
>
{job.cost.response && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>
Response generation
</span>
<span>{formatCostUSD(job.cost.response.cost_usd)}</span>
</div>
)}
{job.cost.embedding && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>
Cosine similarity calculation
</span>
<span>
{formatCostUSD(job.cost.embedding.cost_usd)}
</span>
</div>
)}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Tooltip can render blank when no breakdown entries are present.

Lines 178-195 only render response/embedding. Since these fields are optional in EvalCost, users can get an empty tooltip even when total cost is shown.

Proposed fallback row
                 {isCostTooltipOpen && (
                   <div
                     className="fixed z-50 px-3 py-2 rounded-md text-xs whitespace-normal pointer-events-none space-y-1"
                     style={{
                       backgroundColor: "#171717",
                       color: "#ffffff",
                       width: "260px",
                       boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
                       top: costTooltipPos.top,
                       left: costTooltipPos.left,
                       transform: "translateY(-100%)",
                     }}
                   >
+                    {!job.cost.response && !job.cost.embedding && (
+                      <div className="flex justify-between gap-3">
+                        <span style={{ color: "#a3a3a3" }}>Total</span>
+                        <span>{formatCostUSD(job.cost.total_cost_usd)}</span>
+                      </div>
+                    )}
                     {job.cost.response && (
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{isCostTooltipOpen && (
<div
className="fixed z-50 px-3 py-2 rounded-md text-xs whitespace-normal pointer-events-none space-y-1"
style={{
backgroundColor: "#171717",
color: "#ffffff",
width: "260px",
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
top: costTooltipPos.top,
left: costTooltipPos.left,
transform: "translateY(-100%)",
}}
>
{job.cost.response && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>
Response generation
</span>
<span>{formatCostUSD(job.cost.response.cost_usd)}</span>
</div>
)}
{job.cost.embedding && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>
Cosine similarity calculation
</span>
<span>
{formatCostUSD(job.cost.embedding.cost_usd)}
</span>
</div>
)}
{isCostTooltipOpen && (
<div
className="fixed z-50 px-3 py-2 rounded-md text-xs whitespace-normal pointer-events-none space-y-1"
style={{
backgroundColor: "#171717",
color: "#ffffff",
width: "260px",
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
top: costTooltipPos.top,
left: costTooltipPos.left,
transform: "translateY(-100%)",
}}
>
{!job.cost.response && !job.cost.embedding && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>Total</span>
<span>{formatCostUSD(job.cost.total_cost_usd)}</span>
</div>
)}
{job.cost.response && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>
Response generation
</span>
<span>{formatCostUSD(job.cost.response.cost_usd)}</span>
</div>
)}
{job.cost.embedding && (
<div className="flex justify-between gap-3">
<span style={{ color: "#a3a3a3" }}>
Cosine similarity calculation
</span>
<span>
{formatCostUSD(job.cost.embedding.cost_usd)}
</span>
</div>
)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/components/evaluations/EvalRunCard.tsx` around lines 165 - 195, The
tooltip can end up empty because it only renders job.cost.response and
job.cost.embedding; update the EvalRunCard tooltip rendering to include a
fallback row when neither response nor embedding exist: inside the
isCostTooltipOpen block (where costTooltipPos and formatCostUSD are used) add a
default line that displays a descriptive label like "Total cost" and formats
job.cost.total (or job.cost.cost_usd / computed total) so the tooltip always
shows at least the aggregate cost when EvalCost lacks response/embedding
entries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant