|
@@ -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>
|