2
0
Эх сурвалжийг харах

feat: add metadata to error details dialog (#10050)

* feat: add metadata to error details dialog

- Prepends extension version, provider, model, and repository info to error details
- Helps users provide better bug reports with context
- Uses useExtensionState and useSelectedModel hooks for data

* Tweaks

---------

Co-authored-by: Roo Code <[email protected]>
Co-authored-by: Bruno Bergher <[email protected]>
roomote[bot] 2 долоо хоног өмнө
parent
commit
5929e2686f

+ 28 - 8
webview-ui/src/components/chat/ErrorRow.tsx

@@ -1,4 +1,4 @@
-import React, { useState, useCallback, memo } from "react"
+import React, { useState, useCallback, memo, useMemo } from "react"
 import { useTranslation } from "react-i18next"
 import { useTranslation } from "react-i18next"
 import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
 import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
 import { BookOpenText, MessageCircleWarning, Info, Copy, Check } from "lucide-react"
 import { BookOpenText, MessageCircleWarning, Info, Copy, Check } from "lucide-react"
@@ -7,6 +7,8 @@ import { vscode } from "@src/utils/vscode"
 import CodeBlock from "../common/CodeBlock"
 import CodeBlock from "../common/CodeBlock"
 import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@src/components/ui/dialog"
 import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@src/components/ui/dialog"
 import { Button, Tooltip, TooltipContent, TooltipTrigger } from "../ui"
 import { Button, Tooltip, TooltipContent, TooltipTrigger } from "../ui"
+import { useExtensionState } from "@src/context/ExtensionStateContext"
+import { useSelectedModel } from "@src/components/ui/hooks/useSelectedModel"
 
 
 /**
 /**
  * Unified error display component for all error types in the chat.
  * Unified error display component for all error types in the chat.
@@ -91,6 +93,24 @@ export const ErrorRow = memo(
 		const [isDetailsDialogOpen, setIsDetailsDialogOpen] = useState(false)
 		const [isDetailsDialogOpen, setIsDetailsDialogOpen] = useState(false)
 		const [showDetailsCopySuccess, setShowDetailsCopySuccess] = useState(false)
 		const [showDetailsCopySuccess, setShowDetailsCopySuccess] = useState(false)
 		const { copyWithFeedback } = useCopyToClipboard()
 		const { copyWithFeedback } = useCopyToClipboard()
+		const { version, apiConfiguration } = useExtensionState()
+		const { provider, id: modelId } = useSelectedModel(apiConfiguration)
+
+		// Format error details with metadata prepended
+		const formattedErrorDetails = useMemo(() => {
+			if (!errorDetails) return undefined
+
+			const metadata = [
+				`Date/time: ${new Date().toISOString()}`,
+				`Extension version: ${version}`,
+				`Provider: ${provider}`,
+				`Model: ${modelId}`,
+				"",
+				"",
+			].join("\n")
+
+			return metadata + errorDetails
+		}, [errorDetails, version, provider, modelId])
 
 
 		// Default titles for different error types
 		// Default titles for different error types
 		const getDefaultTitle = () => {
 		const getDefaultTitle = () => {
@@ -139,8 +159,8 @@ export const ErrorRow = memo(
 		const handleCopyDetails = useCallback(
 		const handleCopyDetails = useCallback(
 			async (e: React.MouseEvent) => {
 			async (e: React.MouseEvent) => {
 				e.stopPropagation()
 				e.stopPropagation()
-				if (errorDetails) {
-					const success = await copyWithFeedback(errorDetails)
+				if (formattedErrorDetails) {
+					const success = await copyWithFeedback(formattedErrorDetails)
 					if (success) {
 					if (success) {
 						setShowDetailsCopySuccess(true)
 						setShowDetailsCopySuccess(true)
 						setTimeout(() => {
 						setTimeout(() => {
@@ -149,7 +169,7 @@ export const ErrorRow = memo(
 					}
 					}
 				}
 				}
 			},
 			},
-			[errorDetails, copyWithFeedback],
+			[formattedErrorDetails, copyWithFeedback],
 		)
 		)
 
 
 		const errorTitle = getDefaultTitle()
 		const errorTitle = getDefaultTitle()
@@ -209,12 +229,12 @@ export const ErrorRow = memo(
 										{t("chat:apiRequest.errorMessage.docs")}
 										{t("chat:apiRequest.errorMessage.docs")}
 									</a>
 									</a>
 								)}
 								)}
-								{errorDetails && (
+								{formattedErrorDetails && (
 									<Tooltip>
 									<Tooltip>
 										<TooltipTrigger asChild>
 										<TooltipTrigger asChild>
 											<button
 											<button
 												onClick={() => setIsDetailsDialogOpen(true)}
 												onClick={() => setIsDetailsDialogOpen(true)}
-												className="transition-opacity opacity-0 group-hover:opacity-100 cursor-pointer"
+												className="transition-opacity opacity-30 group-hover:opacity-100 cursor-pointer"
 												aria-label={t("chat:errorDetails.title")}>
 												aria-label={t("chat:errorDetails.title")}>
 												<Info className="size-4" />
 												<Info className="size-4" />
 											</button>
 											</button>
@@ -238,7 +258,7 @@ export const ErrorRow = memo(
 				</div>
 				</div>
 
 
 				{/* Error Details Dialog */}
 				{/* Error Details Dialog */}
-				{errorDetails && (
+				{formattedErrorDetails && (
 					<Dialog open={isDetailsDialogOpen} onOpenChange={setIsDetailsDialogOpen}>
 					<Dialog open={isDetailsDialogOpen} onOpenChange={setIsDetailsDialogOpen}>
 						<DialogContent className="max-w-2xl">
 						<DialogContent className="max-w-2xl">
 							<DialogHeader>
 							<DialogHeader>
@@ -246,7 +266,7 @@ export const ErrorRow = memo(
 							</DialogHeader>
 							</DialogHeader>
 							<div className="max-h-96 overflow-auto px-3 bg-vscode-editor-background rounded-xl border border-vscode-editorGroup-border">
 							<div className="max-h-96 overflow-auto px-3 bg-vscode-editor-background rounded-xl border border-vscode-editorGroup-border">
 								<pre className="font-mono text-sm whitespace-pre-wrap break-words bg-transparent">
 								<pre className="font-mono text-sm whitespace-pre-wrap break-words bg-transparent">
-									{errorDetails}
+									{formattedErrorDetails}
 								</pre>
 								</pre>
 							</div>
 							</div>
 							<DialogFooter>
 							<DialogFooter>