mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-05 08:10:14 +00:00
Use GUI telemetry toggle to more clearly show user if they're opted in or not
This commit is contained in:
parent
8c5f8b253b
commit
e14fd78767
10 changed files with 90 additions and 45 deletions
|
|
@ -186,11 +186,6 @@
|
|||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Controls whether the MCP Marketplace is enabled."
|
||||
},
|
||||
"cline.enableTelemetry": {
|
||||
"type": "boolean",
|
||||
"default": null,
|
||||
"markdownDescription": "Allow anonymous usage and error reporting to help improve Cline. No code, prompts, or personal information is ever sent. See our [privacy policy](https://github.com/cline/cline/blob/main/docs/PRIVACY.md) for details."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import { openMention } from "../mentions"
|
|||
import { getNonce } from "./getNonce"
|
||||
import { getUri } from "./getUri"
|
||||
import { telemetryService } from "../../services/telemetry/TelemetryService"
|
||||
import { TelemetrySetting } from "../../shared/TelemetrySetting"
|
||||
|
||||
/*
|
||||
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
|
||||
|
|
@ -93,6 +94,7 @@ type GlobalStateKey =
|
|||
| "requestyModelId"
|
||||
| "togetherModelId"
|
||||
| "mcpMarketplaceCatalog"
|
||||
| "telemetrySetting"
|
||||
|
||||
export const GlobalFileNames = {
|
||||
apiConversationHistory: "api_conversation_history.json",
|
||||
|
|
@ -454,6 +456,13 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||
}
|
||||
})
|
||||
|
||||
// If user already opted in to telemetry, enable telemetry service
|
||||
this.getStateToPostToWebview().then((state) => {
|
||||
const { telemetrySetting } = state
|
||||
const isOptedIn = telemetrySetting === "enabled"
|
||||
telemetryService.updateTelemetryState(isOptedIn)
|
||||
})
|
||||
|
||||
break
|
||||
case "newTask":
|
||||
// Code that should run in response to the hello message command
|
||||
|
|
@ -849,18 +858,19 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
|||
break
|
||||
}
|
||||
// telemetry
|
||||
case "openTelemetrySettings": {
|
||||
await vscode.commands.executeCommand(
|
||||
"workbench.action.openSettings",
|
||||
"@ext:saoudrizwan.claude-dev cline.telemetryOptIn",
|
||||
)
|
||||
case "openSettings": {
|
||||
await this.postMessageToWebview({
|
||||
type: "action",
|
||||
action: "settingsButtonClicked",
|
||||
})
|
||||
break
|
||||
}
|
||||
case "telemetryOptIn": {
|
||||
if (message.bool !== undefined) {
|
||||
await vscode.workspace.getConfiguration("cline").update("enableTelemetry", message.bool, true)
|
||||
await this.postStateToWebview()
|
||||
}
|
||||
case "telemetrySetting": {
|
||||
const telemetrySetting = message.text as TelemetrySetting
|
||||
await this.updateGlobalState("telemetrySetting", telemetrySetting)
|
||||
const isOptedIn = telemetrySetting === "enabled"
|
||||
telemetryService.updateTelemetryState(isOptedIn)
|
||||
await this.postStateToWebview()
|
||||
break
|
||||
}
|
||||
// Add more switch case statements here as more webview message commands
|
||||
|
|
@ -1628,7 +1638,7 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
|
|||
userInfo,
|
||||
authToken,
|
||||
mcpMarketplaceEnabled,
|
||||
telemetryOptIn,
|
||||
telemetrySetting,
|
||||
} = await this.getState()
|
||||
|
||||
return {
|
||||
|
|
@ -1648,7 +1658,7 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
|
|||
isLoggedIn: !!authToken,
|
||||
userInfo,
|
||||
mcpMarketplaceEnabled,
|
||||
telemetryOptIn,
|
||||
telemetrySetting,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1755,6 +1765,7 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
|
|||
previousModeModelInfo,
|
||||
qwenApiLine,
|
||||
liteLlmApiKey,
|
||||
telemetrySetting,
|
||||
] = await Promise.all([
|
||||
this.getGlobalState("apiProvider") as Promise<ApiProvider | undefined>,
|
||||
this.getGlobalState("apiModelId") as Promise<string | undefined>,
|
||||
|
|
@ -1806,6 +1817,7 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
|
|||
this.getGlobalState("previousModeModelInfo") as Promise<ModelInfo | undefined>,
|
||||
this.getGlobalState("qwenApiLine") as Promise<string | undefined>,
|
||||
this.getSecret("liteLlmApiKey") as Promise<string | undefined>,
|
||||
this.getGlobalState("telemetrySetting") as Promise<TelemetrySetting | undefined>,
|
||||
])
|
||||
|
||||
let apiProvider: ApiProvider
|
||||
|
|
@ -1827,7 +1839,6 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
|
|||
.get("reasoningEffort", "medium")
|
||||
|
||||
const mcpMarketplaceEnabled = vscode.workspace.getConfiguration("cline").get<boolean>("mcpMarketplace.enabled", true)
|
||||
const telemetryOptIn = vscode.workspace.getConfiguration("cline").get<boolean | null>("enableTelemetry", null)
|
||||
|
||||
return {
|
||||
apiConfiguration: {
|
||||
|
|
@ -1884,7 +1895,7 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
|
|||
previousModeModelId,
|
||||
previousModeModelInfo,
|
||||
mcpMarketplaceEnabled,
|
||||
telemetryOptIn,
|
||||
telemetrySetting: telemetrySetting || "unset",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,29 +12,18 @@ class PostHogClient {
|
|||
host: "https://us.i.posthog.com",
|
||||
enableExceptionAutocapture: false,
|
||||
})
|
||||
|
||||
// Initialize telemetry state based on user settings
|
||||
this.updateTelemetryState()
|
||||
|
||||
// Listen for settings changes
|
||||
vscode.workspace.onDidChangeConfiguration((e) => {
|
||||
if (e.affectsConfiguration("cline.enableTelemetry") || e.affectsConfiguration("telemetry.telemetryLevel")) {
|
||||
this.updateTelemetryState()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private updateTelemetryState(): void {
|
||||
public updateTelemetryState(didUserOptIn: boolean): void {
|
||||
this.telemetryEnabled = false
|
||||
|
||||
// First check global telemetry level - telemetry should only be enabled when level is "all"
|
||||
const telemetryLevel = vscode.workspace.getConfiguration("telemetry").get<string>("telemetryLevel", "all")
|
||||
const globalTelemetryEnabled = telemetryLevel === "all"
|
||||
|
||||
// Only check Cline setting if global telemetry is enabled
|
||||
// We only enable telemetry if global vscode telemetry is enabled
|
||||
if (globalTelemetryEnabled) {
|
||||
const clineOptIn = vscode.workspace.getConfiguration("cline").get<boolean | null>("enableTelemetry", null)
|
||||
this.telemetryEnabled = clineOptIn === true
|
||||
this.telemetryEnabled = didUserOptIn
|
||||
}
|
||||
|
||||
// Update PostHog client state based on telemetry preference
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { BrowserSettings } from "./BrowserSettings"
|
|||
import { ChatSettings } from "./ChatSettings"
|
||||
import { HistoryItem } from "./HistoryItem"
|
||||
import { McpServer, McpMarketplaceCatalog, McpMarketplaceItem, McpDownloadResponse } from "./mcp"
|
||||
import { TelemetrySetting } from "./TelemetrySetting"
|
||||
|
||||
// webview will hold state
|
||||
export interface ExtensionMessage {
|
||||
|
|
@ -81,7 +82,7 @@ export interface ExtensionState {
|
|||
photoURL: string | null
|
||||
}
|
||||
mcpMarketplaceEnabled?: boolean
|
||||
telemetryOptIn: boolean | null
|
||||
telemetrySetting: TelemetrySetting
|
||||
}
|
||||
|
||||
export interface ClineMessage {
|
||||
|
|
|
|||
1
src/shared/TelemetrySetting.ts
Normal file
1
src/shared/TelemetrySetting.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export type TelemetrySetting = "unset" | "enabled" | "disabled"
|
||||
|
|
@ -50,8 +50,8 @@ export interface WebviewMessage {
|
|||
| "searchCommits"
|
||||
| "showMcpView"
|
||||
| "fetchLatestMcpServersFromHub"
|
||||
| "telemetryOptIn"
|
||||
| "openTelemetrySettings"
|
||||
| "telemetrySetting"
|
||||
| "openSettings"
|
||||
// | "relaunchChromeDebugMode"
|
||||
text?: string
|
||||
disabled?: boolean
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ interface ChatViewProps {
|
|||
export const MAX_IMAGES_PER_MESSAGE = 20 // Anthropic limits to 20 images
|
||||
|
||||
const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryView }: ChatViewProps) => {
|
||||
const { version, clineMessages: messages, taskHistory, apiConfiguration, telemetryOptIn } = useExtensionState()
|
||||
const { version, clineMessages: messages, taskHistory, apiConfiguration, telemetrySetting } = useExtensionState()
|
||||
|
||||
//const task = messages.length > 0 ? (messages[0].say === "task" ? messages[0] : undefined) : undefined) : undefined
|
||||
const task = useMemo(() => messages.at(0), [messages]) // leaving this less safe version here since if the first message is not a task, then the extension is in a bad state and needs to be debugged (see Cline.abort)
|
||||
|
|
@ -790,7 +790,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
|
|||
flexDirection: "column",
|
||||
paddingBottom: "10px",
|
||||
}}>
|
||||
{telemetryOptIn === null && <TelemetryBanner />}
|
||||
{telemetrySetting === "unset" && <TelemetryBanner />}
|
||||
|
||||
{showAnnouncement && <Announcement version={version} hideAnnouncement={hideAnnouncement} />}
|
||||
<div style={{ padding: "0 20px", flexShrink: 0 }}>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
|
|||
import { memo, useState } from "react"
|
||||
import styled from "styled-components"
|
||||
import { vscode } from "../../utils/vscode"
|
||||
import { TelemetrySetting } from "../../../../src/shared/TelemetrySetting"
|
||||
|
||||
const BannerContainer = styled.div`
|
||||
background-color: var(--vscode-banner-background);
|
||||
|
|
@ -10,6 +11,7 @@ const BannerContainer = styled.div`
|
|||
flex-direction: column;
|
||||
gap: 10px;
|
||||
flex-shrink: 0;
|
||||
margin-bottom: 6px;
|
||||
`
|
||||
|
||||
const ButtonContainer = styled.div`
|
||||
|
|
@ -27,16 +29,16 @@ const TelemetryBanner = () => {
|
|||
|
||||
const handleAllow = () => {
|
||||
setHasChosen(true)
|
||||
vscode.postMessage({ type: "telemetryOptIn", bool: true })
|
||||
vscode.postMessage({ type: "telemetrySetting", text: "enabled" satisfies TelemetrySetting })
|
||||
}
|
||||
|
||||
const handleDeny = () => {
|
||||
setHasChosen(true)
|
||||
vscode.postMessage({ type: "telemetryOptIn", bool: false })
|
||||
vscode.postMessage({ type: "telemetrySetting", text: "disabled" satisfies TelemetrySetting })
|
||||
}
|
||||
|
||||
const handleOpenSettings = () => {
|
||||
vscode.postMessage({ type: "openTelemetrySettings" })
|
||||
vscode.postMessage({ type: "openSettings" })
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { VSCodeButton, VSCodeLink, VSCodeTextArea } from "@vscode/webview-ui-toolkit/react"
|
||||
import { VSCodeButton, VSCodeCheckbox, VSCodeLink, VSCodeTextArea } from "@vscode/webview-ui-toolkit/react"
|
||||
import { memo, useEffect, useState } from "react"
|
||||
import { useExtensionState } from "../../context/ExtensionStateContext"
|
||||
import { validateApiConfiguration, validateModelId } from "../../utils/validate"
|
||||
import { vscode } from "../../utils/vscode"
|
||||
import ApiOptions from "./ApiOptions"
|
||||
import SettingsButton from "../common/SettingsButton"
|
||||
import ApiOptions from "./ApiOptions"
|
||||
const { IS_DEV } = process.env
|
||||
|
||||
type SettingsViewProps = {
|
||||
|
|
@ -12,7 +12,15 @@ type SettingsViewProps = {
|
|||
}
|
||||
|
||||
const SettingsView = ({ onDone }: SettingsViewProps) => {
|
||||
const { apiConfiguration, version, customInstructions, setCustomInstructions, openRouterModels } = useExtensionState()
|
||||
const {
|
||||
apiConfiguration,
|
||||
version,
|
||||
customInstructions,
|
||||
setCustomInstructions,
|
||||
openRouterModels,
|
||||
telemetrySetting,
|
||||
setTelemetrySetting,
|
||||
} = useExtensionState()
|
||||
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
|
||||
const [modelIdErrorMessage, setModelIdErrorMessage] = useState<string | undefined>(undefined)
|
||||
|
||||
|
|
@ -29,6 +37,10 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|||
type: "customInstructions",
|
||||
text: customInstructions,
|
||||
})
|
||||
vscode.postMessage({
|
||||
type: "telemetrySetting",
|
||||
text: telemetrySetting,
|
||||
})
|
||||
onDone()
|
||||
}
|
||||
}
|
||||
|
|
@ -114,6 +126,33 @@ const SettingsView = ({ onDone }: SettingsViewProps) => {
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: 5 }}>
|
||||
<VSCodeCheckbox
|
||||
style={{ marginBottom: "5px" }}
|
||||
checked={telemetrySetting === "enabled"}
|
||||
onChange={(e: any) => {
|
||||
const checked = e.target.checked === true
|
||||
setTelemetrySetting(checked ? "enabled" : "disabled")
|
||||
}}>
|
||||
Allow anonymous error and usage reporting
|
||||
</VSCodeCheckbox>
|
||||
<p
|
||||
style={{
|
||||
fontSize: "12px",
|
||||
marginTop: "5px",
|
||||
color: "var(--vscode-descriptionForeground)",
|
||||
}}>
|
||||
Help improve Cline by sending anonymous usage data and error reports. No code, prompts, or personal
|
||||
information is ever sent. See our{" "}
|
||||
<VSCodeLink
|
||||
href="https://github.com/cline/cline/blob/main/docs/PRIVACY.md"
|
||||
style={{ fontSize: "inherit" }}>
|
||||
privacy policy
|
||||
</VSCodeLink>{" "}
|
||||
for more details.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{IS_DEV && (
|
||||
<>
|
||||
<div style={{ marginTop: "10px", marginBottom: "4px" }}>Debug</div>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { convertTextMateToHljs } from "../utils/textMateToHljs"
|
|||
import { vscode } from "../utils/vscode"
|
||||
import { DEFAULT_BROWSER_SETTINGS } from "../../../src/shared/BrowserSettings"
|
||||
import { DEFAULT_CHAT_SETTINGS } from "../../../src/shared/ChatSettings"
|
||||
import { TelemetrySetting } from "../../../src/shared/TelemetrySetting"
|
||||
|
||||
interface ExtensionStateContextType extends ExtensionState {
|
||||
didHydrateState: boolean
|
||||
|
|
@ -21,6 +22,7 @@ interface ExtensionStateContextType extends ExtensionState {
|
|||
filePaths: string[]
|
||||
setApiConfiguration: (config: ApiConfiguration) => void
|
||||
setCustomInstructions: (value?: string) => void
|
||||
setTelemetrySetting: (value: TelemetrySetting) => void
|
||||
setShowAnnouncement: (value: boolean) => void
|
||||
}
|
||||
|
||||
|
|
@ -39,7 +41,7 @@ export const ExtensionStateContextProvider: React.FC<{
|
|||
chatSettings: DEFAULT_CHAT_SETTINGS,
|
||||
isLoggedIn: false,
|
||||
platform: DEFAULT_PLATFORM,
|
||||
telemetryOptIn: null,
|
||||
telemetrySetting: "unset",
|
||||
})
|
||||
const [didHydrateState, setDidHydrateState] = useState(false)
|
||||
const [showWelcome, setShowWelcome] = useState(false)
|
||||
|
|
@ -158,6 +160,11 @@ export const ExtensionStateContextProvider: React.FC<{
|
|||
...prevState,
|
||||
customInstructions: value,
|
||||
})),
|
||||
setTelemetrySetting: (value) =>
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
telemetrySetting: value,
|
||||
})),
|
||||
setShowAnnouncement: (value) =>
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue