mirror of
https://github.com/cline/cline.git
synced 2026-09-04 20:02:30 +08:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 36a37f5951 | |||
| fb16c72224 | |||
| d40acc2d73 | |||
| 3c016f6bf3 | |||
| e644f39614 | |||
| c725d17c35 | |||
| f6a403ccd0 | |||
| e1fc921757 |
@@ -25,6 +25,7 @@ export const toolUseNames = [
|
||||
"attempt_completion",
|
||||
"new_task",
|
||||
"condense",
|
||||
"report_bug",
|
||||
"new_rule",
|
||||
] as const
|
||||
|
||||
@@ -53,6 +54,11 @@ export const toolParamNames = [
|
||||
"response",
|
||||
"result",
|
||||
"context",
|
||||
"title",
|
||||
"what_happened",
|
||||
"steps_to_reproduce",
|
||||
"api_request_output",
|
||||
"additional_context",
|
||||
] as const
|
||||
|
||||
export type ToolParamName = (typeof toolParamNames)[number]
|
||||
|
||||
@@ -275,6 +275,9 @@ export class Controller {
|
||||
case "condense":
|
||||
this.task?.handleWebviewAskResponse("yesButtonClicked")
|
||||
break
|
||||
case "reportBug":
|
||||
this.task?.handleWebviewAskResponse("yesButtonClicked")
|
||||
break
|
||||
case "apiConfiguration":
|
||||
if (message.apiConfiguration) {
|
||||
await updateApiConfiguration(this.context, message.apiConfiguration)
|
||||
|
||||
@@ -145,3 +145,34 @@ Example:
|
||||
Below is the user's input when they indicated that they wanted to create a new Cline rule file.
|
||||
</explicit_instructions>\n
|
||||
`
|
||||
|
||||
export const reportBugToolResponse = () =>
|
||||
`<explicit_instructions type="report_bug">
|
||||
The user has explicitly asked you to help them submit a bug to the Cline github page (you MUST now help them with this irrespective of what your conversation up to this point in time was). To do so you will use the report_bug tool which is defined below. However, you must first ensure that you have collected all required information to fill in all the parameters for the tool call. If any of the the required information is apparent through your previous conversation with the user, you can suggest how to fill in those entries. However you should NOT assume you know what the issue about unless it's clear.
|
||||
Otherwise, you should converse with the user until you are able to gather all the required details. When conversing with the user, make sure you ask for/reference all required information/fields. When referencing the required fields, use human friendly versions like "Steps to reproduce" rather than "steps_to_reproduce". Only then should you use the report_bug tool call.
|
||||
The report_bug tool can be used in either of the PLAN or ACT modes.
|
||||
|
||||
The report_bug tool call is defined below:
|
||||
|
||||
Description:
|
||||
Your task is to fill in all of the required fields for a issue/bug report on github. You should attempt to get the user to be as verbose as possible with their description of the bug/issue they encountered. Still, it's okay, when the user is unaware of some of the details, to set those fields as "N/A".
|
||||
|
||||
Parameters:
|
||||
- title: (required) Concise description of the issue.
|
||||
- what_happened: (required) What happened and also what the user expected to happen instead.
|
||||
- steps_to_reproduce: (required) What steps are required to reproduce the bug.
|
||||
- api_request_output: (optional) Relevant API request output.
|
||||
- additional_context: (optional) Any other context about this bug not already mentioned.
|
||||
|
||||
Usage:
|
||||
<report_bug>
|
||||
<title>Title of the issue</title>
|
||||
<what_happened>Description of the issue</what_happened>
|
||||
<steps_to_reproduce>Steps to reproduce the issue</steps_to_reproduce>
|
||||
<api_request_output>Output from the LLM API related to the bug</api_request_output>
|
||||
<additional_context>Other issue details not already covered</additional_context>
|
||||
</report_bug>
|
||||
|
||||
Below is the user's input when they indicated that they wanted to create a new Cline rule file.
|
||||
</explicit_instructions>\n
|
||||
`
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { newTaskToolResponse, condenseToolResponse, newRuleToolResponse } from "../prompts/commands"
|
||||
import { newTaskToolResponse, condenseToolResponse, newRuleToolResponse, reportBugToolResponse } from "../prompts/commands"
|
||||
|
||||
/**
|
||||
* Processes text for slash commands and transforms them with appropriate instructions
|
||||
* This is called after parseMentions() to process any slash commands in the user's message
|
||||
*/
|
||||
export function parseSlashCommands(text: string): { processedText: string; needsClinerulesFileCheck: boolean } {
|
||||
const SUPPORTED_COMMANDS = ["newtask", "smol", "compact", "newrule"]
|
||||
const SUPPORTED_COMMANDS = ["newtask", "smol", "compact", "newrule", "reportbug"]
|
||||
|
||||
const commandReplacements: Record<string, string> = {
|
||||
newtask: newTaskToolResponse(),
|
||||
smol: condenseToolResponse(),
|
||||
compact: condenseToolResponse(),
|
||||
newrule: newRuleToolResponse(),
|
||||
reportbug: reportBugToolResponse(),
|
||||
}
|
||||
|
||||
// this currently allows matching prepended whitespace prior to /slash-command
|
||||
|
||||
@@ -57,6 +57,7 @@ import { DEFAULT_LANGUAGE_SETTINGS, getLanguageKey, LanguageDisplay } from "@sha
|
||||
import { ClineAskResponse, ClineCheckpointRestore } from "@shared/WebviewMessage"
|
||||
import { calculateApiCostAnthropic } from "@utils/cost"
|
||||
import { fileExistsAtPath } from "@utils/fs"
|
||||
import { createAndOpenGitHubIssue } from "@utils/github-url-utils"
|
||||
import { arePathsEqual, getReadablePath, isLocatedInWorkspace } from "@utils/path"
|
||||
import { fixModelHtmlEscaping, removeInvalidChars } from "@utils/string"
|
||||
import { AssistantMessageContent, parseAssistantMessage, ToolParamName, ToolUseName } from "@core/assistant-message"
|
||||
@@ -1711,6 +1712,8 @@ export class Task {
|
||||
return `[${block.name} for creating a new task]`
|
||||
case "condense":
|
||||
return `[${block.name}]`
|
||||
case "report_bug":
|
||||
return `[${block.name}]`
|
||||
case "new_rule":
|
||||
return `[${block.name} for '${block.params.path}']`
|
||||
}
|
||||
@@ -3138,6 +3141,135 @@ export class Task {
|
||||
break
|
||||
}
|
||||
}
|
||||
case "report_bug": {
|
||||
const title = block.params.title
|
||||
const what_happened = block.params.what_happened
|
||||
const steps_to_reproduce = block.params.steps_to_reproduce
|
||||
const api_request_output = block.params.api_request_output
|
||||
const additional_context = block.params.additional_context
|
||||
|
||||
try {
|
||||
if (block.partial) {
|
||||
await this.ask(
|
||||
"report_bug",
|
||||
JSON.stringify({
|
||||
title: removeClosingTag("title", title),
|
||||
what_happened: removeClosingTag("what_happened", what_happened),
|
||||
steps_to_reproduce: removeClosingTag("steps_to_reproduce", steps_to_reproduce),
|
||||
api_request_output: removeClosingTag("api_request_output", api_request_output),
|
||||
additional_context: removeClosingTag("additional_context", additional_context),
|
||||
}),
|
||||
block.partial,
|
||||
).catch(() => {})
|
||||
break
|
||||
} else {
|
||||
if (!title) {
|
||||
this.consecutiveMistakeCount++
|
||||
pushToolResult(await this.sayAndCreateMissingParamError("report_bug", "title"))
|
||||
await this.saveCheckpoint()
|
||||
break
|
||||
}
|
||||
if (!what_happened) {
|
||||
this.consecutiveMistakeCount++
|
||||
pushToolResult(await this.sayAndCreateMissingParamError("report_bug", "what_happened"))
|
||||
await this.saveCheckpoint()
|
||||
break
|
||||
}
|
||||
if (!steps_to_reproduce) {
|
||||
this.consecutiveMistakeCount++
|
||||
pushToolResult(await this.sayAndCreateMissingParamError("report_bug", "steps_to_reproduce"))
|
||||
await this.saveCheckpoint()
|
||||
break
|
||||
}
|
||||
if (!api_request_output) {
|
||||
this.consecutiveMistakeCount++
|
||||
pushToolResult(await this.sayAndCreateMissingParamError("report_bug", "api_request_output"))
|
||||
await this.saveCheckpoint()
|
||||
break
|
||||
}
|
||||
if (!additional_context) {
|
||||
this.consecutiveMistakeCount++
|
||||
pushToolResult(await this.sayAndCreateMissingParamError("report_bug", "additional_context"))
|
||||
await this.saveCheckpoint()
|
||||
break
|
||||
}
|
||||
|
||||
this.consecutiveMistakeCount = 0
|
||||
|
||||
if (this.autoApprovalSettings.enabled && this.autoApprovalSettings.enableNotifications) {
|
||||
showSystemNotification({
|
||||
subtitle: "Cline wants to create a github issue...",
|
||||
message: `Cline is suggesting to create a github issue with the title: ${title}`,
|
||||
})
|
||||
}
|
||||
|
||||
// Derive system information values algorithmically
|
||||
const operatingSystem = os.platform() + " " + os.release()
|
||||
const clineVersion =
|
||||
vscode.extensions.getExtension("saoudrizwan.claude-dev")?.packageJSON.version || "Unknown"
|
||||
const systemInfo = `VSCode: ${vscode.version}, Node.js: ${process.version}, Architecture: ${os.arch()}`
|
||||
const providerAndModel = `${(await getGlobalState(this.getContext(), "apiProvider")) as string} / ${this.api.getModel().id}`
|
||||
|
||||
// Ask user for confirmation
|
||||
const bugReportData = JSON.stringify({
|
||||
title,
|
||||
what_happened,
|
||||
steps_to_reproduce,
|
||||
api_request_output,
|
||||
additional_context,
|
||||
// Include derived values in the JSON for display purposes
|
||||
provider_and_model: providerAndModel,
|
||||
operating_system: operatingSystem,
|
||||
system_info: systemInfo,
|
||||
cline_version: clineVersion,
|
||||
})
|
||||
|
||||
const { text, images } = await this.ask("report_bug", bugReportData, false)
|
||||
|
||||
// If the user provided a response, treat it as feedback
|
||||
if (text || images?.length) {
|
||||
await this.say("user_feedback", text ?? "", images)
|
||||
pushToolResult(
|
||||
formatResponse.toolResult(
|
||||
`The user provided feedback on the Github issue generated:\n<feedback>\n${text}\n</feedback>`,
|
||||
images,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
// If no response, the user accepted the condensed version
|
||||
pushToolResult(
|
||||
formatResponse.toolResult(`The user accepted the creation of the Github issue.`),
|
||||
)
|
||||
|
||||
try {
|
||||
// Create a Map of parameters for the GitHub issue
|
||||
const params = new Map<string, string>()
|
||||
params.set("title", title)
|
||||
params.set("operating-system", operatingSystem)
|
||||
params.set("cline-version", clineVersion)
|
||||
params.set("system-info", systemInfo)
|
||||
params.set("additional-context", additional_context)
|
||||
params.set("what-happened", what_happened)
|
||||
params.set("steps", steps_to_reproduce)
|
||||
params.set("provider-model", providerAndModel)
|
||||
params.set("logs", api_request_output)
|
||||
|
||||
// Use our utility function to create and open the GitHub issue URL
|
||||
// This bypasses VS Code's URI handling issues with special characters
|
||||
await createAndOpenGitHubIssue("cline", "cline", "bug_report.yml", params)
|
||||
} catch (error) {
|
||||
console.error(`An error occurred while attempting to report the bug: ${error}`)
|
||||
}
|
||||
}
|
||||
await this.saveCheckpoint()
|
||||
break
|
||||
}
|
||||
} catch (error) {
|
||||
await handleError("reporting bug", error)
|
||||
await this.saveCheckpoint()
|
||||
break
|
||||
}
|
||||
}
|
||||
case "plan_mode_respond": {
|
||||
const response: string | undefined = block.params.response
|
||||
const optionsRaw: string | undefined = block.params.options
|
||||
|
||||
@@ -179,6 +179,7 @@ export type ClineAsk =
|
||||
| "use_mcp_server"
|
||||
| "new_task"
|
||||
| "condense"
|
||||
| "report_bug"
|
||||
|
||||
export type ClineSay =
|
||||
| "task"
|
||||
|
||||
@@ -13,6 +13,7 @@ export interface WebviewMessage {
|
||||
| "webviewDidLaunch"
|
||||
| "newTask"
|
||||
| "condense"
|
||||
| "reportBug"
|
||||
| "askResponse"
|
||||
| "didShowAnnouncement"
|
||||
| "selectImages"
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* github-url-utils.ts
|
||||
*
|
||||
* Portable utility functions for creating and opening GitHub issue URLs
|
||||
* with proper URL encoding that bypasses VS Code's URI handling issues.
|
||||
*
|
||||
* This utility addresses a longstanding issue in VS Code's URI handling:
|
||||
* https://github.com/microsoft/vscode/issues/85930
|
||||
*
|
||||
* The issue causes URLs with special characters in query parameters to be incorrectly
|
||||
* encoded when opened through VS Code's standard APIs (vscode.Uri.parse followed by
|
||||
* vscode.env.openExternal). This particularly affects GitHub issue URLs with pre-filled
|
||||
* fields containing special characters.
|
||||
*/
|
||||
|
||||
import * as vscode from "vscode"
|
||||
import * as cp from "child_process"
|
||||
import * as os from "os"
|
||||
import * as util from "util"
|
||||
|
||||
/**
|
||||
* Creates a properly encoded GitHub issue URL.
|
||||
*
|
||||
* This function manually encodes each parameter value using encodeURIComponent()
|
||||
* to ensure consistent and correct encoding of all special characters. This is
|
||||
* necessary because VS Code's URI handling (vscode.Uri.parse) has issues with
|
||||
* encoding/decoding URL parameters, as documented in:
|
||||
* https://github.com/microsoft/vscode/issues/85930
|
||||
*
|
||||
* Specifically, VS Code's URI handling:
|
||||
* - Double-encodes some characters like # (hash) becoming %2523 instead of %23
|
||||
* - Inconsistently handles other characters like & (ampersand) and + (plus)
|
||||
* - Can corrupt query parameters containing special characters
|
||||
*
|
||||
* @param baseUrl The base GitHub repository URL (e.g., 'https://github.com/owner/repo/issues/new')
|
||||
* @param params Map of parameter names to values for the issue form
|
||||
* @returns The properly encoded full URL
|
||||
*/
|
||||
export function createGitHubIssueUrl(baseUrl: string, params: Map<string, string>): string {
|
||||
// Build query string manually with proper encoding
|
||||
const queryParts: string[] = []
|
||||
|
||||
for (const [key, value] of params.entries()) {
|
||||
const encodedKey = encodeURIComponent(key)
|
||||
const encodedValue = encodeURIComponent(value)
|
||||
queryParts.push(`${encodedKey}=${encodedValue}`)
|
||||
}
|
||||
|
||||
// Determine the proper separator (? or &) based on whether baseUrl already has parameters
|
||||
const separator = baseUrl.includes("?") ? "&" : "?"
|
||||
|
||||
// Join all parts to create the final URL
|
||||
const queryString = queryParts.join("&")
|
||||
return `${baseUrl}${separator}${queryString}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a URL using platform-specific commands to bypass VS Code's URI handling issues.
|
||||
*
|
||||
* IMPORTANT: This function intentionally avoids using VS Code's built-in URI handling
|
||||
* (vscode.Uri.parse() and vscode.env.openExternal()) due to known encoding issues with URLs
|
||||
* that contain special characters in query parameters. See:
|
||||
* https://github.com/microsoft/vscode/issues/85930
|
||||
*
|
||||
* The specific issues with VS Code's URI handling include:
|
||||
* 1. Double-encoding of certain characters (e.g., # becomes %23 then %2523)
|
||||
* 2. Inconsistent handling where some characters are encoded and others are decoded
|
||||
* 3. Issues with parameters in the query string being incorrectly processed
|
||||
*
|
||||
* Instead, this function:
|
||||
* - Uses direct OS commands to open the browser with the URL
|
||||
* - Preserves the exact encoding of the URL as provided
|
||||
* - Provides multiple fallback approaches if the primary method fails
|
||||
*
|
||||
* @param url The URL to open
|
||||
* @returns A promise that resolves when an attempt to open the URL has completed
|
||||
*/
|
||||
export async function openUrlInBrowser(url: string): Promise<void> {
|
||||
// For debugging
|
||||
console.log(`Opening URL: ${url}`)
|
||||
|
||||
// Always copy to clipboard as a fallback
|
||||
try {
|
||||
await vscode.env.clipboard.writeText(url)
|
||||
console.log("URL copied to clipboard as backup")
|
||||
} catch (error) {
|
||||
console.error(`Failed to copy URL to clipboard: ${error}`)
|
||||
}
|
||||
|
||||
// Try to open the URL using platform-specific commands
|
||||
try {
|
||||
const platform = os.platform()
|
||||
console.log(`Detected platform: ${platform}`)
|
||||
|
||||
// Use promisify for better async error handling
|
||||
const execPromise = util.promisify(cp.exec)
|
||||
|
||||
// Use platform-specific commands
|
||||
if (platform === "win32") {
|
||||
// Windows - try multiple approaches
|
||||
try {
|
||||
await execPromise(`start "" "${url}"`)
|
||||
console.log("Opened URL with Windows 'start' command")
|
||||
return
|
||||
} catch (winError) {
|
||||
console.error(`Error with Windows 'start' command: ${winError}`)
|
||||
|
||||
try {
|
||||
await execPromise(`powershell.exe -Command "Start-Process '${url}'"`)
|
||||
console.log("Opened URL with PowerShell command")
|
||||
return
|
||||
} catch (psError) {
|
||||
console.error(`Error with PowerShell command: ${psError}`)
|
||||
// Fall through to the fallbacks
|
||||
}
|
||||
}
|
||||
} else if (platform === "darwin") {
|
||||
// macOS
|
||||
await execPromise(`open "${url}"`)
|
||||
console.log("Opened URL with macOS 'open' command")
|
||||
return
|
||||
} else {
|
||||
// Linux and others - try multiple commands
|
||||
const linuxCommands = ["xdg-open", "gnome-open", "kde-open", "wslview"]
|
||||
|
||||
for (const cmd of linuxCommands) {
|
||||
try {
|
||||
await execPromise(`${cmd} "${url}"`)
|
||||
console.log(`Opened URL with '${cmd}' command`)
|
||||
return
|
||||
} catch (cmdError) {
|
||||
console.error(`Error with '${cmd}' command: ${cmdError}`)
|
||||
// Try next command
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we got here, none of the OS commands worked
|
||||
throw new Error("All OS commands failed")
|
||||
} catch (error) {
|
||||
console.error(`OS commands failed: ${error}`)
|
||||
|
||||
// First fallback: Try VS Code's openExternal
|
||||
// Note: This will likely have encoding issues per https://github.com/microsoft/vscode/issues/85930
|
||||
// but we include it as a fallback in case OS commands completely fail
|
||||
try {
|
||||
// The 'true' parameter might help preserve some encodings, but this is not guaranteed
|
||||
await vscode.env.openExternal(vscode.Uri.parse(url, true))
|
||||
console.log("Opened URL with vscode.env.openExternal (note: URL encoding may be affected)")
|
||||
return
|
||||
} catch (vscodeError) {
|
||||
console.error(`Error with vscode.env.openExternal: ${vscodeError}`)
|
||||
|
||||
// Last fallback: Show a message with instructions
|
||||
vscode.window
|
||||
.showInformationMessage(
|
||||
"Couldn't open the URL automatically. It has been copied to your clipboard.",
|
||||
"Copy URL Again",
|
||||
)
|
||||
.then((selection) => {
|
||||
if (selection === "Copy URL Again") {
|
||||
vscode.env.clipboard.writeText(url)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to create and open a GitHub issue with the specified parameters.
|
||||
*
|
||||
* This is a high-level function that combines URL creation and opening while
|
||||
* working around VS Code's URI handling limitations (issue #85930). It provides
|
||||
* a simple API for the common use case of opening GitHub issue templates with
|
||||
* pre-filled fields.
|
||||
*
|
||||
* The function:
|
||||
* 1. Constructs a correctly formatted GitHub issue URL
|
||||
* 2. Properly encodes all special characters in parameters
|
||||
* 3. Opens the URL directly using OS commands to avoid VS Code's problematic URI handling
|
||||
* 4. Provides fallback options if opening fails
|
||||
*
|
||||
* Reference for the VS Code URI handling issue:
|
||||
* https://github.com/microsoft/vscode/issues/85930
|
||||
*
|
||||
* @param repoOwner GitHub repository owner/organization
|
||||
* @param repoName GitHub repository name
|
||||
* @param issueTemplate Template name to use (e.g., 'bug_report.yml')
|
||||
* @param params Map of parameter names to values for the issue form
|
||||
*/
|
||||
export async function createAndOpenGitHubIssue(
|
||||
repoOwner: string,
|
||||
repoName: string,
|
||||
issueTemplate: string | null,
|
||||
params: Map<string, string>,
|
||||
): Promise<void> {
|
||||
// Construct the base URL
|
||||
let baseUrl = `https://github.com/${repoOwner}/${repoName}/issues/new`
|
||||
|
||||
// Add template parameter if provided
|
||||
if (issueTemplate) {
|
||||
params.set("template", issueTemplate)
|
||||
}
|
||||
|
||||
// Create the URL and open it
|
||||
const issueUrl = createGitHubIssueUrl(baseUrl, params)
|
||||
await openUrlInBrowser(issueUrl)
|
||||
}
|
||||
@@ -89,6 +89,7 @@ import { highlightText } from "./TaskHeader"
|
||||
import SuccessButton from "@/components/common/SuccessButton"
|
||||
import TaskFeedbackButtons from "@/components/chat/TaskFeedbackButtons"
|
||||
import NewTaskPreview from "./NewTaskPreview"
|
||||
import ReportBugPreview from "./ReportBugPreview"
|
||||
import McpResourceRow from "@/components/mcp/configuration/tabs/installed/server-row/McpResourceRow"
|
||||
import UserMessage from "./UserMessage"
|
||||
import QuoteButton from "./QuoteButton"
|
||||
@@ -1475,6 +1476,23 @@ export const ChatRowContent = ({
|
||||
<NewTaskPreview context={message.text || ""} />
|
||||
</>
|
||||
)
|
||||
case "report_bug":
|
||||
return (
|
||||
<>
|
||||
<div style={headerStyle}>
|
||||
<span
|
||||
className="codicon codicon-new-file"
|
||||
style={{
|
||||
color: normalColor,
|
||||
marginBottom: "-1.5px",
|
||||
}}></span>
|
||||
<span style={{ color: normalColor, fontWeight: "bold" }}>
|
||||
Cline wants to create a Github issue:
|
||||
</span>
|
||||
</div>
|
||||
<ReportBugPreview data={message.text || ""} />
|
||||
</>
|
||||
)
|
||||
case "plan_mode_respond": {
|
||||
let response: string | undefined
|
||||
let options: string[] | undefined
|
||||
|
||||
@@ -288,6 +288,13 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
|
||||
setPrimaryButtonText("Condense Conversation")
|
||||
setSecondaryButtonText(undefined)
|
||||
break
|
||||
case "report_bug":
|
||||
setSendingDisabled(isPartial)
|
||||
setClineAsk("report_bug")
|
||||
setEnableButtons(!isPartial)
|
||||
setPrimaryButtonText("Report GitHub issue")
|
||||
setSecondaryButtonText(undefined)
|
||||
break
|
||||
}
|
||||
break
|
||||
case "say":
|
||||
@@ -416,6 +423,14 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
|
||||
images,
|
||||
})
|
||||
break
|
||||
case "report_bug":
|
||||
vscode.postMessage({
|
||||
type: "askResponse",
|
||||
askResponse: "messageResponse",
|
||||
text: messageToSend,
|
||||
images,
|
||||
})
|
||||
break
|
||||
// there is no other case that a textfield should be enabled
|
||||
}
|
||||
}
|
||||
@@ -490,6 +505,12 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
|
||||
text: lastMessage?.text,
|
||||
})
|
||||
break
|
||||
case "report_bug":
|
||||
vscode.postMessage({
|
||||
type: "reportBug",
|
||||
text: lastMessage?.text,
|
||||
})
|
||||
break
|
||||
}
|
||||
setSendingDisabled(true)
|
||||
setClineAsk(undefined)
|
||||
@@ -1101,7 +1122,6 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
|
||||
</>
|
||||
)}
|
||||
{(() => {
|
||||
console.log("[ChatView] Rendering - activeQuote:", activeQuote) // Log here
|
||||
return activeQuote ? (
|
||||
<div style={{ marginBottom: "-12px", marginTop: "10px" }}>
|
||||
<QuotedMessagePreview
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import React from "react"
|
||||
import MarkdownBlock from "../common/MarkdownBlock"
|
||||
|
||||
interface ReportBugPreviewProps {
|
||||
data: string
|
||||
}
|
||||
|
||||
const ReportBugPreview: React.FC<ReportBugPreviewProps> = ({ data }) => {
|
||||
// Parse the JSON data from the context string
|
||||
const bugData = React.useMemo(() => {
|
||||
try {
|
||||
return JSON.parse(data || "{}")
|
||||
} catch (e) {
|
||||
console.error("Failed to parse bug report data", e)
|
||||
return {}
|
||||
}
|
||||
}, [data])
|
||||
|
||||
return (
|
||||
<div className="bg-[var(--vscode-badge-background)] text-[var(--vscode-badge-foreground)] rounded-[3px] p-[14px]">
|
||||
<h3 className="font-bold text-base mb-3 mt-0">{bugData.title || "Bug Report"}</h3>
|
||||
|
||||
<div className="space-y-3 text-sm">
|
||||
{bugData.what_happened && (
|
||||
<div>
|
||||
<div className="font-semibold">What Happened?</div>
|
||||
<MarkdownBlock markdown={bugData.what_happened} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{bugData.steps_to_reproduce && (
|
||||
<div>
|
||||
<div className="font-semibold">Steps to Reproduce</div>
|
||||
<MarkdownBlock markdown={bugData.steps_to_reproduce} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{bugData.api_request_output && (
|
||||
<div>
|
||||
<div className="font-semibold">Relevant API Request Output</div>
|
||||
<MarkdownBlock markdown={bugData.api_request_output} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{bugData.provider_and_model && (
|
||||
<div>
|
||||
<div className="font-semibold">Provider/Model</div>
|
||||
<MarkdownBlock markdown={bugData.provider_and_model} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{bugData.operating_system && (
|
||||
<div>
|
||||
<div className="font-semibold">Operating System</div>
|
||||
<MarkdownBlock markdown={bugData.operating_system} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{bugData.system_info && (
|
||||
<div>
|
||||
<div className="font-semibold">System Info</div>
|
||||
<MarkdownBlock markdown={bugData.system_info} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{bugData.cline_version && (
|
||||
<div>
|
||||
<div className="font-semibold">Cline Version</div>
|
||||
<MarkdownBlock markdown={bugData.cline_version} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{bugData.additional_context && (
|
||||
<div>
|
||||
<div className="font-semibold">Additional Context</div>
|
||||
<MarkdownBlock markdown={bugData.additional_context} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ReportBugPreview
|
||||
@@ -16,6 +16,10 @@ export const SUPPORTED_SLASH_COMMANDS: SlashCommand[] = [
|
||||
name: "newrule",
|
||||
description: "Create a new Cline rule based on your conversation",
|
||||
},
|
||||
{
|
||||
name: "reportbug",
|
||||
description: "Create a Github issue with Cline",
|
||||
},
|
||||
]
|
||||
|
||||
// Regex for detecting slash commands in text
|
||||
|
||||
Reference in New Issue
Block a user