fix(ui): label session rows by their destination

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
jesus 2026-10-11 00:13:34 +00:00
parent 7b0d90bd8c
commit 4bcf77e54e
6 changed files with 88 additions and 4 deletions

View file

@ -558,6 +558,22 @@ describe("RequestLogsPanel", () => {
expect(urlParams().get("log_id")).toBe("req-keyboard");
});
it("opens a multi-request session from its focused row and exposes its accessible name", async () => {
const user = userEvent.setup();
respondWith([
logEntry({ request_id: "req-session-keyboard", session_id: "sess-keyboard", session_total_count: 3 }),
]);
renderPanel();
const sessionRow = await screen.findByRole("row", { name: "Open session sess-keyboard" });
sessionRow.focus();
expect(sessionRow).toHaveFocus();
await user.keyboard("{Enter}");
await waitFor(() => expect(drawer()).toHaveAttribute("data-session-id", "sess-keyboard"));
expect(urlParams().get("log_id")).toBe("req-session-keyboard");
});
it("opens the drawer on load when ?log_id= matches a log in the loaded page", async () => {
respondWith([logEntry({ request_id: "req-1" }), logEntry({ request_id: "req-2" })]);
renderPanel("?log_id=req-2");

View file

@ -22,7 +22,7 @@ import {
type PaginatedResponse,
useLogFilterLogic,
} from "./useLogFilterLogic";
import { useLogDetailRouting } from "./logDetailRouting";
import { isMultiRequestSession, useLogDetailRouting } from "./logDetailRouting";
import { LogDetailsDrawer } from "../detail";
import {
defaultLogsTimeRange,
@ -253,7 +253,7 @@ export default function RequestLogsPanel({ accessToken, token, userRole, userID,
const handleRowClick = useCallback(
(log: LogEntry) => {
setSelectedLog(log);
if (log.session_id && (log.session_total_count || 1) > 1) {
if (isMultiRequestSession(log) && log.session_id) {
openSession(log.session_id, log.request_id);
} else {
openLog(log.request_id);

View file

@ -13,6 +13,7 @@ import { CREDENTIAL_LABELS, SPAN_TYPE_LABELS } from "../constants";
import { LOG_FILTER_IDS, LOG_FILTER_LABELS, type LogsWindow } from "./useLogFilterLogic";
import { RequestLogsFilters } from "./RequestLogsFilters";
import { getRequestLogsTableColumns } from "./RequestLogsTableColumns";
import { requestLogRowLabel } from "./logDetailRouting";
interface RequestLogsTableProps {
data: LogEntry[];
@ -116,7 +117,7 @@ export function RequestLogsTable({
noDataMessage={<RequestLogsEmptyState filtered={isFiltered} />}
size="compact"
onRowClick={onRowClick}
getRowLabel={(row) => `Open request ${row.request_id}`}
getRowLabel={requestLogRowLabel}
toolbar={(table) => (
<>
<DataTableToolbar

View file

@ -6,6 +6,7 @@ import { DataTable } from "@/components/shared/DataTable";
import type { LogEntry } from "../types";
import { getRequestLogsTableColumns } from "./RequestLogsTableColumns";
import { requestLogRowLabel } from "./logDetailRouting";
const { copyToClipboardMock } = vi.hoisted(() => ({ copyToClipboardMock: vi.fn() }));
@ -303,7 +304,7 @@ describe("Request ID column", () => {
getRowId={(row) => row.request_id}
size="compact"
onRowClick={onRowClick}
getRowLabel={(row) => `Open request ${row.request_id}`}
getRowLabel={requestLogRowLabel}
/>,
);

View file

@ -0,0 +1,53 @@
import { describe, expect, it } from "vitest";
import type { LogEntry } from "../types";
import { isMultiRequestSession, requestLogRowLabel } from "./logDetailRouting";
const logEntry = (overrides: Partial<LogEntry> = {}): LogEntry => ({
request_id: "r1",
api_key: "key-1",
team_id: "team-1",
model: "gpt-4o",
model_id: "model-1",
call_type: "acompletion",
spend: 0,
total_tokens: 0,
prompt_tokens: 0,
completion_tokens: 0,
startTime: "2026-07-07T09:50:13Z",
endTime: "2026-07-07T09:50:14Z",
cache_hit: "false",
messages: [],
response: {},
...overrides,
});
describe("Request Logs row labels", () => {
it("labels a multi-request session by its session id", () => {
const log = logEntry({ session_id: "s1", session_total_count: 3 });
expect(isMultiRequestSession(log)).toBe(true);
expect(requestLogRowLabel(log)).toBe("Open session s1");
});
it("labels a single-request session by its request id", () => {
const log = logEntry({ session_id: "s1", session_total_count: 1 });
expect(isMultiRequestSession(log)).toBe(false);
expect(requestLogRowLabel(log)).toBe("Open request r1");
});
it("labels a request without a session by its request id", () => {
const log = logEntry({ session_total_count: 3 });
expect(isMultiRequestSession(log)).toBe(false);
expect(requestLogRowLabel(log)).toBe("Open request r1");
});
it("defaults an undefined session count to a request label", () => {
const log = logEntry({ request_id: "", session_id: "s1", session_total_count: undefined });
expect(isMultiRequestSession(log)).toBe(false);
expect(requestLogRowLabel(log)).toBe("Open request");
});
});

View file

@ -1,9 +1,22 @@
import { parseAsString, useQueryStates } from "nuqs";
import { useCallback } from "react";
import type { LogEntry } from "../types";
export const LOG_ID_QUERY_PARAM = "log_id";
export const SESSION_ID_QUERY_PARAM = "session_id";
export function isMultiRequestSession(log: LogEntry): boolean {
return Boolean(log.session_id) && (log.session_total_count || 1) > 1;
}
export function requestLogRowLabel(log: LogEntry): string {
if (isMultiRequestSession(log)) {
return `Open session ${log.session_id}`;
}
return log.request_id ? `Open request ${log.request_id}` : "Open request";
}
export interface LogDetailRouting {
logId: string | null;
sessionId: string | null;