Skip to content
16 changes: 11 additions & 5 deletions app/api/evaluations/stt/datasets/[dataset_id]/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NextResponse, NextRequest } from 'next/server';
import { NextResponse } from 'next/server';

export async function GET(
request: Request,
Expand All @@ -8,6 +8,13 @@ export async function GET(
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');

if (!apiKey) {
return NextResponse.json(
{ success: false, error: 'Unauthorized: Missing API key', data: null },
{ status: 401 }
);
}

try {
// Get query parameters from the request
const { searchParams } = new URL(request.url);
Expand All @@ -19,13 +26,12 @@ export async function GET(
if (includeSamples) backendParams.append('include_samples', includeSamples);
if (includeAudio) backendParams.append('include_audio', includeAudio);

const backendUrlWithParams = `${backendUrl}/api/v1/evaluations/stt/datasets/${dataset_id}${
backendParams.toString() ? `?${backendParams.toString()}` : ''
}`;
const backendUrlWithParams = `${backendUrl}/api/v1/evaluations/stt/datasets/${dataset_id}${backendParams.toString() ? `?${backendParams.toString()}` : ''
}`;

const response = await fetch(backendUrlWithParams, {
headers: {
'X-API-KEY': apiKey || '',
'X-API-KEY': apiKey,
},
});

Expand Down
33 changes: 33 additions & 0 deletions app/api/evaluations/tts/datasets/[dataset_id]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { NextResponse } from 'next/server';

export async function GET(
request: Request,
{ params }: { params: Promise<{ dataset_id: string }> }
) {
const { dataset_id } = await params;
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');

if (!apiKey) {
return NextResponse.json(
{ success: false, error: 'Unauthorized: Missing API key', data: null },
{ status: 401 }
);
}

try {
const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/datasets/${dataset_id}`, {
headers: {
'X-API-KEY': apiKey,
},
});

const data = await response.json();
return NextResponse.json(data, { status: response.status });
} catch (error) {
return NextResponse.json(
{ success: false, error: 'Failed to fetch dataset', data: null },
{ status: 500 }
);
}
}
53 changes: 53 additions & 0 deletions app/api/evaluations/tts/datasets/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { NextResponse, NextRequest } from 'next/server';

export async function GET(request: Request) {
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');

try {
const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/datasets`, {
headers: {
'X-API-KEY': apiKey || '',
},
});

const data = await response.json();
return NextResponse.json(data, { status: response.status });
Comment on lines +3 to +15
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Reject unauthenticated dataset-list GETs here too.

POST in this file and GET in app/api/evaluations/tts/datasets/[dataset_id]/route.ts already return 401 when X-API-KEY is missing, but this handler still proxies X-API-KEY: '' to the backend. That makes the auth contract inconsistent and turns a local 401 into an extra backend call whose behavior now depends on backend header parsing.

🔐 Suggested fix
 export async function GET(request: Request) {
   const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
   const apiKey = request.headers.get('X-API-KEY');
+
+  if (!apiKey) {
+    return NextResponse.json(
+      { success: false, error: 'Unauthorized: Missing API key', data: null },
+      { status: 401 }
+    );
+  }

   try {
     const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/datasets`, {
       headers: {
-        'X-API-KEY': apiKey || '',
+        'X-API-KEY': apiKey,
       },
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/evaluations/tts/datasets/route.ts` around lines 3 - 15, The GET
handler in this route proxies an empty X-API-KEY to the backend instead of
rejecting unauthenticated requests; update the GET function to check
request.headers.get('X-API-KEY') (same as POST and the other GET in
evaluations/tts/datasets/[dataset_id]/route.ts) and return a 401 NextResponse
when apiKey is missing or falsy, avoiding the backend fetch; only perform the
fetch when apiKey is present and include the header value in the proxied
request.

} catch (error) {
return NextResponse.json(
{ success: false, error: error, data: null },
{ status: 500 }
);
}
}

export async function POST(request: NextRequest) {
try {
const apiKey = request.headers.get('X-API-KEY');
if (!apiKey) {
return NextResponse.json(
{ error: 'Missing X-API-KEY. Either generate an API Key. Contact Kaapi team for more details' },
{ status: 401 }
);
}
const body = await request.json();
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';

const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/datasets`, {
method: 'POST',
body: JSON.stringify(body),
headers: {
'X-API-KEY': apiKey,
'Content-Type': 'application/json',
},
});
const data = await response.json();
return NextResponse.json(data, { status: response.status });
} catch (error) {
console.error('Proxy error:', error);
return NextResponse.json(
{ error: 'Failed to forward request to backend', details: error instanceof Error ? error.message : String(error) },
{ status: 500 }
);
}
}
63 changes: 63 additions & 0 deletions app/api/evaluations/tts/results/[result_id]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { NextResponse } from 'next/server';

export async function GET(
request: Request,
{ params }: { params: Promise<{ result_id: string }> }
) {
const { result_id } = await params;
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');

try {
const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/results/${result_id}`, {
headers: {
'X-API-KEY': apiKey || '',
},
});

const data = await response.json();
return NextResponse.json(data, { status: response.status });
Comment on lines +3 to +19
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fail fast on missing API keys for result GETs as well.

PATCH already rejects missing X-API-KEY, but GET still forwards an empty value to the backend. Keeping both methods consistent here avoids anonymous proxy calls and gives the client a stable 401 response shape.

🔐 Suggested fix
 export async function GET(
   request: Request,
   { params }: { params: Promise<{ result_id: string }> }
 ) {
   const { result_id } = await params;
   const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
   const apiKey = request.headers.get('X-API-KEY');
+
+  if (!apiKey) {
+    return NextResponse.json(
+      { success: false, error: 'Unauthorized: Missing API key', data: null },
+      { status: 401 }
+    );
+  }

   try {
     const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/results/${result_id}`, {
       headers: {
-        'X-API-KEY': apiKey || '',
+        'X-API-KEY': apiKey,
       },
     });
📝 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
export async function GET(
request: Request,
{ params }: { params: Promise<{ result_id: string }> }
) {
const { result_id } = await params;
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');
try {
const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/results/${result_id}`, {
headers: {
'X-API-KEY': apiKey || '',
},
});
const data = await response.json();
return NextResponse.json(data, { status: response.status });
export async function GET(
request: Request,
{ params }: { params: Promise<{ result_id: string }> }
) {
const { result_id } = await params;
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');
if (!apiKey) {
return NextResponse.json(
{ success: false, error: 'Unauthorized: Missing API key', data: null },
{ status: 401 }
);
}
try {
const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/results/${result_id}`, {
headers: {
'X-API-KEY': apiKey,
},
});
const data = await response.json();
return NextResponse.json(data, { status: response.status });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/evaluations/tts/results/`[result_id]/route.ts around lines 3 - 19,
The GET handler in route.ts currently reads X-API-KEY into the apiKey variable
and forwards an empty string to the backend; update the GET function to fail
fast like PATCH by checking request.headers.get('X-API-KEY') (the apiKey
variable) and if missing return a 401 NextResponse with a JSON error body
immediately, avoiding forwarding empty keys to the backend and keeping GET and
PATCH response shapes consistent.

} catch (error) {
return NextResponse.json(
{ success: false, error: 'Failed to fetch results', data: null },
{ status: 500 }
);
}
}

export async function PATCH(
request: Request,
{ params }: { params: Promise<{ result_id: string }> }
) {
const { result_id } = await params;
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');

if (!apiKey) {
return NextResponse.json(
{ error: 'Missing X-API-KEY header' },
{ status: 401 }
);
}

try {
const body = await request.json();

const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/results/${result_id}`, {
method: 'PATCH',
headers: {
'X-API-KEY': apiKey || '',
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});

const data = await response.json();
return NextResponse.json(data, { status: response.status });
} catch (error) {
return NextResponse.json(
{ success: false, error: 'Failed to update result feedback', data: null },
{ status: 500 }
);
}
}
33 changes: 33 additions & 0 deletions app/api/evaluations/tts/runs/[run_id]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { NextResponse } from 'next/server';

export async function GET(
request: Request,
{ params }: { params: Promise<{ run_id: string }> }
) {
const { run_id } = await params;
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');

const { searchParams } = new URL(request.url);
const queryString = searchParams.toString();

try {
const backendUrlWithParams = queryString
? `${backendUrl}/api/v1/evaluations/tts/runs/${run_id}?${queryString}`
: `${backendUrl}/api/v1/evaluations/tts/runs/${run_id}`;

const response = await fetch(backendUrlWithParams, {
headers: {
'X-API-KEY': apiKey || '',
},
});
Comment on lines +8 to +23
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Return 401 before proxying unauthenticated run lookups.

This handler currently forwards X-API-KEY: '' when the header is absent, while the dataset-detail proxy already fails fast locally. The mismatch makes GET auth behavior inconsistent across the TTS routes and adds needless backend traffic for anonymous requests.

🔐 Suggested fix
   const { run_id } = await params;
   const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
   const apiKey = request.headers.get('X-API-KEY');
+
+  if (!apiKey) {
+    return NextResponse.json(
+      { success: false, error: 'Unauthorized: Missing API key', data: null },
+      { status: 401 }
+    );
+  }

   const { searchParams } = new URL(request.url);
   const queryString = searchParams.toString();
@@
     const response = await fetch(backendUrlWithParams, {
       headers: {
-        'X-API-KEY': apiKey || '',
+        'X-API-KEY': apiKey,
       },
     });
📝 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
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');
const { searchParams } = new URL(request.url);
const queryString = searchParams.toString();
try {
const backendUrlWithParams = queryString
? `${backendUrl}/api/v1/evaluations/tts/runs/${run_id}?${queryString}`
: `${backendUrl}/api/v1/evaluations/tts/runs/${run_id}`;
const response = await fetch(backendUrlWithParams, {
headers: {
'X-API-KEY': apiKey || '',
},
});
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');
if (!apiKey) {
return NextResponse.json(
{ success: false, error: 'Unauthorized: Missing API key', data: null },
{ status: 401 }
);
}
const { searchParams } = new URL(request.url);
const queryString = searchParams.toString();
try {
const backendUrlWithParams = queryString
? `${backendUrl}/api/v1/evaluations/tts/runs/${run_id}?${queryString}`
: `${backendUrl}/api/v1/evaluations/tts/runs/${run_id}`;
const response = await fetch(backendUrlWithParams, {
headers: {
'X-API-KEY': apiKey,
},
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/evaluations/tts/runs/`[run_id]/route.ts around lines 8 - 23, The
handler currently reads apiKey via request.headers.get('X-API-KEY') and forwards
an empty string to backend; instead, in the route handler (before building
backendUrlWithParams and calling fetch) check if apiKey is falsy and immediately
return a 401 Unauthorized response; update the logic around apiKey and the fetch
call (symbols: apiKey, request.headers.get, backendUrlWithParams, fetch) so
unauthenticated requests short-circuit locally rather than proxying to the
backend.


const data = await response.json();
return NextResponse.json(data, { status: response.status });
} catch (error) {
return NextResponse.json(
{ success: false, error: 'Failed to fetch the run', data: null },
{ status: 500 }
);
}
}
53 changes: 53 additions & 0 deletions app/api/evaluations/tts/runs/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { NextResponse, NextRequest } from 'next/server';

export async function GET(request: Request) {
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');

try {
const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/runs`, {
headers: {
'X-API-KEY': apiKey || '',
},
});

const data = await response.json();
return NextResponse.json(data, { status: response.status });
Comment on lines +3 to +15
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Mirror the POST auth guard on the runs GET endpoint.

Right now the list GET proxies X-API-KEY: '' instead of returning 401 like POST does. That makes callers depend on backend behavior for a missing key and weakens the proxy’s own auth boundary.

🔐 Suggested fix
 export async function GET(request: Request) {
   const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
   const apiKey = request.headers.get('X-API-KEY');
+
+  if (!apiKey) {
+    return NextResponse.json(
+      { success: false, error: 'Unauthorized: Missing API key', data: null },
+      { status: 401 }
+    );
+  }

   try {
     const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/runs`, {
       headers: {
-        'X-API-KEY': apiKey || '',
+        'X-API-KEY': apiKey,
       },
     });
📝 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
export async function GET(request: Request) {
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');
try {
const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/runs`, {
headers: {
'X-API-KEY': apiKey || '',
},
});
const data = await response.json();
return NextResponse.json(data, { status: response.status });
export async function GET(request: Request) {
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';
const apiKey = request.headers.get('X-API-KEY');
if (!apiKey) {
return NextResponse.json(
{ success: false, error: 'Unauthorized: Missing API key', data: null },
{ status: 401 }
);
}
try {
const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/runs`, {
headers: {
'X-API-KEY': apiKey,
},
});
const data = await response.json();
return NextResponse.json(data, { status: response.status });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/api/evaluations/tts/runs/route.ts` around lines 3 - 15, The GET handler
currently forwards an empty X-API-KEY header instead of enforcing the same auth
guard as the POST; update the GET function to read apiKey via
request.headers.get('X-API-KEY') and if it's missing/empty return a 401
NextResponse (mirroring the POST behavior) before calling fetch; only when
apiKey is present should you call
fetch(`${backendUrl}/api/v1/evaluations/tts/runs`, { headers: { 'X-API-KEY':
apiKey } }) and return NextResponse.json with the upstream response.

} catch (error) {
return NextResponse.json(
{ success: false, error: error, data: null },
{ status: 500 }
);
}
}

export async function POST(request: NextRequest) {
try {
const apiKey = request.headers.get('X-API-KEY');
if (!apiKey) {
return NextResponse.json(
{ error: 'Missing X-API-KEY. Either generate an API Key. Contact Kaapi team for more details' },
{ status: 401 }
);
}
const body = await request.json();
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:8000';

const response = await fetch(`${backendUrl}/api/v1/evaluations/tts/runs`, {
method: 'POST',
body: JSON.stringify(body),
headers: {
'X-API-KEY': apiKey,
'Content-Type': 'application/json',
},
});
const data = await response.json();
return NextResponse.json(data, { status: response.status });
} catch (error) {
console.error('Proxy error:', error);
return NextResponse.json(
{ error: 'Failed to forward request to backend', details: error instanceof Error ? error.message : String(error) },
{ status: 500 }
);
}
}
30 changes: 15 additions & 15 deletions app/components/DetailedResultsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,10 @@ export default function DetailedResultsTable({ job }: DetailedResultsTableProps)
Question
</th>
<th className="px-4 py-3 text-left text-xs font-semibold uppercase" style={{ color: '#171717', width: '25%' }}>
Answer
Ground Truth
</th>
<th className="px-4 py-3 text-left text-xs font-semibold uppercase" style={{ color: '#171717', width: '25%' }}>
Ground Truth
Answer
Comment on lines 120 to +124
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Keep the individual table and CSV column order aligned.

This reorders the row view to Question → Ground Truth → Answer, but the individual export in app/evaluations/[id]/page.tsx, Lines 283-300, still writes Question,Answer,Ground Truth. That mismatch makes it easy to misread columns when users compare the UI with the downloaded CSV. Please update both surfaces together or keep the existing order here.

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

In `@app/components/DetailedResultsTable.tsx` around lines 120 - 124, The table
header order in DetailedResultsTable.tsx was changed to "Question → Ground Truth
→ Answer" but the CSV export in app/evaluations/[id]/page.tsx still writes rows
as "Question,Answer,Ground Truth", causing a mismatch; update the CSV row
generation in that page.tsx (the code that builds/writes the CSV rows where you
currently emit "Question,Answer, Ground Truth") to emit columns in the same
order as the UI: "Question,Ground Truth,Answer" (or alternatively revert the
DetailedResultsTable header to the original order) so both the table display and
the individual CSV export match exactly.

</th>
{scoreNames.map((scoreName) => (
<th key={scoreName} className="px-4 py-3 text-center text-xs font-semibold uppercase" style={{ color: '#171717', width: `${20 / scoreNames.length}%` }}>
Expand Down Expand Up @@ -153,12 +153,12 @@ export default function DetailedResultsTable({ job }: DetailedResultsTableProps)
}}
>
{/* Row Number */}
<td className="px-4 py-3 text-sm font-medium" style={{ color: '#737373' }}>
<td className="px-4 py-3 text-sm font-medium align-top" style={{ color: '#737373' }}>
{index + 1}
</td>

{/* Question */}
<td className="px-4 py-3">
<td className="px-4 py-3 align-top" style={{ backgroundColor: '#fafafa' }}>
<div
className="text-sm overflow-auto"
style={{
Expand All @@ -171,8 +171,8 @@ export default function DetailedResultsTable({ job }: DetailedResultsTableProps)
</div>
</td>

{/* Answer */}
<td className="px-4 py-3">
{/* Ground Truth */}
<td className="px-4 py-3 align-top" style={{ backgroundColor: '#fafafa' }}>
<div
className="text-sm overflow-auto"
style={{
Expand All @@ -181,12 +181,12 @@ export default function DetailedResultsTable({ job }: DetailedResultsTableProps)
maxHeight: '150px'
}}
>
{answer}
{groundTruth}
</div>
</td>

{/* Ground Truth */}
<td className="px-4 py-3">
{/* Answer */}
<td className="px-4 py-3 align-top">
<div
className="text-sm overflow-auto"
style={{
Expand All @@ -195,7 +195,7 @@ export default function DetailedResultsTable({ job }: DetailedResultsTableProps)
maxHeight: '150px'
}}
>
{groundTruth}
{answer}
</div>
</td>

Expand All @@ -205,7 +205,7 @@ export default function DetailedResultsTable({ job }: DetailedResultsTableProps)
const { value, color, bg } = formatScoreValue(score);

return (
<td key={scoreName} className="px-4 py-3 text-center">
<td key={scoreName} className="px-4 py-3 text-center align-top">
<div className="flex items-center justify-center gap-2">
<div
className="inline-block px-2 py-1 rounded text-xs font-medium"
Expand Down Expand Up @@ -404,12 +404,12 @@ function GroupedResultsTable({ traces }: { traces: GroupedTraceItem[] }) {
}}
>
{/* Question ID - matching row format # column */}
<td className="px-4 py-3 text-sm font-medium" style={{ color: '#737373' }}>
<td className="px-4 py-3 text-sm font-medium align-top" style={{ color: '#737373' }}>
{group.question_id}
</td>

{/* Question - matching row format text cell */}
<td className="px-4 py-3">
<td className="px-4 py-3 align-top" style={{ backgroundColor: '#fafafa' }}>
<div
className="text-sm overflow-auto"
style={{ color: '#171717', lineHeight: '1.5', maxHeight: '150px' }}
Expand All @@ -419,7 +419,7 @@ function GroupedResultsTable({ traces }: { traces: GroupedTraceItem[] }) {
</td>

{/* Ground Truth - matching row format text cell */}
<td className="px-4 py-3">
<td className="px-4 py-3 align-top" style={{ backgroundColor: '#fafafa' }}>
<div
className="text-sm overflow-auto"
style={{ color: '#171717', lineHeight: '1.5', maxHeight: '150px' }}
Expand All @@ -434,7 +434,7 @@ function GroupedResultsTable({ traces }: { traces: GroupedTraceItem[] }) {
const answerScores: TraceScore[] = group.scores?.[answerIndex] || [];

return (
<td key={answerIndex} className="px-4 py-3">
<td key={answerIndex} className="px-4 py-3 align-top">
{answer ? (
<div>
<div
Expand Down
2 changes: 1 addition & 1 deletion app/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default function Sidebar({ collapsed, activeRoute = '/evaluations' }: Sid
submenu: [
{ name: 'Text', route: '/evaluations' },
{ name: 'Speech-to-Text', route: '/speech-to-text' },
// { name: 'Text-to-Speech', route: '/text-to-speech', comingSoon: true },
{ name: 'Text-to-Speech', route: '/text-to-speech' },
]
},
{ name: 'Documents', route: '/document' },
Expand Down
Loading