diff --git a/site/src/pages/AIBridgePage/RequestLogsPage/RequestLogsRow/RequestLogsRow.tsx b/site/src/pages/AIBridgePage/RequestLogsPage/RequestLogsRow/RequestLogsRow.tsx index 129c2f0402711..cbb338ab40fb1 100644 --- a/site/src/pages/AIBridgePage/RequestLogsPage/RequestLogsRow/RequestLogsRow.tsx +++ b/site/src/pages/AIBridgePage/RequestLogsPage/RequestLogsRow/RequestLogsRow.tsx @@ -1,4 +1,7 @@ -import type { AIBridgeInterception } from "api/typesGenerated"; +import type { + AIBridgeInterception, + AIBridgeUserPrompt, +} from "api/typesGenerated"; import { Avatar } from "components/Avatar/Avatar"; import { Badge } from "components/Badge/Badge"; import { TableCell, TableRow } from "components/Table/Table"; @@ -13,8 +16,9 @@ import { ArrowUpIcon, ChevronDownIcon, ChevronRightIcon, + ChevronUpIcon, } from "lucide-react"; -import { type FC, Fragment, useState } from "react"; +import { type FC, useLayoutEffect, useRef, useState } from "react"; import { cn } from "utils/cn"; import { humanDuration } from "utils/time"; import { AIBridgeProviderIcon } from "../AIBridgeProviderIcon"; @@ -114,6 +118,62 @@ export function tokenUsageMetadataMerge( : result; } +const RequestLogsPrompt: FC<{ prompt: AIBridgeUserPrompt }> = ({ prompt }) => { + const [isOpen, setIsOpen] = useState(false); + const [canCollapse, setCanCollapse] = useState(false); + + const promptRef = useRef(null); + useLayoutEffect(() => { + const promptEl = promptRef.current; + if (!promptEl || isOpen) { + // If the prompt is open or the prompt element is not found, return. + return; + } + + const updateContentSize = () => + setCanCollapse(promptEl.scrollHeight > promptEl.clientHeight); + updateContentSize(); + + const ro = new ResizeObserver(updateContentSize); + ro.observe(promptEl); + return () => { + ro.disconnect(); + }; + }, [isOpen]); + + return ( +
+
+ {prompt.prompt} +
+ {canCollapse && ( +
+ +
+ )} +
+ ); +}; + export const RequestLogsRow: FC = ({ interception }) => { const [isOpen, setIsOpen] = useState(false); @@ -370,21 +430,16 @@ export const RequestLogsRow: FC = ({ interception }) => { {interception.user_prompts.length > 0 && ( -
+
Prompts
-
- {interception.user_prompts.map((prompt) => ( - {prompt.prompt} - ))} -
+ {interception.user_prompts.map((prompt) => ( + + ))}
)} {interception.tool_usages.length > 0 && ( -
+
Tool Usages
= ({ interception }) => { )} {tokenUsagesMetadata !== null && ( -
+
Token Usage Metadata
{JSON.stringify(tokenUsagesMetadata, null, 2)}