mirror of
https://github.com/cline/cline.git
synced 2026-09-08 22:13:11 +08:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e038d3b150 | ||
|
|
b9551c960a | ||
|
|
f2ffe26aaf |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Use identify to enhance distinct user segmentation
|
||||
@@ -1,5 +1,9 @@
|
||||
# Changelog
|
||||
|
||||
## [3.17.5]
|
||||
|
||||
- Fix issue with Claude 4 models where after several conversation turns, it would start making invalid diff edits
|
||||
|
||||
## [3.17.4]
|
||||
|
||||
- Fix thinking budget slider for Claude 4
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"name": "claude-dev",
|
||||
"displayName": "Cline",
|
||||
"description": "Autonomous coding agent right in your IDE, capable of creating/editing files, running commands, using the browser, and more with your permission every step of the way.",
|
||||
"version": "3.17.4",
|
||||
"version": "3.17.5",
|
||||
"icon": "assets/icons/icon.png",
|
||||
"engines": {
|
||||
"vscode": "^1.84.0"
|
||||
|
||||
@@ -261,13 +261,6 @@ export class Controller {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// If user already opted in to telemetry, enable telemetry service
|
||||
this.getStateToPostToWebview().then((state) => {
|
||||
const { telemetrySetting } = state
|
||||
const isOptedIn = telemetrySetting !== "disabled"
|
||||
telemetryService.updateTelemetryState(isOptedIn)
|
||||
})
|
||||
break
|
||||
case "showChatView": {
|
||||
this.postMessageToWebview({
|
||||
@@ -810,6 +803,7 @@ export class Controller {
|
||||
const response = await axios.get("https://api.cline.bot/v1/mcp/marketplace", {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": "cline-vscode-extension",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1287,7 +1281,7 @@ export class Controller {
|
||||
telemetrySetting,
|
||||
planActSeparateModelsSetting,
|
||||
enableCheckpointsSetting: enableCheckpointsSetting ?? true,
|
||||
vscMachineId: vscode.env.machineId,
|
||||
distinctId: telemetryService.distinctId,
|
||||
globalClineRulesToggles: globalClineRulesToggles || {},
|
||||
localClineRulesToggles: localClineRulesToggles || {},
|
||||
localWindsurfRulesToggles: localWindsurfRulesToggles || {},
|
||||
|
||||
@@ -196,7 +196,7 @@ Otherwise, if you have not completed the task and do not need additional informa
|
||||
`${newProblemsMessage}`,
|
||||
|
||||
diffError: (relPath: string, originalContent: string | undefined) =>
|
||||
`This is likely because the SEARCH block content doesn't match exactly with what's in the file, or if you used multiple SEARCH/REPLACE blocks they may not have been in the order they appear in the file.\n\n` +
|
||||
`This is likely because the SEARCH block content doesn't match exactly with what's in the file, or if you used multiple SEARCH/REPLACE blocks they may not have been in the order they appear in the file. (Please also ensure that when using the replace_in_file tool, Do NOT add extra characters to the markers (e.g., <<<<<<< SEARCH> is INVALID). Do NOT forget to use the closing >>>>>>> REPLACE marker. Do NOT modify the marker format in any way. Malformed XML will cause complete tool failure and break the entire editing process.)\n\n` +
|
||||
`The file was reverted to its original state:\n\n` +
|
||||
`<file_content path="${relPath.toPosix()}">\n${originalContent}\n</file_content>\n\n` +
|
||||
`Now that you have the latest state of the file, try the operation again with fewer, more precise SEARCH blocks. For large files especially, it may be prudent to try to limit yourself to <5 SEARCH/REPLACE blocks at a time, then wait for the user to respond with the result of the operation before following up with another replace_in_file call to make additional edits.\n(If you run into this error 3 times in a row, you may use the write_to_file tool as a fallback.)`,
|
||||
|
||||
@@ -14,6 +14,7 @@ import { Controller } from "./core/controller"
|
||||
import { ErrorService } from "./services/error/ErrorService"
|
||||
import { initializeTestMode, cleanupTestMode } from "./services/test/TestMode"
|
||||
import { telemetryService } from "./services/posthog/telemetry/TelemetryService"
|
||||
import { v4 as uuidv4 } from "uuid"
|
||||
|
||||
/*
|
||||
Built using https://github.com/microsoft/vscode-webview-ui-toolkit
|
||||
@@ -75,6 +76,16 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
console.error(`Error during post-update actions: ${errorMessage}, Stack trace: ${error.stack}`)
|
||||
}
|
||||
|
||||
// backup id in case vscMachineID doesn't work
|
||||
let installId = context.globalState.get<string>("installId")
|
||||
|
||||
if (!installId) {
|
||||
installId = uuidv4()
|
||||
await context.globalState.update("installId", installId)
|
||||
}
|
||||
|
||||
telemetryService.captureExtensionActivated(installId)
|
||||
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand("cline.plusButtonClicked", async (webview: any) => {
|
||||
const openChat = async (instance?: WebviewProvider) => {
|
||||
|
||||
@@ -9,7 +9,6 @@ class PostHogClientProvider {
|
||||
this.client = new PostHog(posthogConfig.apiKey, {
|
||||
host: posthogConfig.host,
|
||||
enableExceptionAutocapture: false,
|
||||
defaultOptIn: false,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { BrowserSettings } from "@shared/BrowserSettings"
|
||||
import { posthogClientProvider } from "../PostHogClientProvider"
|
||||
|
||||
/**
|
||||
* PostHogClient handles telemetry event tracking for the Cline extension
|
||||
* TelemetryService handles telemetry event tracking for the Cline extension
|
||||
* Uses PostHog analytics to track user interactions and system events
|
||||
* Respects user privacy settings and VSCode's global telemetry configuration
|
||||
*/
|
||||
@@ -29,7 +29,7 @@ interface Collection {
|
||||
*/
|
||||
type TelemetryCategory = "checkpoints" | "browser"
|
||||
|
||||
class PostHogClient {
|
||||
class TelemetryService {
|
||||
// Map to control specific telemetry categories (event types)
|
||||
private telemetryCategoryEnabled: Map<TelemetryCategory, boolean> = new Map([
|
||||
["checkpoints", false], // Checkpoints telemetry disabled
|
||||
@@ -41,6 +41,11 @@ class PostHogClient {
|
||||
// Event constants for tracking user interactions and system events
|
||||
private static readonly EVENTS = {
|
||||
// Task-related events for tracking conversation and execution flow
|
||||
|
||||
USER: {
|
||||
OPT_OUT: "user.opt_out",
|
||||
EXTENSION_ACTIVATED: "user.extension_activated",
|
||||
},
|
||||
TASK: {
|
||||
// Tracks when a new task/conversation is started
|
||||
CREATED: "task.created",
|
||||
@@ -83,37 +88,19 @@ class PostHogClient {
|
||||
},
|
||||
// UI interaction events for tracking user engagement
|
||||
UI: {
|
||||
// Tracks when user switches between API providers
|
||||
PROVIDER_SWITCH: "ui.provider_switch",
|
||||
// Tracks when images are attached to a conversation
|
||||
IMAGE_ATTACHED: "ui.image_attached",
|
||||
// Tracks general button click interactions
|
||||
BUTTON_CLICK: "ui.button_click",
|
||||
// Tracks when the marketplace view is opened
|
||||
MARKETPLACE_OPENED: "ui.marketplace_opened",
|
||||
// Tracks when settings panel is opened
|
||||
SETTINGS_OPENED: "ui.settings_opened",
|
||||
// Tracks when task history view is opened
|
||||
HISTORY_OPENED: "ui.history_opened",
|
||||
// Tracks when a task is removed from history
|
||||
TASK_POPPED: "ui.task_popped",
|
||||
// Tracks when a different model is selected
|
||||
MODEL_SELECTED: "ui.model_selected",
|
||||
// Tracks when planning mode is toggled on
|
||||
PLAN_MODE_TOGGLED: "ui.plan_mode_toggled",
|
||||
// Tracks when action mode is toggled on
|
||||
ACT_MODE_TOGGLED: "ui.act_mode_toggled",
|
||||
// Tracks when users use the "favorite" button in the model picker
|
||||
MODEL_FAVORITE_TOGGLED: "ui.model_favorite_toggled",
|
||||
},
|
||||
}
|
||||
|
||||
/** Singleton instance of the PostHogClient */
|
||||
private static instance: PostHogClient
|
||||
/** Singleton instance of the TelemetryService */
|
||||
private static instance: TelemetryService
|
||||
/** PostHog client instance for sending analytics events */
|
||||
private client: PostHog
|
||||
/** Unique identifier for the current VSCode instance */
|
||||
private distinctId: string = vscode.env.machineId
|
||||
public distinctId: string = vscode.env.machineId
|
||||
/** Whether telemetry is currently enabled based on user and VSCode settings */
|
||||
private telemetryEnabled: boolean = false
|
||||
/** Current version of the extension */
|
||||
@@ -129,14 +116,18 @@ class PostHogClient {
|
||||
this.client = posthogClientProvider.getClient()
|
||||
}
|
||||
|
||||
private setDistinctId(installId: string) {
|
||||
if (this.distinctId === "someValue.machineId") {
|
||||
this.distinctId = installId
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the telemetry state based on user preferences and VSCode settings
|
||||
* Only enables telemetry if both VSCode global telemetry is enabled and user has opted in
|
||||
* @param didUserOptIn Whether the user has explicitly opted into telemetry
|
||||
*/
|
||||
public updateTelemetryState(didUserOptIn: boolean): void {
|
||||
this.telemetryEnabled = false
|
||||
|
||||
public async updateTelemetryState(didUserOptIn: boolean): Promise<void> {
|
||||
// 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"
|
||||
@@ -144,25 +135,53 @@ class PostHogClient {
|
||||
// We only enable telemetry if global vscode telemetry is enabled
|
||||
if (globalTelemetryEnabled) {
|
||||
this.telemetryEnabled = didUserOptIn
|
||||
} else {
|
||||
// Show warning to user that global telemetry is disabled
|
||||
void vscode.window
|
||||
.showWarningMessage(
|
||||
"VSCode telemetry is disabled. To enable telemetry for this extension, first enable VSCode telemetry in settings.",
|
||||
"Open Settings",
|
||||
)
|
||||
.then((selection) => {
|
||||
if (selection === "Open Settings") {
|
||||
void vscode.commands.executeCommand("workbench.action.openSettings", "telemetry.telemetryLevel")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Update PostHog client state based on telemetry preference
|
||||
if (this.telemetryEnabled) {
|
||||
this.client.optIn()
|
||||
this.client.identify({ distinctId: this.distinctId })
|
||||
} else {
|
||||
this.client.capture({
|
||||
distinctId: this.distinctId,
|
||||
event: TelemetryService.EVENTS.USER.OPT_OUT,
|
||||
properties: this.addProperties({}),
|
||||
})
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000)) // Delay 1 second before opting out
|
||||
this.client.optOut()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets or creates the singleton instance of PostHogClient
|
||||
* @returns The PostHogClient instance
|
||||
* Gets or creates the singleton instance of TelemetryService
|
||||
* @returns The TelemetryService instance
|
||||
*/
|
||||
public static getInstance(): PostHogClient {
|
||||
if (!PostHogClient.instance) {
|
||||
PostHogClient.instance = new PostHogClient()
|
||||
public static getInstance(): TelemetryService {
|
||||
if (!TelemetryService.instance) {
|
||||
TelemetryService.instance = new TelemetryService()
|
||||
}
|
||||
return TelemetryService.instance
|
||||
}
|
||||
|
||||
private addProperties(properties: any): any {
|
||||
return {
|
||||
...properties,
|
||||
extension_version: this.version,
|
||||
is_dev: this.isDev,
|
||||
}
|
||||
return PostHogClient.instance
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,13 +190,14 @@ class PostHogClient {
|
||||
* @param collect If true, store the event in collectedEvents instead of sending to PostHog
|
||||
*/
|
||||
public capture(event: { event: string; properties?: any }, collect: boolean = false): void {
|
||||
const taskId = event.properties.taskId
|
||||
const propertiesWithVersion = {
|
||||
...event.properties,
|
||||
extension_version: this.version,
|
||||
is_dev: this.isDev,
|
||||
if (!this.telemetryEnabled) {
|
||||
return
|
||||
}
|
||||
if (collect) {
|
||||
const taskId = event.properties.taskId
|
||||
|
||||
const propertiesWithVersion = this.addProperties(event.properties)
|
||||
|
||||
if (collect && taskId) {
|
||||
const existingTask = this.collectedTasks.find((task) => task.taskId === taskId)
|
||||
if (existingTask) {
|
||||
existingTask.collection.push({
|
||||
@@ -195,11 +215,20 @@ class PostHogClient {
|
||||
],
|
||||
})
|
||||
}
|
||||
} else if (this.telemetryEnabled) {
|
||||
} else {
|
||||
this.client.capture({ distinctId: this.distinctId, event: event.event, properties: propertiesWithVersion })
|
||||
}
|
||||
}
|
||||
|
||||
public captureExtensionActivated(installId: string) {
|
||||
this.setDistinctId(installId)
|
||||
|
||||
if (this.telemetryEnabled) {
|
||||
this.client.identify({ distinctId: this.distinctId })
|
||||
this.client.capture({ distinctId: this.distinctId, event: TelemetryService.EVENTS.USER.EXTENSION_ACTIVATED })
|
||||
}
|
||||
}
|
||||
|
||||
// Task events
|
||||
/**
|
||||
* Records when a new task/conversation is started
|
||||
@@ -210,7 +239,7 @@ class PostHogClient {
|
||||
public captureTaskCreated(taskId: string, apiProvider?: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.CREATED,
|
||||
event: TelemetryService.EVENTS.TASK.CREATED,
|
||||
properties: { taskId, apiProvider },
|
||||
},
|
||||
collect,
|
||||
@@ -226,7 +255,7 @@ class PostHogClient {
|
||||
public captureTaskRestarted(taskId: string, apiProvider?: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.RESTARTED,
|
||||
event: TelemetryService.EVENTS.TASK.RESTARTED,
|
||||
properties: { taskId, apiProvider },
|
||||
},
|
||||
collect,
|
||||
@@ -241,7 +270,7 @@ class PostHogClient {
|
||||
public captureTaskCompleted(taskId: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.COMPLETED,
|
||||
event: TelemetryService.EVENTS.TASK.COMPLETED,
|
||||
properties: { taskId },
|
||||
},
|
||||
collect,
|
||||
@@ -278,7 +307,7 @@ class PostHogClient {
|
||||
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.CONVERSATION_TURN,
|
||||
event: TelemetryService.EVENTS.TASK.CONVERSATION_TURN,
|
||||
properties,
|
||||
},
|
||||
collect,
|
||||
@@ -295,7 +324,7 @@ class PostHogClient {
|
||||
public captureTokenUsage(taskId: string, tokensIn: number, tokensOut: number, model: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.TOKEN_USAGE,
|
||||
event: TelemetryService.EVENTS.TASK.TOKEN_USAGE,
|
||||
properties: {
|
||||
taskId,
|
||||
tokensIn,
|
||||
@@ -315,7 +344,7 @@ class PostHogClient {
|
||||
public captureModeSwitch(taskId: string, mode: "plan" | "act", collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.MODE_SWITCH,
|
||||
event: TelemetryService.EVENTS.TASK.MODE_SWITCH,
|
||||
properties: {
|
||||
taskId,
|
||||
mode,
|
||||
@@ -334,7 +363,7 @@ class PostHogClient {
|
||||
console.info("TelemetryService: Capturing task feedback", { taskId, feedbackType })
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.FEEDBACK,
|
||||
event: TelemetryService.EVENTS.TASK.FEEDBACK,
|
||||
properties: {
|
||||
taskId,
|
||||
feedbackType,
|
||||
@@ -355,7 +384,7 @@ class PostHogClient {
|
||||
public captureToolUsage(taskId: string, tool: string, autoApproved: boolean, success: boolean, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.TOOL_USED,
|
||||
event: TelemetryService.EVENTS.TASK.TOOL_USED,
|
||||
properties: {
|
||||
taskId,
|
||||
tool,
|
||||
@@ -385,7 +414,7 @@ class PostHogClient {
|
||||
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.CHECKPOINT_USED,
|
||||
event: TelemetryService.EVENTS.TASK.CHECKPOINT_USED,
|
||||
properties: {
|
||||
taskId,
|
||||
action,
|
||||
@@ -396,135 +425,6 @@ class PostHogClient {
|
||||
)
|
||||
}
|
||||
|
||||
// UI events
|
||||
/**
|
||||
* Records when the user switches between different API providers
|
||||
* @param from Previous provider name
|
||||
* @param to New provider name
|
||||
* @param location Where the switch occurred (settings panel or bottom bar)
|
||||
* @param taskId Optional task identifier if switch occurred during a task
|
||||
*/
|
||||
public captureProviderSwitch(
|
||||
from: string,
|
||||
to: string,
|
||||
location: "settings" | "bottom",
|
||||
taskId?: string,
|
||||
collect: boolean = false,
|
||||
) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.UI.PROVIDER_SWITCH,
|
||||
properties: {
|
||||
from,
|
||||
to,
|
||||
location,
|
||||
taskId,
|
||||
},
|
||||
},
|
||||
collect,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Records when images are attached to a conversation
|
||||
* @param taskId Unique identifier for the task
|
||||
* @param imageCount Number of images attached
|
||||
*/
|
||||
public captureImageAttached(taskId: string, imageCount: number, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.UI.IMAGE_ATTACHED,
|
||||
properties: {
|
||||
taskId,
|
||||
imageCount,
|
||||
},
|
||||
},
|
||||
collect,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Records general button click interactions in the UI
|
||||
* @param button Identifier for the button that was clicked
|
||||
* @param taskId Optional task identifier if click occurred during a task
|
||||
*/
|
||||
public captureButtonClick(button: string, taskId?: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.UI.BUTTON_CLICK,
|
||||
properties: {
|
||||
button,
|
||||
taskId,
|
||||
},
|
||||
},
|
||||
collect,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Records when the marketplace view is opened
|
||||
* @param taskId Optional task identifier if marketplace was opened during a task
|
||||
*/
|
||||
public captureMarketplaceOpened(taskId?: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.UI.MARKETPLACE_OPENED,
|
||||
properties: {
|
||||
taskId,
|
||||
},
|
||||
},
|
||||
collect,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Records when the settings panel is opened
|
||||
* @param taskId Optional task identifier if settings were opened during a task
|
||||
*/
|
||||
public captureSettingsOpened(taskId?: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.UI.SETTINGS_OPENED,
|
||||
properties: {
|
||||
taskId,
|
||||
},
|
||||
},
|
||||
collect,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Records when the task history view is opened
|
||||
* @param taskId Optional task identifier if history was opened during a task
|
||||
*/
|
||||
public captureHistoryOpened(taskId?: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.UI.HISTORY_OPENED,
|
||||
properties: {
|
||||
taskId,
|
||||
},
|
||||
},
|
||||
collect,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Records when a task is removed from the task history
|
||||
* @param taskId Unique identifier for the task being removed
|
||||
*/
|
||||
public captureTaskPopped(taskId: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.UI.TASK_POPPED,
|
||||
properties: {
|
||||
taskId,
|
||||
},
|
||||
},
|
||||
collect,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Records when a diff edit (replace_in_file) operation fails
|
||||
* @param taskId Unique identifier for the task
|
||||
@@ -533,7 +433,7 @@ class PostHogClient {
|
||||
public captureDiffEditFailure(taskId: string, modelId: string, errorType?: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.DIFF_EDIT_FAILED,
|
||||
event: TelemetryService.EVENTS.TASK.DIFF_EDIT_FAILED,
|
||||
properties: {
|
||||
taskId,
|
||||
errorType,
|
||||
@@ -553,7 +453,7 @@ class PostHogClient {
|
||||
public captureModelSelected(model: string, provider: string, taskId?: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.UI.MODEL_SELECTED,
|
||||
event: TelemetryService.EVENTS.UI.MODEL_SELECTED,
|
||||
properties: {
|
||||
model,
|
||||
provider,
|
||||
@@ -571,7 +471,7 @@ class PostHogClient {
|
||||
public captureHistoricalTaskLoaded(taskId: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.HISTORICAL_LOADED,
|
||||
event: TelemetryService.EVENTS.TASK.HISTORICAL_LOADED,
|
||||
properties: {
|
||||
taskId,
|
||||
},
|
||||
@@ -587,7 +487,7 @@ class PostHogClient {
|
||||
public captureRetryClicked(taskId: string, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.RETRY_CLICKED,
|
||||
event: TelemetryService.EVENTS.TASK.RETRY_CLICKED,
|
||||
properties: {
|
||||
taskId,
|
||||
},
|
||||
@@ -608,7 +508,7 @@ class PostHogClient {
|
||||
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.BROWSER_TOOL_START,
|
||||
event: TelemetryService.EVENTS.TASK.BROWSER_TOOL_START,
|
||||
properties: {
|
||||
taskId,
|
||||
viewport: browserSettings.viewport,
|
||||
@@ -641,7 +541,7 @@ class PostHogClient {
|
||||
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.BROWSER_TOOL_END,
|
||||
event: TelemetryService.EVENTS.TASK.BROWSER_TOOL_END,
|
||||
properties: {
|
||||
taskId,
|
||||
actionCount: stats.actionCount,
|
||||
@@ -679,7 +579,7 @@ class PostHogClient {
|
||||
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.BROWSER_ERROR,
|
||||
event: TelemetryService.EVENTS.TASK.BROWSER_ERROR,
|
||||
properties: {
|
||||
taskId,
|
||||
errorType,
|
||||
@@ -701,7 +601,7 @@ class PostHogClient {
|
||||
public captureOptionSelected(taskId: string, qty: number, mode: "plan" | "act", collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.OPTION_SELECTED,
|
||||
event: TelemetryService.EVENTS.TASK.OPTION_SELECTED,
|
||||
properties: {
|
||||
taskId,
|
||||
qty,
|
||||
@@ -721,7 +621,7 @@ class PostHogClient {
|
||||
public captureOptionsIgnored(taskId: string, qty: number, mode: "plan" | "act", collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.OPTIONS_IGNORED,
|
||||
event: TelemetryService.EVENTS.TASK.OPTIONS_IGNORED,
|
||||
properties: {
|
||||
taskId,
|
||||
qty,
|
||||
@@ -758,7 +658,7 @@ class PostHogClient {
|
||||
) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.GEMINI_API_PERFORMANCE,
|
||||
event: TelemetryService.EVENTS.TASK.GEMINI_API_PERFORMANCE,
|
||||
properties: {
|
||||
taskId,
|
||||
modelId,
|
||||
@@ -777,7 +677,7 @@ class PostHogClient {
|
||||
public captureModelFavoritesUsage(model: string, isFavorited: boolean, collect: boolean = false) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.UI.MODEL_FAVORITE_TOGGLED,
|
||||
event: TelemetryService.EVENTS.UI.MODEL_FAVORITE_TOGGLED,
|
||||
properties: {
|
||||
model,
|
||||
isFavorited,
|
||||
@@ -806,13 +706,17 @@ class PostHogClient {
|
||||
}
|
||||
|
||||
public async sendCollectedEvents(taskId?: string): Promise<void> {
|
||||
if (!this.telemetryEnabled) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.collectedTasks.length > 0) {
|
||||
if (taskId) {
|
||||
const task = this.collectedTasks.find((t) => t.taskId === taskId)
|
||||
if (task) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.TASK_COLLECTION,
|
||||
event: TelemetryService.EVENTS.TASK.TASK_COLLECTION,
|
||||
properties: { taskId, events: task.collection },
|
||||
},
|
||||
false,
|
||||
@@ -823,7 +727,7 @@ class PostHogClient {
|
||||
for (const task of this.collectedTasks) {
|
||||
this.capture(
|
||||
{
|
||||
event: PostHogClient.EVENTS.TASK.TASK_COLLECTION,
|
||||
event: TelemetryService.EVENTS.TASK.TASK_COLLECTION,
|
||||
properties: { taskId: task.taskId, events: task.collection },
|
||||
},
|
||||
false,
|
||||
@@ -839,4 +743,4 @@ class PostHogClient {
|
||||
}
|
||||
}
|
||||
|
||||
export const telemetryService = PostHogClient.getInstance()
|
||||
export const telemetryService = TelemetryService.getInstance()
|
||||
|
||||
@@ -137,7 +137,7 @@ export interface ExtensionState {
|
||||
photoURL: string | null
|
||||
}
|
||||
version: string
|
||||
vscMachineId: string
|
||||
distinctId: string
|
||||
globalClineRulesToggles: ClineRulesToggles
|
||||
localClineRulesToggles: ClineRulesToggles
|
||||
localWorkflowToggles: ClineRulesToggles
|
||||
|
||||
@@ -5,32 +5,44 @@ import { posthogConfig } from "@shared/services/config/posthog-config"
|
||||
import { useExtensionState } from "./context/ExtensionStateContext"
|
||||
|
||||
export function CustomPostHogProvider({ children }: { children: ReactNode }) {
|
||||
const { telemetrySetting, vscMachineId } = useExtensionState()
|
||||
const { telemetrySetting, distinctId, version } = useExtensionState()
|
||||
const isTelemetryEnabled = telemetrySetting !== "disabled"
|
||||
|
||||
useEffect(() => {
|
||||
if (vscMachineId.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
posthog.init(posthogConfig.apiKey, {
|
||||
api_host: posthogConfig.host,
|
||||
ui_host: posthogConfig.uiHost,
|
||||
opt_out_capturing_by_default: true,
|
||||
disable_session_recording: true,
|
||||
capture_pageview: false,
|
||||
capture_dead_clicks: true,
|
||||
bootstrap: {
|
||||
distinctID: vscMachineId,
|
||||
})
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (distinctId.length === 0 || version.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
posthog.set_config({
|
||||
before_send: (payload: any) => {
|
||||
if (payload?.properties) {
|
||||
payload.properties.extension_version = version
|
||||
payload.properties.distinct_id = distinctId
|
||||
}
|
||||
return payload
|
||||
},
|
||||
})
|
||||
|
||||
if (isTelemetryEnabled) {
|
||||
const optedIn = posthog.has_opted_in_capturing()
|
||||
const optedOut = posthog.has_opted_out_capturing()
|
||||
|
||||
if (isTelemetryEnabled && !optedIn) {
|
||||
posthog.opt_in_capturing()
|
||||
} else {
|
||||
posthog.identify(distinctId)
|
||||
} else if (!isTelemetryEnabled && !optedOut) {
|
||||
posthog.opt_out_capturing()
|
||||
}
|
||||
}, [isTelemetryEnabled, vscMachineId])
|
||||
}, [isTelemetryEnabled, distinctId, version])
|
||||
|
||||
return <PostHogProvider client={posthog}>{children}</PostHogProvider>
|
||||
}
|
||||
|
||||
@@ -607,7 +607,7 @@ const SettingsView = ({ onDone, targetSection }: SettingsViewProps) => {
|
||||
<div className="mb-[5px]">
|
||||
<VSCodeCheckbox
|
||||
className="mb-[5px]"
|
||||
checked={telemetrySetting === "enabled"}
|
||||
checked={telemetrySetting !== "disabled"}
|
||||
onChange={(e: any) => {
|
||||
const checked = e.target.checked === true
|
||||
setTelemetrySetting(checked ? "enabled" : "disabled")
|
||||
|
||||
@@ -156,7 +156,7 @@ export const ExtensionStateContextProvider: React.FC<{
|
||||
chatSettings: DEFAULT_CHAT_SETTINGS,
|
||||
platform: DEFAULT_PLATFORM,
|
||||
telemetrySetting: "unset",
|
||||
vscMachineId: "",
|
||||
distinctId: "",
|
||||
planActSeparateModelsSetting: true,
|
||||
enableCheckpointsSetting: true,
|
||||
globalClineRulesToggles: {},
|
||||
|
||||
Reference in New Issue
Block a user