diff --git a/src/core/webview/__tests__/diagnosticsHandler.spec.ts b/src/core/webview/__tests__/diagnosticsHandler.spec.ts new file mode 100644 index 00000000000..27593b56bf0 --- /dev/null +++ b/src/core/webview/__tests__/diagnosticsHandler.spec.ts @@ -0,0 +1,188 @@ +// npx vitest src/core/webview/__tests__/diagnosticsHandler.spec.ts + +import * as path from "path" + +// Mock vscode first +vi.mock("vscode", () => { + const showErrorMessage = vi.fn() + const openTextDocument = vi.fn().mockResolvedValue({}) + const showTextDocument = vi.fn().mockResolvedValue(undefined) + + return { + window: { + showErrorMessage, + showTextDocument, + }, + workspace: { + openTextDocument, + }, + } +}) + +// Mock storage utilities +vi.mock("../../../utils/storage", () => ({ + getTaskDirectoryPath: vi.fn(async () => "/mock/task-dir"), +})) + +// Mock fs utilities +vi.mock("../../../utils/fs", () => ({ + fileExistsAtPath: vi.fn(), +})) + +// Mock fs/promises +vi.mock("fs/promises", () => { + const mockReadFile = vi.fn() + const mockWriteFile = vi.fn().mockResolvedValue(undefined) + + return { + default: { + readFile: mockReadFile, + writeFile: mockWriteFile, + }, + readFile: mockReadFile, + writeFile: mockWriteFile, + } +}) + +import * as vscode from "vscode" +import * as fs from "fs/promises" +import * as fsUtils from "../../../utils/fs" +import { generateErrorDiagnostics } from "../diagnosticsHandler" + +describe("generateErrorDiagnostics", () => { + const mockLog = vi.fn() + + beforeEach(() => { + vi.clearAllMocks() + }) + + it("generates a diagnostics file with error metadata and history", async () => { + vi.mocked(fsUtils.fileExistsAtPath).mockResolvedValue(true as any) + vi.mocked(fs.readFile).mockResolvedValue('[{"role": "user", "content": "test"}]' as any) + + const result = await generateErrorDiagnostics({ + taskId: "test-task-id", + globalStoragePath: "/mock/global/storage", + values: { + timestamp: "2025-01-01T00:00:00.000Z", + version: "1.2.3", + provider: "test-provider", + model: "test-model", + details: "Sample error details", + }, + log: mockLog, + }) + + expect(result.success).toBe(true) + expect(result.filePath).toContain("roo-diagnostics-") + + // Verify we attempted to read API history + expect(fs.readFile).toHaveBeenCalledWith(path.join("/mock/task-dir", "api_conversation_history.json"), "utf8") + + // Verify we wrote a diagnostics file with the expected content + expect(fs.writeFile).toHaveBeenCalledTimes(1) + const [writtenPath, writtenContent] = vi.mocked(fs.writeFile).mock.calls[0] + // taskId.slice(0, 8) = "test-tas" from "test-task-id" + expect(String(writtenPath)).toContain("roo-diagnostics-test-tas") + expect(String(writtenContent)).toContain( + "// Please share this file with Roo Code Support (support@roocode.com) to diagnose the issue faster", + ) + expect(String(writtenContent)).toContain('"error":') + expect(String(writtenContent)).toContain('"history":') + expect(String(writtenContent)).toContain('"version": "1.2.3"') + expect(String(writtenContent)).toContain('"provider": "test-provider"') + expect(String(writtenContent)).toContain('"model": "test-model"') + expect(String(writtenContent)).toContain('"details": "Sample error details"') + + // Verify VS Code APIs were used to open the generated file + expect(vscode.workspace.openTextDocument).toHaveBeenCalledTimes(1) + expect(vscode.window.showTextDocument).toHaveBeenCalledTimes(1) + }) + + it("uses empty history when API history file does not exist", async () => { + vi.mocked(fsUtils.fileExistsAtPath).mockResolvedValue(false as any) + + const result = await generateErrorDiagnostics({ + taskId: "test-task-id", + globalStoragePath: "/mock/global/storage", + values: { + timestamp: "2025-01-01T00:00:00.000Z", + version: "1.0.0", + provider: "test", + model: "test", + details: "error", + }, + log: mockLog, + }) + + expect(result.success).toBe(true) + + // Should not attempt to read file when it doesn't exist + expect(fs.readFile).not.toHaveBeenCalled() + + // Verify empty history in output + const [, writtenContent] = vi.mocked(fs.writeFile).mock.calls[0] + expect(String(writtenContent)).toContain('"history": []') + }) + + it("uses default values when values are not provided", async () => { + vi.mocked(fsUtils.fileExistsAtPath).mockResolvedValue(false as any) + + const result = await generateErrorDiagnostics({ + taskId: "test-task-id", + globalStoragePath: "/mock/global/storage", + log: mockLog, + }) + + expect(result.success).toBe(true) + + // Verify defaults in output + const [, writtenContent] = vi.mocked(fs.writeFile).mock.calls[0] + expect(String(writtenContent)).toContain('"version": ""') + expect(String(writtenContent)).toContain('"provider": ""') + expect(String(writtenContent)).toContain('"model": ""') + expect(String(writtenContent)).toContain('"details": ""') + }) + + it("handles JSON parse error gracefully", async () => { + vi.mocked(fsUtils.fileExistsAtPath).mockResolvedValue(true as any) + vi.mocked(fs.readFile).mockResolvedValue("invalid json" as any) + + const result = await generateErrorDiagnostics({ + taskId: "test-task-id", + globalStoragePath: "/mock/global/storage", + values: { + timestamp: "2025-01-01T00:00:00.000Z", + version: "1.0.0", + provider: "test", + model: "test", + details: "error", + }, + log: mockLog, + }) + + // Should still succeed but with empty history + expect(result.success).toBe(true) + expect(vscode.window.showErrorMessage).toHaveBeenCalledWith("Failed to parse api_conversation_history.json") + + // Verify empty history in output + const [, writtenContent] = vi.mocked(fs.writeFile).mock.calls[0] + expect(String(writtenContent)).toContain('"history": []') + }) + + it("returns error result when file write fails", async () => { + vi.mocked(fsUtils.fileExistsAtPath).mockResolvedValue(false as any) + vi.mocked(fs.writeFile).mockRejectedValue(new Error("Write failed")) + + const result = await generateErrorDiagnostics({ + taskId: "test-task-id", + globalStoragePath: "/mock/global/storage", + log: mockLog, + }) + + expect(result.success).toBe(false) + expect(result.error).toBe("Write failed") + expect(mockLog).toHaveBeenCalledWith("Error generating diagnostics: Write failed") + expect(vscode.window.showErrorMessage).toHaveBeenCalledWith("Failed to generate diagnostics: Write failed") + }) +}) diff --git a/src/core/webview/__tests__/webviewMessageHandler.spec.ts b/src/core/webview/__tests__/webviewMessageHandler.spec.ts index f724558ae6a..66423dd379b 100644 --- a/src/core/webview/__tests__/webviewMessageHandler.spec.ts +++ b/src/core/webview/__tests__/webviewMessageHandler.spec.ts @@ -5,6 +5,11 @@ import type { Mock } from "vitest" // Mock dependencies - must come before imports vi.mock("../../../api/providers/fetchers/modelCache") +// Mock the diagnosticsHandler module +vi.mock("../diagnosticsHandler", () => ({ + generateErrorDiagnostics: vi.fn().mockResolvedValue({ success: true, filePath: "/tmp/diagnostics.json" }), +})) + import { webviewMessageHandler } from "../webviewMessageHandler" import type { ClineProvider } from "../ClineProvider" import { getModels } from "../../../api/providers/fetchers/modelCache" @@ -41,15 +46,24 @@ const mockClineProvider = { import { t } from "../../../i18n" -vi.mock("vscode", () => ({ - window: { - showInformationMessage: vi.fn(), - showErrorMessage: vi.fn(), - }, - workspace: { - workspaceFolders: [{ uri: { fsPath: "/mock/workspace" } }], - }, -})) +vi.mock("vscode", () => { + const showInformationMessage = vi.fn() + const showErrorMessage = vi.fn() + const openTextDocument = vi.fn().mockResolvedValue({}) + const showTextDocument = vi.fn().mockResolvedValue(undefined) + + return { + window: { + showInformationMessage, + showErrorMessage, + showTextDocument, + }, + workspace: { + workspaceFolders: [{ uri: { fsPath: "/mock/workspace" } }], + openTextDocument, + }, + } +}) vi.mock("../../../i18n", () => ({ t: vi.fn((key: string, args?: Record) => { @@ -72,14 +86,20 @@ vi.mock("../../../i18n", () => ({ vi.mock("fs/promises", () => { const mockRm = vi.fn().mockResolvedValue(undefined) const mockMkdir = vi.fn().mockResolvedValue(undefined) + const mockReadFile = vi.fn().mockResolvedValue("[]") + const mockWriteFile = vi.fn().mockResolvedValue(undefined) return { default: { rm: mockRm, mkdir: mockMkdir, + readFile: mockReadFile, + writeFile: mockWriteFile, }, rm: mockRm, mkdir: mockMkdir, + readFile: mockReadFile, + writeFile: mockWriteFile, } }) @@ -90,6 +110,7 @@ import * as path from "path" import * as fsUtils from "../../../utils/fs" import { getWorkspacePath } from "../../../utils/path" import { ensureSettingsDirectoryExists } from "../../../utils/globalContext" +import { generateErrorDiagnostics } from "../diagnosticsHandler" import type { ModeConfig } from "@roo-code/types" vi.mock("../../../utils/fs") @@ -739,3 +760,57 @@ describe("webviewMessageHandler - mcpEnabled", () => { expect(mockClineProvider.postStateToWebview).toHaveBeenCalledTimes(1) }) }) + +describe("webviewMessageHandler - downloadErrorDiagnostics", () => { + beforeEach(() => { + vi.clearAllMocks() + + // Ensure contextProxy has a globalStorageUri for the handler + ;(mockClineProvider as any).contextProxy.globalStorageUri = { fsPath: "/mock/global/storage" } + + // Provide a current task with a stable ID + vi.mocked(mockClineProvider.getCurrentTask).mockReturnValue({ + taskId: "test-task-id", + } as any) + }) + + it("calls generateErrorDiagnostics with correct parameters", async () => { + await webviewMessageHandler(mockClineProvider, { + type: "downloadErrorDiagnostics", + values: { + timestamp: "2025-01-01T00:00:00.000Z", + version: "1.2.3", + provider: "test-provider", + model: "test-model", + details: "Sample error details", + }, + } as any) + + // Verify generateErrorDiagnostics was called with the correct parameters + expect(generateErrorDiagnostics).toHaveBeenCalledTimes(1) + expect(generateErrorDiagnostics).toHaveBeenCalledWith({ + taskId: "test-task-id", + globalStoragePath: "/mock/global/storage", + values: { + timestamp: "2025-01-01T00:00:00.000Z", + version: "1.2.3", + provider: "test-provider", + model: "test-model", + details: "Sample error details", + }, + log: expect.any(Function), + }) + }) + + it("shows error when no active task", async () => { + vi.mocked(mockClineProvider.getCurrentTask).mockReturnValue(null as any) + + await webviewMessageHandler(mockClineProvider, { + type: "downloadErrorDiagnostics", + values: {}, + } as any) + + expect(vscode.window.showErrorMessage).toHaveBeenCalledWith("No active task to generate diagnostics for") + expect(generateErrorDiagnostics).not.toHaveBeenCalled() + }) +}) diff --git a/src/core/webview/diagnosticsHandler.ts b/src/core/webview/diagnosticsHandler.ts new file mode 100644 index 00000000000..212ddbc5dee --- /dev/null +++ b/src/core/webview/diagnosticsHandler.ts @@ -0,0 +1,92 @@ +import * as path from "path" +import * as os from "os" +import * as fs from "fs/promises" +import * as vscode from "vscode" + +import { getTaskDirectoryPath } from "../../utils/storage" +import { fileExistsAtPath } from "../../utils/fs" + +export interface ErrorDiagnosticsValues { + timestamp?: string + version?: string + provider?: string + model?: string + details?: string +} + +export interface GenerateDiagnosticsParams { + taskId: string + globalStoragePath: string + values?: ErrorDiagnosticsValues + log: (message: string) => void +} + +export interface GenerateDiagnosticsResult { + success: boolean + filePath?: string + error?: string +} + +/** + * Generates an error diagnostics file containing error metadata and API conversation history. + * The file is created in the system temp directory and opened in VS Code for the user to review + * before sharing with support. + */ +export async function generateErrorDiagnostics(params: GenerateDiagnosticsParams): Promise { + const { taskId, globalStoragePath, values, log } = params + + try { + const taskDirPath = await getTaskDirectoryPath(globalStoragePath, taskId) + + // Load API conversation history from the same file used by openDebugApiHistory + const apiHistoryPath = path.join(taskDirPath, "api_conversation_history.json") + let history: unknown = [] + + if (await fileExistsAtPath(apiHistoryPath)) { + const content = await fs.readFile(apiHistoryPath, "utf8") + try { + history = JSON.parse(content) + } catch { + // If parsing fails, fall back to empty history but still generate diagnostics file + vscode.window.showErrorMessage("Failed to parse api_conversation_history.json") + } + } + + const diagnostics = { + error: { + timestamp: values?.timestamp ?? new Date().toISOString(), + version: values?.version ?? "", + provider: values?.provider ?? "", + model: values?.model ?? "", + details: values?.details ?? "", + }, + history, + } + + // Prepend human-readable guidance comments before the JSON payload + const headerComment = + "// Please share this file with Roo Code Support (support@roocode.com) to diagnose the issue faster\n" + + "// Just make sure you're OK sharing the contents of the conversation below.\n\n" + const jsonContent = JSON.stringify(diagnostics, null, 2) + const fullContent = headerComment + jsonContent + + // Create a temporary diagnostics file + const tmpDir = os.tmpdir() + const timestamp = Date.now() + const tempFileName = `roo-diagnostics-${taskId.slice(0, 8)}-${timestamp}.json` + const tempFilePath = path.join(tmpDir, tempFileName) + + await fs.writeFile(tempFilePath, fullContent, "utf8") + + // Open the diagnostics file in VS Code + const doc = await vscode.workspace.openTextDocument(tempFilePath) + await vscode.window.showTextDocument(doc, { preview: true }) + + return { success: true, filePath: tempFilePath } + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error) + log(`Error generating diagnostics: ${errorMessage}`) + vscode.window.showErrorMessage(`Failed to generate diagnostics: ${errorMessage}`) + return { success: false, error: errorMessage } + } +} diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index e408414879f..aa72ee253f5 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -25,6 +25,7 @@ import { saveTaskMessages } from "../task-persistence" import { ClineProvider } from "./ClineProvider" import { BrowserSessionPanelManager } from "./BrowserSessionPanelManager" import { handleCheckpointRestoreOperation } from "./checkpointRestoreHandler" +import { generateErrorDiagnostics } from "./diagnosticsHandler" import { changeLanguage, t } from "../../i18n" import { Package } from "../../shared/package" import { type RouterName, type ModelRecord, toRouterName } from "../../shared/api" @@ -3173,6 +3174,22 @@ export const webviewMessageHandler = async ( break } + case "downloadErrorDiagnostics": { + const currentTask = provider.getCurrentTask() + if (!currentTask) { + vscode.window.showErrorMessage("No active task to generate diagnostics for") + break + } + + await generateErrorDiagnostics({ + taskId: currentTask.taskId, + globalStoragePath: provider.contextProxy.globalStorageUri.fsPath, + values: message.values, + log: (msg) => provider.log(msg), + }) + break + } + default: { // console.log(`Unhandled message type: ${message.type}`) // diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index a2ae6b199dc..970208a2a3e 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -178,6 +178,7 @@ export interface WebviewMessage { | "browserPanelDidLaunch" | "openDebugApiHistory" | "openDebugUiHistory" + | "downloadErrorDiagnostics" | "requestClaudeCodeRateLimits" text?: string editedMessageContent?: string diff --git a/webview-ui/src/components/chat/ErrorRow.tsx b/webview-ui/src/components/chat/ErrorRow.tsx index 30ea05fe96d..1f87a6fd6ae 100644 --- a/webview-ui/src/components/chat/ErrorRow.tsx +++ b/webview-ui/src/components/chat/ErrorRow.tsx @@ -1,7 +1,8 @@ import React, { useState, useCallback, memo, useMemo } from "react" import { useTranslation } from "react-i18next" import { VSCodeButton } from "@vscode/webview-ui-toolkit/react" -import { BookOpenText, MessageCircleWarning, Copy, Check } from "lucide-react" +import { BookOpenText, MessageCircleWarning, Copy, Check, Microscope } from "lucide-react" + import { useCopyToClipboard } from "@src/utils/clipboard" import { vscode } from "@src/utils/vscode" import CodeBlock from "../common/CodeBlock" @@ -112,6 +113,23 @@ export const ErrorRow = memo( return metadata + errorDetails }, [errorDetails, version, provider, modelId]) + const handleDownloadDiagnostics = useCallback( + (e: React.MouseEvent) => { + e.stopPropagation() + vscode.postMessage({ + type: "downloadErrorDiagnostics", + values: { + timestamp: new Date().toISOString(), + version, + provider, + model: modelId, + details: errorDetails || "", + }, + }) + }, + [version, provider, modelId, errorDetails], + ) + // Default titles for different error types const getDefaultTitle = () => { if (title) return title @@ -278,7 +296,7 @@ export const ErrorRow = memo( - + diff --git a/webview-ui/src/components/chat/__tests__/ErrorRow.spec.tsx b/webview-ui/src/components/chat/__tests__/ErrorRow.spec.tsx new file mode 100644 index 00000000000..612c6c117b8 --- /dev/null +++ b/webview-ui/src/components/chat/__tests__/ErrorRow.spec.tsx @@ -0,0 +1,82 @@ +import React from "react" + +import { render, screen, fireEvent } from "@/utils/test-utils" +import { vscode } from "@/utils/vscode" + +import { ErrorRow } from "../ErrorRow" + +// Mock vscode webview messaging +vi.mock("@/utils/vscode", () => ({ + vscode: { + postMessage: vi.fn(), + }, +})) + +// Mock ExtensionState context +vi.mock("@/context/ExtensionStateContext", () => ({ + useExtensionState: () => ({ + version: "1.0.0", + apiConfiguration: {}, + }), +})) + +// Mock selected model hook +vi.mock("@/components/ui/hooks/useSelectedModel", () => ({ + useSelectedModel: () => ({ + provider: "test-provider", + id: "test-model", + }), +})) + +// Mock i18n +vi.mock("react-i18next", () => ({ + useTranslation: () => ({ + t: (key: string) => { + const map: Record = { + "chat:error": "Error", + "chat:errorDetails.title": "Error Details", + "chat:errorDetails.copyToClipboard": "Copy to Clipboard", + "chat:errorDetails.copied": "Copied!", + "chat:errorDetails.diagnostics": "Get detailed error info", + } + return map[key] ?? key + }, + }), + initReactI18next: { + type: "3rdParty", + init: vi.fn(), + }, +})) + +describe("ErrorRow diagnostics download", () => { + it("sends downloadErrorDiagnostics message with error metadata", () => { + const mockPostMessage = vi.mocked(vscode.postMessage) + + render() + + // Open the Error Details dialog via the info button + const infoButton = screen.getByRole("button", { name: "Error Details" }) + fireEvent.click(infoButton) + + // Click the diagnostics button + const downloadButton = screen.getByRole("button", { name: "Get detailed error info" }) + fireEvent.click(downloadButton) + + expect(mockPostMessage).toHaveBeenCalled() + const call = mockPostMessage.mock.calls.find(([arg]) => arg.type === "downloadErrorDiagnostics") + expect(call).toBeTruthy() + if (!call) return + + const payload = call[0] as { type: string; values?: any } + expect(payload.values).toBeTruthy() + if (!payload.values) return + + expect(payload.values).toMatchObject({ + version: "1.0.0", + provider: "test-provider", + model: "test-model", + }) + // Timestamp is generated at runtime, but should be a string + expect(typeof payload.values.timestamp).toBe("string") + }) +}) diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index c91dff24ba7..73df09a299a 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -267,7 +267,8 @@ "link": "Details", "title": "Detalls de l'error", "copyToClipboard": "Copiar al porta-retalls", - "copied": "Copiat!" + "copied": "Copiat!", + "diagnostics": "Obtenir informació d'error detallada" }, "powershell": { "issues": "Sembla que estàs tenint problemes amb Windows PowerShell, si us plau consulta aquesta documentació per a més informació." diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index b6f9b2a4927..759d4dba912 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -267,7 +267,8 @@ "link": "Details", "title": "Fehlerdetails", "copyToClipboard": "In Zwischenablage kopieren", - "copied": "Kopiert!" + "copied": "Kopiert!", + "diagnostics": "Detaillierte Fehlerinformationen abrufen" }, "powershell": { "issues": "Es scheint, dass du Probleme mit Windows PowerShell hast, bitte sieh dir dies an" diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index b1a50fd7531..4a4d0cf3e8b 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -293,8 +293,9 @@ "errorDetails": { "link": "Details", "title": "Error Details", - "copyToClipboard": "Copy to Clipboard", - "copied": "Copied!" + "copyToClipboard": "Copy basic error info", + "copied": "Copied!", + "diagnostics": "Get detailed error info" }, "diffError": { "title": "Edit Unsuccessful" diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index fdf0a4eb31f..eede12a4416 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -267,7 +267,8 @@ "link": "Detalles", "title": "Detalles del error", "copyToClipboard": "Copiar al portapapeles", - "copied": "¡Copiado!" + "copied": "¡Copiado!", + "diagnostics": "Obtener información de error detallada" }, "powershell": { "issues": "Parece que estás teniendo problemas con Windows PowerShell, por favor consulta esta" diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index 6cac21b8e25..99f2ddd226e 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -267,7 +267,8 @@ "link": "Détails", "title": "Détails de l'erreur", "copyToClipboard": "Copier dans le presse-papiers", - "copied": "Copié !" + "copied": "Copié !", + "diagnostics": "Obtenir les détails de l'erreur" }, "powershell": { "issues": "Il semble que vous rencontriez des problèmes avec Windows PowerShell, veuillez consulter ce" diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 4b09782639d..7e2c985ad7c 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -267,7 +267,8 @@ "link": "विवरण", "title": "त्रुटि विवरण", "copyToClipboard": "क्लिपबोर्ड पर कॉपी करें", - "copied": "कॉपी किया गया!" + "copied": "कॉपी किया गया!", + "diagnostics": "विस्तृत त्रुटि जानकारी प्राप्त करें" }, "powershell": { "issues": "ऐसा लगता है कि आपको Windows PowerShell के साथ समस्याएँ हो रही हैं, कृपया इसे देखें" diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index c72f1abd024..d7f8b33ae15 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -303,7 +303,8 @@ "link": "Details", "title": "Detail Kesalahan", "copyToClipboard": "Salin ke Clipboard", - "copied": "Disalin!" + "copied": "Disalin!", + "diagnostics": "Dapatkan informasi kesalahan terperinci" }, "powershell": { "issues": "Sepertinya kamu mengalami masalah Windows PowerShell, silakan lihat ini" diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index a1a22db25ff..638d9765667 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -267,7 +267,8 @@ "link": "Dettagli", "title": "Dettagli errore", "copyToClipboard": "Copia negli appunti", - "copied": "Copiato!" + "copied": "Copiato!", + "diagnostics": "Ottieni informazioni errore dettagliate" }, "powershell": { "issues": "Sembra che tu stia avendo problemi con Windows PowerShell, consulta questa" diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index e12c0866b9e..35eddef57be 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -267,7 +267,8 @@ "link": "詳細", "title": "エラー詳細", "copyToClipboard": "クリップボードにコピー", - "copied": "コピーしました!" + "copied": "コピーしました!", + "diagnostics": "詳細なエラー情報を取得" }, "powershell": { "issues": "Windows PowerShellに問題があるようです。こちらを参照してください" diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index d268809e826..1b2f0973da6 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -267,7 +267,8 @@ "link": "자세히", "title": "오류 세부 정보", "copyToClipboard": "클립보드에 복사", - "copied": "복사됨!" + "copied": "복사됨!", + "diagnostics": "상세한 오류 정보 가져오기" }, "powershell": { "issues": "Windows PowerShell에 문제가 있는 것 같습니다. 다음을 참조하세요" diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index f92cc414a8f..e3eab860e85 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -267,7 +267,8 @@ "link": "Details", "title": "Foutdetails", "copyToClipboard": "Naar klembord kopiëren", - "copied": "Gekopieerd!" + "copied": "Gekopieerd!", + "diagnostics": "Gedetailleerde foutinformatie ophalen" }, "powershell": { "issues": "Het lijkt erop dat je problemen hebt met Windows PowerShell, zie deze" diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index 24c5f169932..4665d01cde4 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -267,7 +267,8 @@ "link": "Details", "title": "Szczegóły błędu", "copyToClipboard": "Kopiuj do schowka", - "copied": "Skopiowano!" + "copied": "Skopiowano!", + "diagnostics": "Uzyskaj szczegółowe informacje o błędzie" }, "powershell": { "issues": "Wygląda na to, że masz problemy z Windows PowerShell, proszę zapoznaj się z tym" diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index 393c22842f2..30c51e72aeb 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -267,7 +267,8 @@ "link": "Details", "title": "Detalhes do erro", "copyToClipboard": "Copiar para área de transferência", - "copied": "Copiado!" + "copied": "Copiado!", + "diagnostics": "Obter informações detalhadas do erro" }, "powershell": { "issues": "Parece que você está tendo problemas com o Windows PowerShell, por favor veja este" diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index f40ab34f8bc..b3188fe8e53 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -268,7 +268,8 @@ "link": "Подробности", "title": "Детали ошибки", "copyToClipboard": "Скопировать в буфер обмена", - "copied": "Скопировано!" + "copied": "Скопировано!", + "diagnostics": "Получить подробную информацию об ошибке" }, "powershell": { "issues": "Похоже, у вас проблемы с Windows PowerShell, пожалуйста, ознакомьтесь с этим" diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index cfd828fc683..9a56b032fb9 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -268,7 +268,8 @@ "link": "Details", "title": "Hata Detayları", "copyToClipboard": "Panoya Kopyala", - "copied": "Kopyalandı!" + "copied": "Kopyalandı!", + "diagnostics": "Ayrıntılı hata bilgisi al" }, "powershell": { "issues": "Windows PowerShell ile ilgili sorunlar yaşıyor gibi görünüyorsunuz, lütfen şu konuya bakın" diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index 1d05e5d8020..be6a42addd1 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -268,7 +268,8 @@ "link": "Chi tiết", "title": "Chi tiết lỗi", "copyToClipboard": "Sao chép vào clipboard", - "copied": "Đã sao chép!" + "copied": "Đã sao chép!", + "diagnostics": "Nhận thông tin lỗi chi tiết" }, "powershell": { "issues": "Có vẻ như bạn đang gặp vấn đề với Windows PowerShell, vui lòng xem" diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index f704e8fe64c..abaee47dcb8 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -268,7 +268,8 @@ "link": "详情", "title": "错误详情", "copyToClipboard": "复制到剪贴板", - "copied": "已复制!" + "copied": "已复制!", + "diagnostics": "获取详细错误信息" }, "powershell": { "issues": "看起来您遇到了Windows PowerShell问题,请参阅此" diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index c24bfa79cd5..6a95f0a0ac0 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -301,7 +301,8 @@ "link": "詳情", "title": "錯誤詳細資訊", "copyToClipboard": "複製到剪貼簿", - "copied": "已複製!" + "copied": "已複製!", + "diagnostics": "取得詳細錯誤資訊" }, "powershell": { "issues": "您似乎遇到了 Windows PowerShell 的問題,請參閱此說明文件"