chore(telemetry): catalogue desktop.marketplace.install in CORE_TELEMETRY_EVENTS

The sidecar emits the install event through a typed helper beside the
constant, as the other events do, so the name and fields cannot drift.
This commit is contained in:
Mikołaj Kondratek
2026-10-19 21:50:19 +02:00
parent 77d7f019ef
commit 2f64fcb26a
4 changed files with 82 additions and 20 deletions
@@ -1,20 +1,11 @@
import type { ITelemetryService, TelemetryProperties } from "@cline/shared";
import {
captureMarketplaceInstall,
type MarketplaceInstallProperties,
} from "@cline/core";
import type { ITelemetryService } from "@cline/shared";
import type { JsonRecord } from "./types";
export type MarketplaceInstallOutcome =
| "installed"
| "already_installed"
| "failed";
export interface MarketplaceInstallEvent {
type: string;
outcome: MarketplaceInstallOutcome;
/** Which path produced the outcome: skills-cli, github-download, already-installed. */
method?: string;
/** Coarse class of the skills CLI failure, when one happened. */
cli_failure?: string;
fallback_failed?: boolean;
}
export type MarketplaceInstallEvent = MarketplaceInstallProperties;
/** The marketplace entry type a desktop install request asked for. */
export function requestedMarketplaceType(
@@ -66,11 +57,7 @@ export function captureMarketplaceInstallEvent(
): void {
try {
if (!telemetry?.isEnabled()) return;
const properties: TelemetryProperties = {};
for (const [key, value] of Object.entries(event)) {
if (value !== undefined) properties[key] = value;
}
telemetry.capture({ event: "desktop.marketplace.install", properties });
captureMarketplaceInstall(telemetry, event);
} catch {
// Product interactions must continue if the telemetry provider fails.
}
+2
View File
@@ -791,6 +791,7 @@ export type {
CaptureCompactionExecutedProperties,
CaptureCompactionSkippedProperties,
GitSnapshotProperties,
MarketplaceInstallProperties,
TelemetryAgentIdentityProperties,
TelemetryAgentKind,
TelemetryCompactionMode,
@@ -816,6 +817,7 @@ export {
captureExtensionActivated,
captureGitSnapshot,
captureHookDiscovery,
captureMarketplaceInstall,
captureMentionFailed,
captureMentionSearchResults,
captureMentionUsed,
@@ -17,6 +17,7 @@ import {
captureCompactionSkipped,
captureExtensionActivated,
captureGitSnapshot,
captureMarketplaceInstall,
captureMistakeLimitReached,
captureProviderConfigured,
captureRunCommandsTimeout,
@@ -1072,3 +1073,39 @@ test("scheduler telemetry allowlists diagnostics and tolerates capture failures"
expect(() => captureScheduleRun(telemetry, input)).not.toThrow();
expect(() => captureScheduleRun(undefined, input)).not.toThrow();
});
describe("captureMarketplaceInstall", () => {
test("emits desktop.marketplace.install with only the defined fields", () => {
const capture = vi.fn();
const telemetry = { capture } as unknown as Parameters<
typeof captureMarketplaceInstall
>[0];
captureMarketplaceInstall(telemetry, {
type: "skill",
outcome: "failed",
method: "github-download",
cli_failure: "git-missing",
fallback_failed: true,
});
captureMarketplaceInstall(telemetry, { type: "mcp", outcome: "installed" });
expect(CORE_TELEMETRY_EVENTS.DESKTOP.MARKETPLACE_INSTALL).toBe(
"desktop.marketplace.install",
);
expect(capture).toHaveBeenNthCalledWith(1, {
event: "desktop.marketplace.install",
properties: {
type: "skill",
outcome: "failed",
method: "github-download",
cli_failure: "git-missing",
fallback_failed: true,
},
});
expect(capture).toHaveBeenNthCalledWith(2, {
event: "desktop.marketplace.install",
properties: { type: "mcp", outcome: "installed" },
});
});
});
@@ -105,6 +105,9 @@ export const CORE_TELEMETRY_EVENTS = {
INIT_ERROR: "workspace.init_error",
PATH_RESOLVED: "workspace.path_resolved",
},
DESKTOP: {
MARKETPLACE_INSTALL: "desktop.marketplace.install",
},
SDK: {
ERROR: SDK_ERROR_TELEMETRY_EVENT,
TOOL_TIMEOUT: "sdk.tool_timeout",
@@ -297,6 +300,39 @@ export function captureWorkspacePathResolved(
});
}
export interface MarketplaceInstallProperties {
/** Marketplace entry type: skill, plugin, mcp. */
type: string;
outcome: "installed" | "already_installed" | "failed";
/** Path that produced the outcome: skills-cli, github-download, already-installed. */
method?: string;
/** Coarse class of a skills CLI failure: npx-missing, node-too-old, git-missing, other. */
cli_failure?: string;
fallback_failed?: boolean;
}
/**
* One event per Desktop marketplace install attempt. Only coarse classes are
* sent, never CLI output, so the payload cannot carry paths or tokens.
*/
export function captureMarketplaceInstall(
telemetry: ITelemetryService | undefined,
properties: MarketplaceInstallProperties,
): void {
const payload: TelemetryProperties = {
type: properties.type,
outcome: properties.outcome,
};
if (properties.method !== undefined) payload.method = properties.method;
if (properties.cli_failure !== undefined) {
payload.cli_failure = properties.cli_failure;
}
if (properties.fallback_failed !== undefined) {
payload.fallback_failed = properties.fallback_failed;
}
emit(telemetry, CORE_TELEMETRY_EVENTS.DESKTOP.MARKETPLACE_INSTALL, payload);
}
export function captureAuthStarted(
telemetry: ITelemetryService | undefined,
provider?: string,