Skip to content

Commit d2782bc

Browse files
authored
chore(code): add permissions-related events (#1236)
## problem we don't have any analytics tracking on permission modes (current agent mode, mode swaps, plan mode approval options) ## changes adds events for: - session config changed (includes agent mode) - permission response - permission cancelled
1 parent d2896bc commit d2782bc

5 files changed

Lines changed: 91 additions & 3 deletions

File tree

apps/code/src/renderer/features/sessions/service/service.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,10 @@ vi.mock("@features/sidebar/hooks/useTaskViewed", () => ({
137137
},
138138
}));
139139

140-
vi.mock("@utils/analytics", () => ({ track: vi.fn() }));
140+
vi.mock("@utils/analytics", () => ({
141+
track: vi.fn(),
142+
buildPermissionToolMetadata: vi.fn(() => ({})),
143+
}));
141144
vi.mock("@utils/logger", () => ({
142145
logger: {
143146
scope: () => ({

apps/code/src/renderer/features/sessions/service/service.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import {
4040
import { ANALYTICS_EVENTS } from "@shared/types/analytics";
4141
import type { AcpMessage, StoredLogEntry } from "@shared/types/session-events";
4242
import { isJsonRpcRequest } from "@shared/types/session-events";
43-
import { track } from "@utils/analytics";
43+
import { buildPermissionToolMetadata, track } from "@utils/analytics";
4444
import { logger } from "@utils/logger";
4545
import {
4646
notifyPermissionRequest,
@@ -571,6 +571,8 @@ export class SessionService {
571571
track(ANALYTICS_EVENTS.TASK_RUN_STARTED, {
572572
task_id: taskId,
573573
execution_type: "local",
574+
initial_mode: executionMode,
575+
adapter,
574576
});
575577

576578
const preferredModel = model ?? DEFAULT_GATEWAY_MODEL;
@@ -1493,6 +1495,12 @@ export class SessionService {
14931495
return;
14941496
}
14951497

1498+
const permission = session.pendingPermissions.get(toolCallId);
1499+
track(ANALYTICS_EVENTS.PERMISSION_RESPONDED, {
1500+
task_id: taskId,
1501+
...buildPermissionToolMetadata(permission, optionId, customInput),
1502+
});
1503+
14961504
this.resolvePermission(session, toolCallId);
14971505

14981506
try {
@@ -1530,6 +1538,12 @@ export class SessionService {
15301538
return;
15311539
}
15321540

1541+
const permission = session.pendingPermissions.get(toolCallId);
1542+
track(ANALYTICS_EVENTS.PERMISSION_CANCELLED, {
1543+
task_id: taskId,
1544+
...buildPermissionToolMetadata(permission),
1545+
});
1546+
15331547
this.resolvePermission(session, toolCallId);
15341548

15351549
try {
@@ -1636,6 +1650,15 @@ export class SessionService {
16361650
return;
16371651
}
16381652

1653+
if (configOption.currentValue !== value) {
1654+
track(ANALYTICS_EVENTS.SESSION_CONFIG_CHANGED, {
1655+
task_id: taskId,
1656+
category,
1657+
from_value: configOption.currentValue,
1658+
to_value: value,
1659+
});
1660+
}
1661+
16391662
await this.setSessionConfigOption(taskId, configOption.id, value);
16401663
}
16411664

apps/code/src/renderer/utils/analytics.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import posthog from "posthog-js/dist/module.full.no-external";
33
// The module.full.no-external bundle includes rrweb but not the initSessionRecording function
44
// posthog-recorder (vs lazy-recorder) ensures recording is ready immediately
55
import "posthog-js/dist/posthog-recorder";
6+
import type { PermissionRequest } from "@renderer/features/sessions/utils/parseSessionLogs";
67
import type {
78
EventPropertyMap,
89
UserIdentifyProperties,
@@ -128,6 +129,29 @@ export function track<K extends keyof EventPropertyMap>(
128129
posthog.capture(eventName, args[0]);
129130
}
130131

132+
/**
133+
* Build tool metadata for analytics on permission requests
134+
*/
135+
export function buildPermissionToolMetadata(
136+
permission?: PermissionRequest,
137+
selectedOptionId?: string,
138+
customInput?: string,
139+
): Record<string, any> {
140+
const selectedOption = permission?.options?.find(
141+
(o) => o.optionId === selectedOptionId,
142+
);
143+
const rawInput = permission?.toolCall?.rawInput as
144+
| Record<string, unknown>
145+
| undefined;
146+
147+
return {
148+
tool_name: rawInput?.toolName,
149+
option_id: selectedOptionId,
150+
option_kind: selectedOption?.kind ?? "unknown",
151+
custom_input: customInput,
152+
};
153+
}
154+
131155
/**
132156
* Capture an exception for error tracking using PostHog's built-in exception tracking.
133157
*/

apps/code/src/shared/types/analytics.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ export interface TaskRunStartedProperties {
6464
task_id: string;
6565
execution_type: ExecutionType;
6666
model?: string;
67+
initial_mode?: string;
68+
adapter?: string;
6769
}
6870

6971
export interface TaskRunCompletedProperties {
@@ -151,6 +153,28 @@ export interface AgentSessionErrorProperties {
151153
error_type: string;
152154
}
153155

156+
// Permission events
157+
export interface PermissionRespondedProperties {
158+
task_id: string;
159+
tool_name?: string;
160+
option_id?: string;
161+
option_kind?: string;
162+
custom_input?: string;
163+
}
164+
165+
export interface PermissionCancelledProperties {
166+
task_id: string;
167+
tool_name?: string;
168+
}
169+
170+
// Session config events
171+
export interface SessionConfigChangedProperties {
172+
task_id: string;
173+
category: string;
174+
from_value: string;
175+
to_value: string;
176+
}
177+
154178
// Feedback events
155179
export interface TaskFeedbackProperties {
156180
task_id: string;
@@ -203,6 +227,13 @@ export const ANALYTICS_EVENTS = {
203227
COMMAND_MENU_ACTION: "Command menu action",
204228
COMMAND_CENTER_VIEWED: "Command center viewed",
205229

230+
// Permission events
231+
PERMISSION_RESPONDED: "Permission responded",
232+
PERMISSION_CANCELLED: "Permission cancelled",
233+
234+
// Session config events
235+
SESSION_CONFIG_CHANGED: "Session config changed",
236+
206237
// Settings events
207238
SETTING_CHANGED: "Setting changed",
208239

@@ -249,6 +280,13 @@ export type EventPropertyMap = {
249280
[ANALYTICS_EVENTS.COMMAND_MENU_ACTION]: CommandMenuActionProperties;
250281
[ANALYTICS_EVENTS.COMMAND_CENTER_VIEWED]: never;
251282

283+
// Permission events
284+
[ANALYTICS_EVENTS.PERMISSION_RESPONDED]: PermissionRespondedProperties;
285+
[ANALYTICS_EVENTS.PERMISSION_CANCELLED]: PermissionCancelledProperties;
286+
287+
// Session config events
288+
[ANALYTICS_EVENTS.SESSION_CONFIG_CHANGED]: SessionConfigChangedProperties;
289+
252290
// Settings events
253291
[ANALYTICS_EVENTS.SETTING_CHANGED]: SettingChangedProperties;
254292

packages/agent/src/adapters/claude/permissions/permission-handlers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ async function handleDefaultPermissionFlow(
356356
kind: toolInfo.kind,
357357
content: toolInfo.content,
358358
locations: toolInfo.locations,
359-
rawInput: toolInput as Record<string, unknown>,
359+
rawInput: { ...(toolInput as Record<string, unknown>), toolName },
360360
},
361361
});
362362

0 commit comments

Comments
 (0)