1- import React , { useState , useCallback , memo } from "react"
1+ import React , { useState , useCallback , memo , useMemo } from "react"
22import { useTranslation } from "react-i18next"
33import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
44import { BookOpenText , MessageCircleWarning , Info , Copy , Check } from "lucide-react"
@@ -7,6 +7,8 @@ import { vscode } from "@src/utils/vscode"
77import CodeBlock from "../common/CodeBlock"
88import { Dialog , DialogContent , DialogHeader , DialogTitle , DialogFooter } from "@src/components/ui/dialog"
99import { Button , Tooltip , TooltipContent , TooltipTrigger } from "../ui"
10+ import { useExtensionState } from "@src/context/ExtensionStateContext"
11+ import { useSelectedModel } from "@src/components/ui/hooks/useSelectedModel"
1012
1113/**
1214 * Unified error display component for all error types in the chat.
@@ -91,6 +93,24 @@ export const ErrorRow = memo(
9193 const [ isDetailsDialogOpen , setIsDetailsDialogOpen ] = useState ( false )
9294 const [ showDetailsCopySuccess , setShowDetailsCopySuccess ] = useState ( false )
9395 const { copyWithFeedback } = useCopyToClipboard ( )
96+ const { version, apiConfiguration } = useExtensionState ( )
97+ const { provider, id : modelId } = useSelectedModel ( apiConfiguration )
98+
99+ // Format error details with metadata prepended
100+ const formattedErrorDetails = useMemo ( ( ) => {
101+ if ( ! errorDetails ) return undefined
102+
103+ const metadata = [
104+ `Date/time: ${ new Date ( ) . toISOString ( ) } ` ,
105+ `Extension version: ${ version } ` ,
106+ `Provider: ${ provider } ` ,
107+ `Model: ${ modelId } ` ,
108+ "" ,
109+ "" ,
110+ ] . join ( "\n" )
111+
112+ return metadata + errorDetails
113+ } , [ errorDetails , version , provider , modelId ] )
94114
95115 // Default titles for different error types
96116 const getDefaultTitle = ( ) => {
@@ -139,8 +159,8 @@ export const ErrorRow = memo(
139159 const handleCopyDetails = useCallback (
140160 async ( e : React . MouseEvent ) => {
141161 e . stopPropagation ( )
142- if ( errorDetails ) {
143- const success = await copyWithFeedback ( errorDetails )
162+ if ( formattedErrorDetails ) {
163+ const success = await copyWithFeedback ( formattedErrorDetails )
144164 if ( success ) {
145165 setShowDetailsCopySuccess ( true )
146166 setTimeout ( ( ) => {
@@ -149,7 +169,7 @@ export const ErrorRow = memo(
149169 }
150170 }
151171 } ,
152- [ errorDetails , copyWithFeedback ] ,
172+ [ formattedErrorDetails , copyWithFeedback ] ,
153173 )
154174
155175 const errorTitle = getDefaultTitle ( )
@@ -209,12 +229,12 @@ export const ErrorRow = memo(
209229 { t ( "chat:apiRequest.errorMessage.docs" ) }
210230 </ a >
211231 ) }
212- { errorDetails && (
232+ { formattedErrorDetails && (
213233 < Tooltip >
214234 < TooltipTrigger asChild >
215235 < button
216236 onClick = { ( ) => setIsDetailsDialogOpen ( true ) }
217- className = "transition-opacity opacity-0 group-hover:opacity-100 cursor-pointer"
237+ className = "transition-opacity opacity-30 group-hover:opacity-100 cursor-pointer"
218238 aria-label = { t ( "chat:errorDetails.title" ) } >
219239 < Info className = "size-4" />
220240 </ button >
@@ -238,15 +258,15 @@ export const ErrorRow = memo(
238258 </ div >
239259
240260 { /* Error Details Dialog */ }
241- { errorDetails && (
261+ { formattedErrorDetails && (
242262 < Dialog open = { isDetailsDialogOpen } onOpenChange = { setIsDetailsDialogOpen } >
243263 < DialogContent className = "max-w-2xl" >
244264 < DialogHeader >
245265 < DialogTitle > { t ( "chat:errorDetails.title" ) } </ DialogTitle >
246266 </ DialogHeader >
247267 < div className = "max-h-96 overflow-auto px-3 bg-vscode-editor-background rounded-xl border border-vscode-editorGroup-border" >
248268 < pre className = "font-mono text-sm whitespace-pre-wrap break-words bg-transparent" >
249- { errorDetails }
269+ { formattedErrorDetails }
250270 </ pre >
251271 </ div >
252272 < DialogFooter >
0 commit comments