Skip to content

Commit 2052131

Browse files
wolfibDevtools-frontend LUCI CQ
authored andcommitted
Logging for AI conversations
This logs the type of conversation (freestyler, dr-jones-network,...) and whether they were initiated via the UI or via MCP. Corresponding Chromium CL: https://crrev.com/c/6568811 Bug: 417878946 Change-Id: I7ebd7a7b6487d63959e98ec5643bce6f94b599d2 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6574295 Reviewed-by: Danil Somsikov <dsv@chromium.org> Commit-Queue: Wolfgang Beyer <wolfi@chromium.org> Auto-Submit: Wolfgang Beyer <wolfi@chromium.org>
1 parent 02ec230 commit 2052131

File tree

8 files changed

+44
-3
lines changed

8 files changed

+44
-3
lines changed

front_end/core/host/InspectorFrontendHost.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import {
4949
Events,
5050
type EventTypes,
5151
type ExtensionDescriptor,
52+
type FunctionCallEvent,
5253
type HoverEvent,
5354
type ImpressionEvent,
5455
type InspectorFrontendHostAPI,
@@ -550,6 +551,8 @@ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
550551
}
551552
recordSettingAccess(_event: SettingAccessEvent): void {
552553
}
554+
recordFunctionCall(_event: FunctionCallEvent): void {
555+
}
553556
}
554557

555558
// @ts-expect-error Global injected by devtools_compatibility.js

front_end/core/host/InspectorFrontendHostAPI.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ export interface SettingAccessEvent {
206206
string_value?: number;
207207
}
208208

209+
export interface FunctionCallEvent {
210+
name: number;
211+
context?: number;
212+
}
213+
209214
// While `EventDescriptors` are used to dynamically dispatch host binding events,
210215
// the `EventTypes` "type map" is used for type-checking said events by TypeScript.
211216
// `EventTypes` is not used at runtime.
@@ -396,6 +401,7 @@ export interface InspectorFrontendHostAPI {
396401
recordChange(event: ChangeEvent): void;
397402
recordKeyDown(event: KeyDownEvent): void;
398403
recordSettingAccess(event: SettingAccessEvent): void;
404+
recordFunctionCall(event: FunctionCallEvent): void;
399405
}
400406

401407
export interface AcceleratorDescriptor {

front_end/panels/ai_assistance/AiAssistancePanel.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,9 @@ export class AiAssistancePanel extends UI.Panel.Panel {
14251425
type: multimodalInputType,
14261426
} :
14271427
undefined;
1428+
if (this.#conversation) {
1429+
void VisualLogging.logFunctionCall(`start-conversation-${this.#conversation.type}`, 'ui');
1430+
}
14281431
const runner = this.#conversationAgent.run(
14291432
text, {
14301433
signal,
@@ -1602,6 +1605,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
16021605
throw new Error(disabledReasons.join(' '));
16031606
}
16041607

1608+
void VisualLogging.logFunctionCall(`start-conversation-${conversationType}`, 'external');
16051609
switch (conversationType) {
16061610
case AiAssistanceModel.ConversationType.STYLING:
16071611
return await this.handleExternalStylingRequest(prompt, selector);

front_end/ui/visual_logging/Debugging.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ function processElementForDebugging(element: HTMLElement, loggingState: LoggingS
126126
}
127127
}
128128

129-
type EventType = 'Click'|'Drag'|'Hover'|'Change'|'KeyDown'|'Resize'|'SettingAccess';
129+
type EventType = 'Click'|'Drag'|'Hover'|'Change'|'KeyDown'|'Resize'|'SettingAccess'|'FunctionCall';
130130
export function processEventForDebugging(
131131
event: EventType, state: LoggingState|null, extraInfo?: EventAttributes): void {
132132
const format = localStorage.getItem('veDebugLoggingEnabled');
@@ -163,7 +163,7 @@ export function processEventForIntuitiveDebugging(
163163

164164
export function processEventForTestDebugging(
165165
event: EventType, state: LoggingState|null, _extraInfo?: EventAttributes): void {
166-
if (event !== 'SettingAccess') {
166+
if (event !== 'SettingAccess' && event !== 'FunctionCall') {
167167
lastImpressionLogEntry = null;
168168
}
169169
maybeLogDebugEvent(

front_end/ui/visual_logging/KnownContextValues.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3388,6 +3388,11 @@ export const knownContextValues = new Set([
33883388
'stalled',
33893389
'standard-emulated-device-list',
33903390
'start',
3391+
'start-conversation-drjones-file',
3392+
'start-conversation-drjones-network-request',
3393+
'start-conversation-drjones-performance',
3394+
'start-conversation-freestyler',
3395+
'start-conversation-performance-insight',
33913396
'start-new-chat',
33923397
'start-recording',
33933398
'start-time',

front_end/ui/visual_logging/LoggingEvents.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,4 +256,16 @@ describe('LoggingEvents', () => {
256256
assert.deepEqual(
257257
recordSettingAccess.lastCall.firstArg, {name: -1361026584, numeric_value: 123, string_value: undefined});
258258
});
259+
260+
it('calls UI binding to log a function call event', async () => {
261+
const recordFunctionCall = sinon.stub(
262+
Host.InspectorFrontendHost.InspectorFrontendHostInstance,
263+
'recordFunctionCall',
264+
);
265+
await VisualLogging.LoggingEvents.logFunctionCall('test-function', 'test-context');
266+
assert.deepEqual(recordFunctionCall.lastCall.firstArg, {name: -1470917656, context: 617717214});
267+
268+
await VisualLogging.LoggingEvents.logFunctionCall('test-function');
269+
assert.deepEqual(recordFunctionCall.lastCall.firstArg, {name: -1470917656, context: undefined});
270+
});
259271
});

front_end/ui/visual_logging/LoggingEvents.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,14 @@ export async function logSettingAccess(name: string, value: number|string|boolea
190190
Host.InspectorFrontendHost.InspectorFrontendHostInstance.recordSettingAccess(settingAccessEvent);
191191
processEventForDebugging('SettingAccess', null, {name, numericValue, stringValue});
192192
}
193+
194+
export async function logFunctionCall(name: string, context?: string): Promise<void> {
195+
const nameHash = await contextAsNumber(name);
196+
if (typeof nameHash === 'undefined') {
197+
return;
198+
}
199+
const functionCallEvent:
200+
Host.InspectorFrontendHostAPI.FunctionCallEvent = {name: nameHash, context: await contextAsNumber(context)};
201+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.recordFunctionCall(functionCallEvent);
202+
processEventForDebugging('FunctionCall', null, {name, context});
203+
}

front_end/ui/visual_logging/visual_logging.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import * as NonDomState from './NonDomState.js';
1111
export type Loggable = LoggableModule.Loggable;
1212
export {DebugLoggingFormat, setVeDebuggingEnabled, setVeDebugLoggingEnabled} from './Debugging.js';
1313
export {addDocument, startLogging, stopLogging} from './LoggingDriver.js';
14-
export {logImpressions, logSettingAccess} from './LoggingEvents.js';
14+
export {logImpressions, logSettingAccess, logFunctionCall} from './LoggingEvents.js';
1515
export const logClick = (loggable: Loggable, event: Event, options: {doubleClick?: boolean} = {}): void =>
1616
LoggingEvents.logClick(LoggingDriver.clickLogThrottler)(loggable, event, options);
1717

0 commit comments

Comments
 (0)