chrome-devtools-frontend 1.0.1642899 → 1.0.1643855
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/eslint.config.mjs +3 -1
- package/extension-api/ExtensionAPI.d.ts +83 -12
- package/front_end/core/host/UserMetrics.ts +0 -1
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/core/root/ExperimentNames.ts +0 -1
- package/front_end/core/sdk/ConsoleModel.ts +4 -0
- package/front_end/core/sdk/NetworkRequest.ts +12 -0
- package/front_end/core/sdk/SourceMap.ts +15 -18
- package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +0 -2
- package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +0 -2
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +4 -5
- package/front_end/entrypoints/main/MainImpl.ts +0 -6
- package/front_end/generated/InspectorBackendCommands.ts +1 -1
- package/front_end/generated/protocol.ts +7 -0
- package/front_end/models/ai_assistance/AiAgent2.ts +24 -5
- package/front_end/models/ai_assistance/AiConversation.ts +15 -12
- package/front_end/models/ai_assistance/AiUtils.ts +71 -0
- package/front_end/models/ai_assistance/ChangeManager.ts +2 -5
- package/front_end/models/ai_assistance/{agents/ConversationSummaryAgent.ts → ConversationSummary.ts} +29 -66
- package/front_end/models/ai_assistance/ExtensionScope.ts +1 -4
- package/front_end/models/ai_assistance/{agents/PerformanceAnnotationsAgent.ts → PerformanceAnnotations.ts} +47 -89
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +47 -31
- package/front_end/models/ai_assistance/agents/AiAgent.ts +40 -12
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +11 -0
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +58 -8
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +1 -92
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +25 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +94 -79
- package/front_end/models/ai_assistance/agents/StorageAgent.ts +101 -39
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +1 -2
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +27 -21
- package/front_end/models/ai_assistance/ai_assistance.ts +6 -4
- package/front_end/models/ai_assistance/skills/styling.md +12 -4
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +134 -0
- package/front_end/models/ai_assistance/tools/GetStyles.ts +6 -2
- package/front_end/models/ai_assistance/tools/Tool.ts +16 -1
- package/front_end/models/ai_assistance/tools/ToolRegistry.ts +2 -0
- package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +6 -9
- package/front_end/models/bindings/DefaultScriptMapping.ts +2 -1
- package/front_end/models/bindings/SymbolizedError.ts +45 -35
- package/front_end/models/extensions/ExtensionAPI.ts +138 -47
- package/front_end/models/har/Importer.ts +1 -0
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +5 -7
- package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +12 -2
- package/front_end/models/stack_trace/DetailedErrorStackParser.ts +44 -51
- package/front_end/models/stack_trace/StackTrace.ts +7 -0
- package/front_end/models/stack_trace/StackTraceImpl.ts +13 -4
- package/front_end/models/stack_trace/StackTraceModel.ts +9 -8
- package/front_end/panels/accessibility/AccessibilitySidebarView.ts +2 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +8 -8
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +96 -4
- package/front_end/panels/ai_assistance/components/chatMessage.css +6 -0
- package/front_end/panels/application/ApplicationPanelSidebar.ts +39 -0
- package/front_end/panels/application/ApplicationPanelTreeElement.ts +39 -0
- package/front_end/panels/application/CookieItemsView.ts +2 -2
- package/front_end/panels/application/components/AdsView.ts +219 -0
- package/front_end/panels/application/components/adsView.css +54 -0
- package/front_end/panels/application/components/components.ts +2 -0
- package/front_end/panels/application/resourcesSidebar.css +11 -0
- package/front_end/panels/console/SymbolizedErrorWidget.ts +79 -25
- package/front_end/panels/network/NetworkLogView.ts +5 -1
- package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +1 -0
- package/front_end/panels/sources/SourcesPanel.ts +2 -1
- package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +5 -4
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/lighthouse/README.chromium +2 -2
- package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1607 -5733
- package/front_end/third_party/lighthouse/locales/ar-XB.json +290 -65
- package/front_end/third_party/lighthouse/locales/ar.json +290 -65
- package/front_end/third_party/lighthouse/locales/bg.json +290 -65
- package/front_end/third_party/lighthouse/locales/ca.json +295 -70
- package/front_end/third_party/lighthouse/locales/cs.json +290 -65
- package/front_end/third_party/lighthouse/locales/da.json +294 -69
- package/front_end/third_party/lighthouse/locales/de.json +295 -70
- package/front_end/third_party/lighthouse/locales/el.json +290 -65
- package/front_end/third_party/lighthouse/locales/en-GB.json +290 -65
- package/front_end/third_party/lighthouse/locales/en-US.json +79 -67
- package/front_end/third_party/lighthouse/locales/en-XA.json +253 -64
- package/front_end/third_party/lighthouse/locales/en-XL.json +79 -67
- package/front_end/third_party/lighthouse/locales/es-419.json +290 -65
- package/front_end/third_party/lighthouse/locales/es.json +298 -73
- package/front_end/third_party/lighthouse/locales/fi.json +290 -65
- package/front_end/third_party/lighthouse/locales/fil.json +290 -65
- package/front_end/third_party/lighthouse/locales/fr.json +294 -69
- package/front_end/third_party/lighthouse/locales/he.json +293 -68
- package/front_end/third_party/lighthouse/locales/hi.json +291 -66
- package/front_end/third_party/lighthouse/locales/hr.json +290 -65
- package/front_end/third_party/lighthouse/locales/hu.json +290 -65
- package/front_end/third_party/lighthouse/locales/id.json +290 -65
- package/front_end/third_party/lighthouse/locales/it.json +294 -69
- package/front_end/third_party/lighthouse/locales/ja.json +290 -65
- package/front_end/third_party/lighthouse/locales/ko.json +290 -65
- package/front_end/third_party/lighthouse/locales/lt.json +290 -65
- package/front_end/third_party/lighthouse/locales/lv.json +290 -65
- package/front_end/third_party/lighthouse/locales/nl.json +290 -65
- package/front_end/third_party/lighthouse/locales/no.json +290 -65
- package/front_end/third_party/lighthouse/locales/pl.json +290 -65
- package/front_end/third_party/lighthouse/locales/pt-PT.json +291 -66
- package/front_end/third_party/lighthouse/locales/pt.json +290 -65
- package/front_end/third_party/lighthouse/locales/ro.json +290 -65
- package/front_end/third_party/lighthouse/locales/ru.json +301 -76
- package/front_end/third_party/lighthouse/locales/sk.json +291 -66
- package/front_end/third_party/lighthouse/locales/sl.json +290 -65
- package/front_end/third_party/lighthouse/locales/sr-Latn.json +290 -65
- package/front_end/third_party/lighthouse/locales/sr.json +290 -65
- package/front_end/third_party/lighthouse/locales/sv.json +297 -72
- package/front_end/third_party/lighthouse/locales/ta.json +291 -66
- package/front_end/third_party/lighthouse/locales/te.json +293 -68
- package/front_end/third_party/lighthouse/locales/th.json +291 -66
- package/front_end/third_party/lighthouse/locales/tr.json +290 -65
- package/front_end/third_party/lighthouse/locales/uk.json +290 -65
- package/front_end/third_party/lighthouse/locales/vi.json +291 -66
- package/front_end/third_party/lighthouse/locales/zh-HK.json +292 -67
- package/front_end/third_party/lighthouse/locales/zh-TW.json +291 -66
- package/front_end/third_party/lighthouse/locales/zh.json +291 -66
- package/front_end/third_party/lighthouse/report/bundle.d.ts +6 -6
- package/front_end/third_party/lighthouse/report/bundle.js +4 -7
- package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +2 -2
- package/front_end/ui/legacy/StackedPane.ts +229 -0
- package/front_end/ui/legacy/ViewManager.ts +59 -169
- package/front_end/ui/legacy/Widget.ts +32 -8
- package/front_end/ui/legacy/legacy.ts +3 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
- package/mcp/mcp.ts +1 -0
- package/package.json +1 -1
|
@@ -23,7 +23,7 @@ const lockedString = i18n.i18n.lockedString;
|
|
|
23
23
|
const preamble =
|
|
24
24
|
`You are a Senior Software Engineer specializing in state audit and storage analysis within Chrome DevTools. Your mission is to help developers debug storage-related issues faster by analyzing the evidence in LocalStorage, SessionStorage, and Cookies.
|
|
25
25
|
|
|
26
|
-
You have access to the site's storage using tools like \`listPageOrigins\`, \`listStorageKeys\`, \`getStorageValues\`, \`listCookies\`, and \`getCookieValues\`.
|
|
26
|
+
You have access to the site's storage using tools like \`getStorageBreakdown\`, \`listPageOrigins\`, \`listStorageKeys\`, \`getStorageValues\`, \`listCookies\`, and \`getCookieValues\`.
|
|
27
27
|
|
|
28
28
|
# Goals
|
|
29
29
|
|
|
@@ -34,6 +34,7 @@ const preamble =
|
|
|
34
34
|
# Tools & Workflow
|
|
35
35
|
|
|
36
36
|
- **Prioritize Top-Level Context**: Always initiate your investigation from the top-level page's storage. Explicitly state if you are analyzing storage from a different context (e.g., an iframe).
|
|
37
|
+
- **Storage Breakdown**: Calling \`getStorageBreakdown\` gives you the total usage and quota per storage for the top-level page.
|
|
37
38
|
- **Address Specific Selections**: The user can select individual storage items in the DevTools UI (provided in the '# Active Context' section of the prompt). If the query is about a selected item (e.g., "Why is this cookie set?"), focus your response on that specific item.
|
|
38
39
|
- **Expand Scope When Necessary**: For general questions or those implying a wider scope (e.g., "Check all storages," "Are there related cookies on subdomains?"), proactively use your tools to explore other relevant storage contexts, including iframes and different origins.
|
|
39
40
|
- **Discovery**: Start by calling \`listPageOrigins\` to discover all active, non-empty frame origins loaded by the page.
|
|
@@ -173,18 +174,17 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
173
174
|
},
|
|
174
175
|
});
|
|
175
176
|
|
|
176
|
-
this.declareFunction<
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}>('listStorageKeys', {
|
|
177
|
+
this.declareFunction<{
|
|
178
|
+
type: 'localStorage' | 'sessionStorage',
|
|
179
|
+
origin: string,
|
|
180
|
+
storageKey?: string,
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
partitions: Array<{
|
|
184
|
+
storageKey: string,
|
|
185
|
+
keys: string[],
|
|
186
|
+
}>,
|
|
187
|
+
}>('listStorageKeys', {
|
|
188
188
|
description:
|
|
189
189
|
'Lists all keys for a given storage type for the requested origin. Returns keys grouped by storage partition.',
|
|
190
190
|
parameters: {
|
|
@@ -218,6 +218,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
218
218
|
},
|
|
219
219
|
|
|
220
220
|
handler: async args => {
|
|
221
|
+
this.disableServerSideLogging();
|
|
221
222
|
if (!isSamePrimaryPageOrigin(this.context)) {
|
|
222
223
|
return {error: 'No origin available or not allowed.'};
|
|
223
224
|
}
|
|
@@ -244,19 +245,18 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
244
245
|
},
|
|
245
246
|
});
|
|
246
247
|
|
|
247
|
-
this.declareFunction<
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}>('getStorageValues', {
|
|
248
|
+
this.declareFunction<{
|
|
249
|
+
type: 'localStorage' | 'sessionStorage',
|
|
250
|
+
keys: string[],
|
|
251
|
+
origin: string,
|
|
252
|
+
storageKey?: string,
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
items: Array<{
|
|
256
|
+
storageKey: string,
|
|
257
|
+
values: Record<string, string>,
|
|
258
|
+
}>,
|
|
259
|
+
}>('getStorageValues', {
|
|
260
260
|
description: 'Retrieve specific string values from storage partitions for requested keys.',
|
|
261
261
|
parameters: {
|
|
262
262
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
@@ -296,6 +296,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
296
296
|
},
|
|
297
297
|
|
|
298
298
|
handler: async (args, options) => {
|
|
299
|
+
this.disableServerSideLogging();
|
|
299
300
|
if (!isSamePrimaryPageOrigin(this.context)) {
|
|
300
301
|
return {error: 'No origin available or not allowed.'};
|
|
301
302
|
}
|
|
@@ -353,11 +354,10 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
353
354
|
},
|
|
354
355
|
});
|
|
355
356
|
|
|
356
|
-
this.declareFunction<
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
{cookies: string[]}>('listCookies', {
|
|
357
|
+
this.declareFunction<{
|
|
358
|
+
origin: string,
|
|
359
|
+
},
|
|
360
|
+
{cookies: string[]}>('listCookies', {
|
|
361
361
|
description: 'Lists all cookies for the requested origin, strictly excluding their values.',
|
|
362
362
|
parameters: {
|
|
363
363
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
@@ -379,6 +379,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
379
379
|
};
|
|
380
380
|
},
|
|
381
381
|
handler: async args => {
|
|
382
|
+
this.disableServerSideLogging();
|
|
382
383
|
if (!isSamePrimaryPageOrigin(this.context)) {
|
|
383
384
|
return {error: 'No origin available or not allowed.'};
|
|
384
385
|
}
|
|
@@ -396,14 +397,13 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
396
397
|
},
|
|
397
398
|
});
|
|
398
399
|
|
|
399
|
-
this.declareFunction<
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}>('getCookieValues', {
|
|
400
|
+
this.declareFunction<{
|
|
401
|
+
cookieNames: string[],
|
|
402
|
+
origin: string,
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
cookies: CookieDetails[],
|
|
406
|
+
}>('getCookieValues', {
|
|
407
407
|
description: 'Retrieve the values and detailed metadata of specific cookies by their names.',
|
|
408
408
|
parameters: {
|
|
409
409
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
@@ -431,6 +431,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
431
431
|
};
|
|
432
432
|
},
|
|
433
433
|
handler: async (args, options) => {
|
|
434
|
+
this.disableServerSideLogging();
|
|
434
435
|
if (!isSamePrimaryPageOrigin(this.context)) {
|
|
435
436
|
return {error: 'No origin available or not allowed.'};
|
|
436
437
|
}
|
|
@@ -479,6 +480,58 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
479
480
|
return {result: {cookies: cookieData}};
|
|
480
481
|
},
|
|
481
482
|
});
|
|
483
|
+
|
|
484
|
+
this.declareFunction<Record<string, never>, {
|
|
485
|
+
totalUsage: string,
|
|
486
|
+
totalQuota: string,
|
|
487
|
+
usageBreakdown: Array<{
|
|
488
|
+
storageType: string,
|
|
489
|
+
usage: string,
|
|
490
|
+
}>,
|
|
491
|
+
}>('getStorageBreakdown', {
|
|
492
|
+
description:
|
|
493
|
+
'Retrieves the total storage usage, total storage quota, and a breakdown of active storage usage per storage type for the top-level page.',
|
|
494
|
+
parameters: {
|
|
495
|
+
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
496
|
+
description: '',
|
|
497
|
+
nullable: false,
|
|
498
|
+
properties: {},
|
|
499
|
+
required: [],
|
|
500
|
+
},
|
|
501
|
+
displayInfoFromArgs: () => {
|
|
502
|
+
return {
|
|
503
|
+
title: lockedString('Retrieving storage breakdown'),
|
|
504
|
+
action: 'getStorageBreakdown()',
|
|
505
|
+
};
|
|
506
|
+
},
|
|
507
|
+
handler: async () => {
|
|
508
|
+
const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
509
|
+
if (!target || !this.context || !isSamePageOrigin(target, this.context)) {
|
|
510
|
+
return {error: 'No origin available or not allowed.'};
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const origin = this.context.getOrigin();
|
|
514
|
+
const response = await target.storageAgent().invoke_getUsageAndQuota({origin});
|
|
515
|
+
if (response.getError()) {
|
|
516
|
+
return {error: response.getError() || 'Unknown CDP error'};
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const usageBreakdown = response.usageBreakdown.filter(entry => entry.usage > 0)
|
|
520
|
+
.sort((a, b) => b.usage - a.usage)
|
|
521
|
+
.map(entry => ({
|
|
522
|
+
storageType: entry.storageType as string,
|
|
523
|
+
usage: i18n.ByteUtilities.bytesToString(entry.usage),
|
|
524
|
+
}));
|
|
525
|
+
|
|
526
|
+
return {
|
|
527
|
+
result: {
|
|
528
|
+
totalUsage: i18n.ByteUtilities.bytesToString(response.usage),
|
|
529
|
+
totalQuota: i18n.ByteUtilities.bytesToString(response.quota),
|
|
530
|
+
usageBreakdown,
|
|
531
|
+
},
|
|
532
|
+
};
|
|
533
|
+
},
|
|
534
|
+
});
|
|
482
535
|
}
|
|
483
536
|
|
|
484
537
|
static #formatContext(item: StorageItem): string {
|
|
@@ -498,6 +551,15 @@ export class StorageAgent extends AiAgent<StorageItem> {
|
|
|
498
551
|
return primaryTargetOrigin;
|
|
499
552
|
}
|
|
500
553
|
|
|
554
|
+
protected override async preRun(): Promise<void> {
|
|
555
|
+
const item = this.context?.getItem();
|
|
556
|
+
if (item instanceof CookieItem && Boolean(item.name)) {
|
|
557
|
+
this.disableServerSideLogging();
|
|
558
|
+
} else if (item instanceof DOMStorageItem && Boolean(item.key)) {
|
|
559
|
+
this.disableServerSideLogging();
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
501
563
|
async *
|
|
502
564
|
handleContextDetails(context: ConversationContext<StorageItem>|null):
|
|
503
565
|
AsyncGenerator<ContextResponse, void, void> {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
Title: StylingAgent buildRequest structure matches the snapshot
|
|
3
2
|
Content:
|
|
4
3
|
{
|
|
@@ -129,7 +128,7 @@ Content:
|
|
|
129
128
|
"disable_user_content_logging": false,
|
|
130
129
|
"string_session_id": "sessionId",
|
|
131
130
|
"user_tier": 3,
|
|
132
|
-
"client_version": "unit_test"
|
|
131
|
+
"client_version": "unit_test+function_calling"
|
|
133
132
|
},
|
|
134
133
|
"functionality_type": 5,
|
|
135
134
|
"client_feature": 2
|
|
@@ -27,10 +27,8 @@ import {
|
|
|
27
27
|
} from './AiAgent.js';
|
|
28
28
|
import {
|
|
29
29
|
type CreateExtensionScopeFunction,
|
|
30
|
-
executeJavaScriptFunction,
|
|
31
30
|
type ExecuteJsAgentOptions,
|
|
32
31
|
executeJsCode,
|
|
33
|
-
JavascriptExecutor
|
|
34
32
|
} from './ExecuteJavascript.js';
|
|
35
33
|
|
|
36
34
|
const preamble = `You are the most advanced CSS/DOM/HTML debugging assistant integrated into Chrome DevTools.
|
|
@@ -169,32 +167,21 @@ export class StylingAgent extends AiAgent<SDK.DOMModel.DOMNode> {
|
|
|
169
167
|
}
|
|
170
168
|
|
|
171
169
|
#execJs: typeof executeJsCode;
|
|
172
|
-
#javascriptExecutor: JavascriptExecutor;
|
|
173
170
|
|
|
174
171
|
#changes: ChangeManager;
|
|
175
172
|
#createExtensionScope: CreateExtensionScopeFunction;
|
|
176
173
|
#greenDevEmulationScreenshot: string|null = null;
|
|
177
174
|
#greenDevEmulationAxTree: string|null = null;
|
|
178
175
|
#hasAddedEmulationInstructions = false;
|
|
179
|
-
#currentTurnId = 0;
|
|
180
176
|
|
|
181
177
|
constructor(opts: ExecuteJsAgentOptions) {
|
|
182
178
|
super(opts);
|
|
183
179
|
|
|
184
180
|
this.#changes = opts.changeManager || new ChangeManager();
|
|
185
181
|
this.#execJs = opts.execJs ?? executeJsCode;
|
|
186
|
-
this.#createExtensionScope =
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
});
|
|
190
|
-
this.#javascriptExecutor = new JavascriptExecutor(
|
|
191
|
-
{
|
|
192
|
-
executionMode: this.executionMode,
|
|
193
|
-
getContextNode: () => this.#getSelectedNode(),
|
|
194
|
-
createExtensionScope: this.#createExtensionScope.bind(this),
|
|
195
|
-
changes: this.#changes,
|
|
196
|
-
},
|
|
197
|
-
this.#execJs);
|
|
182
|
+
this.#createExtensionScope = opts.createExtensionScope ?? ((changes: ChangeManager) => {
|
|
183
|
+
return new ExtensionScope(changes, this.sessionId, this.context?.getItem() ?? null);
|
|
184
|
+
});
|
|
198
185
|
|
|
199
186
|
const getStylesTool = ToolRegistry.get(ToolName.GET_STYLES);
|
|
200
187
|
if (!getStylesTool) {
|
|
@@ -209,7 +196,26 @@ export class StylingAgent extends AiAgent<SDK.DOMModel.DOMNode> {
|
|
|
209
196
|
}),
|
|
210
197
|
});
|
|
211
198
|
|
|
212
|
-
|
|
199
|
+
const executeJsTool = ToolRegistry.get(ToolName.EXECUTE_JAVASCRIPT);
|
|
200
|
+
if (!executeJsTool) {
|
|
201
|
+
throw new Error('Required tool "executeJavaScript" not found');
|
|
202
|
+
}
|
|
203
|
+
this.declareFunction(ToolName.EXECUTE_JAVASCRIPT, {
|
|
204
|
+
description: executeJsTool.description,
|
|
205
|
+
parameters: executeJsTool.parameters,
|
|
206
|
+
displayInfoFromArgs: executeJsTool.displayInfoFromArgs,
|
|
207
|
+
handler: (args, options) => executeJsTool.handler(
|
|
208
|
+
args,
|
|
209
|
+
{
|
|
210
|
+
conversationContext: this.context ?? null,
|
|
211
|
+
changeManager: this.#changes,
|
|
212
|
+
createExtensionScope: this.#createExtensionScope.bind(this),
|
|
213
|
+
execJs: this.#execJs,
|
|
214
|
+
getExecutionContextNode: () => this.context?.getItem() ?? null,
|
|
215
|
+
},
|
|
216
|
+
options,
|
|
217
|
+
),
|
|
218
|
+
});
|
|
213
219
|
|
|
214
220
|
if (Annotations.AnnotationRepository.annotationsEnabled()) {
|
|
215
221
|
this.declareFunction<{
|
|
@@ -275,6 +281,10 @@ export class StylingAgent extends AiAgent<SDK.DOMModel.DOMNode> {
|
|
|
275
281
|
});
|
|
276
282
|
}
|
|
277
283
|
|
|
284
|
+
override preambleFeatures(): string[] {
|
|
285
|
+
return ['function_calling'];
|
|
286
|
+
}
|
|
287
|
+
|
|
278
288
|
#getSelectedNode(): SDK.DOMModel.DOMNode|null {
|
|
279
289
|
return this.context?.getItem() ?? null;
|
|
280
290
|
}
|
|
@@ -515,10 +525,6 @@ export class StylingAgent extends AiAgent<SDK.DOMModel.DOMNode> {
|
|
|
515
525
|
}
|
|
516
526
|
}
|
|
517
527
|
|
|
518
|
-
protected override async preRun(): Promise<void> {
|
|
519
|
-
this.#currentTurnId++;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
528
|
override async enhanceQuery(
|
|
523
529
|
query: string, selectedElement: ConversationContext<SDK.DOMModel.DOMNode>|null,
|
|
524
530
|
multimodalInputType?: MultimodalInputType): Promise<string> {
|
|
@@ -6,7 +6,6 @@ import * as AgentProject from './AgentProject.js';
|
|
|
6
6
|
import * as AccessibilityAgent from './agents/AccessibilityAgent.js';
|
|
7
7
|
import * as AiAgent from './agents/AiAgent.js';
|
|
8
8
|
import * as ContextSelectionAgent from './agents/ContextSelectionAgent.js';
|
|
9
|
-
import * as ConversationSummaryAgent from './agents/ConversationSummaryAgent.js';
|
|
10
9
|
import * as FileAgent from './agents/FileAgent.js';
|
|
11
10
|
import * as GreenDevAgent from './agents/GreenDevAgent.js';
|
|
12
11
|
import * as GreenDevAgentAntigravityCliSocketClient from './agents/GreenDevAgentAntigravityCliSocketClient.js';
|
|
@@ -14,7 +13,6 @@ import * as GreenDevAgentGeminiCliSocketClient from './agents/GreenDevAgentGemin
|
|
|
14
13
|
import * as NetworkAgent from './agents/NetworkAgent.js';
|
|
15
14
|
import * as PatchAgent from './agents/PatchAgent.js';
|
|
16
15
|
import * as PerformanceAgent from './agents/PerformanceAgent.js';
|
|
17
|
-
import * as PerformanceAnnotationsAgent from './agents/PerformanceAnnotationsAgent.js';
|
|
18
16
|
import * as StorageAgent from './agents/StorageAgent.js';
|
|
19
17
|
import * as StylingAgent from './agents/StylingAgent.js';
|
|
20
18
|
import * as AiAgent2 from './AiAgent2.js';
|
|
@@ -25,6 +23,7 @@ import * as AiUtils from './AiUtils.js';
|
|
|
25
23
|
import * as BuiltInAi from './BuiltInAi.js';
|
|
26
24
|
import * as ChangeManager from './ChangeManager.js';
|
|
27
25
|
import * as DOMNodeContext from './contexts/DOMNodeContext.js';
|
|
26
|
+
import * as ConversationSummary from './ConversationSummary.js';
|
|
28
27
|
import * as FileFormatter from './data_formatters/FileFormatter.js';
|
|
29
28
|
import * as LighthouseFormatter from './data_formatters/LighthouseFormatter.js';
|
|
30
29
|
import * as NetworkRequestFormatter from './data_formatters/NetworkRequestFormatter.js';
|
|
@@ -38,7 +37,9 @@ import * as Injected from './injected.js';
|
|
|
38
37
|
import * as AICallTree from './performance/AICallTree.js';
|
|
39
38
|
import * as AIContext from './performance/AIContext.js';
|
|
40
39
|
import * as AIQueries from './performance/AIQueries.js';
|
|
40
|
+
import * as PerformanceAnnotations from './PerformanceAnnotations.js';
|
|
41
41
|
import * as StorageItem from './StorageItem.js';
|
|
42
|
+
import * as ExecuteJavaScript from './tools/ExecuteJavaScript.js';
|
|
42
43
|
import * as GetStyles from './tools/GetStyles.js';
|
|
43
44
|
import * as Tool from './tools/Tool.js';
|
|
44
45
|
import * as ToolRegistry from './tools/ToolRegistry.js';
|
|
@@ -58,10 +59,11 @@ export {
|
|
|
58
59
|
BuiltInAi,
|
|
59
60
|
ChangeManager,
|
|
60
61
|
ContextSelectionAgent,
|
|
61
|
-
|
|
62
|
+
ConversationSummary,
|
|
62
63
|
Debug,
|
|
63
64
|
DOMNodeContext,
|
|
64
65
|
EvaluateAction,
|
|
66
|
+
ExecuteJavaScript,
|
|
65
67
|
ExtensionScope,
|
|
66
68
|
FileAgent,
|
|
67
69
|
FileFormatter,
|
|
@@ -75,7 +77,7 @@ export {
|
|
|
75
77
|
NetworkRequestFormatter,
|
|
76
78
|
PatchAgent,
|
|
77
79
|
PerformanceAgent,
|
|
78
|
-
|
|
80
|
+
PerformanceAnnotations,
|
|
79
81
|
PerformanceInsightFormatter,
|
|
80
82
|
PerformanceTraceFormatter,
|
|
81
83
|
StorageAgent,
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
name: styling
|
|
3
3
|
description: Helping with CSS and styling
|
|
4
4
|
allowed-tools:
|
|
5
|
+
- executeJavaScript
|
|
5
6
|
- getStyles
|
|
6
7
|
---
|
|
7
|
-
You are
|
|
8
|
+
You are the most advanced CSS/DOM/HTML debugging assistant integrated into Chrome DevTools.
|
|
8
9
|
You always suggest considering the best web development practices and the newest platform features such as view transitions.
|
|
9
10
|
The user selected a DOM element in the browser's DevTools and sends a query about the page or the selected DOM element.
|
|
10
|
-
First, examine the provided context, then use the getStyles
|
|
11
|
+
First, examine the provided context, then use the getStyles and executeJavaScript functions to gather additional context and resolve the user request.
|
|
11
12
|
|
|
12
13
|
# Considerations
|
|
13
14
|
|
|
@@ -19,10 +20,17 @@ First, examine the provided context, then use the getStyles function to gather a
|
|
|
19
20
|
* Please answer only if you are sure about the answer. Otherwise, explain why you're not able to answer.
|
|
20
21
|
* When answering, always consider MULTIPLE possible solutions.
|
|
21
22
|
* When answering, remember to consider CSS concepts such as the CSS cascade, explicit and implicit stacking contexts and various CSS layout types.
|
|
22
|
-
* Use the
|
|
23
|
-
*
|
|
23
|
+
* Use the functions available to you to investigate and fulfill the user request.
|
|
24
|
+
* After applying a fix, please ask the user to confirm if the fix worked or not.
|
|
25
|
+
* ALWAYS OUTPUT a list of follow-up queries at the end of your text response. The format is SUGGESTIONS: ["suggestion1", "suggestion2", "suggestion3"]. Make sure that the array and the `SUGGESTIONS: ` text is in the same line. You're also capable of executing the fix for the issue user mentioned. Reflect this in your suggestions.
|
|
24
26
|
* Use the precision of Strunk & White, the brevity of Hemingway, and the simple clarity of Vonnegut. Don't add repeated information, and keep the whole answer short.
|
|
27
|
+
* **CRITICAL** NEVER output text before a function call. Always do a function call first.
|
|
25
28
|
* **CRITICAL** When answering questions about positioning or layout, ALWAYS inspect `position`, `display` and all other related properties. You MUST provide a specific list of CSS property names when calling getStyles. Do not use generic values like "all" or "*".
|
|
29
|
+
* **CRITICAL** When writing JavaScript via the `executeJavaScript` tool:
|
|
30
|
+
- To return data, define a top-level `data` variable and populate it with a JSON-serializable object.
|
|
31
|
+
- If you modify styles on an element, ALWAYS call the pre-defined global `async setElementStyles(el: Element, styles: object)` function. This function is an internal mechanism and should never be presented to the user.
|
|
32
|
+
- Never assume a selector for the elements unless you verified your knowledge.
|
|
33
|
+
- Consider that `data` variables from previous function calls are not available in a new function call.
|
|
26
34
|
* **CRITICAL** You are a CSS/DOM/HTML debugging assistant. NEVER provide answers to questions of unrelated topics such as legal advice, financial advice, personal opinions, medical advice, religion, race, politics, sexuality, gender, or any other non web-development topics. Answer "Sorry, I can't answer that. I'm best at questions about debugging web pages." to such questions.
|
|
27
35
|
|
|
28
36
|
## Response Structure
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// Copyright 2026 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
import * as Host from '../../../core/host/host.js';
|
|
6
|
+
import * as Root from '../../../core/root/root.js';
|
|
7
|
+
import type {FunctionCallHandlerResult, FunctionHandlerOptions,} from '../agents/AiAgent.js';
|
|
8
|
+
import {JavascriptExecutor} from '../agents/ExecuteJavascript.js';
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
type Tool,
|
|
12
|
+
type ToolArgs,
|
|
13
|
+
type ToolContext,
|
|
14
|
+
ToolName,
|
|
15
|
+
} from './Tool.js';
|
|
16
|
+
|
|
17
|
+
export interface ExecuteJavaScriptArgs extends ToolArgs {
|
|
18
|
+
code: string;
|
|
19
|
+
explanation: string;
|
|
20
|
+
title: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class ExecuteJavaScriptTool implements Tool<ExecuteJavaScriptArgs, unknown> {
|
|
24
|
+
readonly name = ToolName.EXECUTE_JAVASCRIPT;
|
|
25
|
+
|
|
26
|
+
readonly description =
|
|
27
|
+
'This function allows you to run JavaScript code on the inspected page to access the element styles and page content.\nCall this function to gather additional information or modify the page state. Call this function enough times to investigate the user request.';
|
|
28
|
+
|
|
29
|
+
readonly parameters: Host.AidaClient.FunctionObjectParam<keyof ExecuteJavaScriptArgs> = {
|
|
30
|
+
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
31
|
+
description: '',
|
|
32
|
+
nullable: false,
|
|
33
|
+
properties: {
|
|
34
|
+
code: {
|
|
35
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
36
|
+
description:
|
|
37
|
+
`JavaScript code snippet to run on the inspected page. Make sure the code is formatted for readability.
|
|
38
|
+
|
|
39
|
+
# Instructions
|
|
40
|
+
|
|
41
|
+
* To return data, define a top-level \`data\` variable and populate it with data you want to get. Only JSON-serializable objects can be assigned to \`data\`.
|
|
42
|
+
* If you modify styles on an element, ALWAYS call the pre-defined global \`async setElementStyles(el: Element, styles: object)\` function. This function is an internal mechanism for you and should never be presented as a command/advice to the user.
|
|
43
|
+
* **CRITICAL** Only get styles that might be relevant to the user request.
|
|
44
|
+
* **CRITICAL** Never assume a selector for the elements unless you verified your knowledge.
|
|
45
|
+
* **CRITICAL** Consider that \`data\` variable from the previous function calls are not available in a new function call.
|
|
46
|
+
|
|
47
|
+
For example, the code to change element styles:
|
|
48
|
+
|
|
49
|
+
\`\`\`
|
|
50
|
+
await setElementStyles($0, {
|
|
51
|
+
color: 'blue',
|
|
52
|
+
});
|
|
53
|
+
\`\`\`
|
|
54
|
+
|
|
55
|
+
For example, the code to get overlapping elements:
|
|
56
|
+
|
|
57
|
+
\`\`\`
|
|
58
|
+
const data = {
|
|
59
|
+
overlappingElements: Array.from(document.querySelectorAll('*'))
|
|
60
|
+
.filter(el => {
|
|
61
|
+
const rect = el.getBoundingClientRect();
|
|
62
|
+
const popupRect = $0.getBoundingClientRect();
|
|
63
|
+
return (
|
|
64
|
+
el !== $0 &&
|
|
65
|
+
rect.left < popupRect.right &&
|
|
66
|
+
rect.right > popupRect.left &&
|
|
67
|
+
rect.top < popupRect.bottom &&
|
|
68
|
+
rect.bottom > popupRect.top
|
|
69
|
+
);
|
|
70
|
+
})
|
|
71
|
+
.map(el => ({
|
|
72
|
+
tagName: el.tagName,
|
|
73
|
+
id: el.id,
|
|
74
|
+
className: el.className,
|
|
75
|
+
zIndex: window.getComputedStyle(el)['z-index']
|
|
76
|
+
}))
|
|
77
|
+
};
|
|
78
|
+
\`\`\`
|
|
79
|
+
`,
|
|
80
|
+
},
|
|
81
|
+
explanation: {
|
|
82
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
83
|
+
description: 'Explain why you want to run this code',
|
|
84
|
+
},
|
|
85
|
+
title: {
|
|
86
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
87
|
+
description: 'Provide a summary of what the code does. For example, "Checking related element styles".',
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
required: ['code', 'explanation', 'title'],
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
displayInfoFromArgs(params: ExecuteJavaScriptArgs): {
|
|
94
|
+
title: string,
|
|
95
|
+
thought: string,
|
|
96
|
+
action: string,
|
|
97
|
+
} {
|
|
98
|
+
return {
|
|
99
|
+
title: params.title,
|
|
100
|
+
thought: params.explanation,
|
|
101
|
+
action: params.code,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async handler(
|
|
106
|
+
params: ExecuteJavaScriptArgs,
|
|
107
|
+
context: ToolContext,
|
|
108
|
+
options?: FunctionHandlerOptions,
|
|
109
|
+
): Promise<FunctionCallHandlerResult<unknown>> {
|
|
110
|
+
const executionNode = context.getExecutionContextNode?.() ?? null;
|
|
111
|
+
if (!executionNode) {
|
|
112
|
+
return {error: 'Error: Could not find the context node for execution.'};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const executionMode = Root.Runtime.hostConfig.devToolsFreestyler?.executionMode ??
|
|
116
|
+
Root.Runtime.HostConfigFreestylerExecutionMode.ALL_SCRIPTS;
|
|
117
|
+
|
|
118
|
+
const changes = context.changeManager;
|
|
119
|
+
const createExtensionScope = context.createExtensionScope;
|
|
120
|
+
if (!changes || !createExtensionScope) {
|
|
121
|
+
return {error: 'Internal Error: Required change manager or extension scope creator is missing.'};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const executor = new JavascriptExecutor({
|
|
125
|
+
executionMode,
|
|
126
|
+
getContextNode: () => executionNode,
|
|
127
|
+
createExtensionScope,
|
|
128
|
+
changes,
|
|
129
|
+
},
|
|
130
|
+
context.execJs);
|
|
131
|
+
|
|
132
|
+
return await executor.executeAction(params.code, options);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import * as Host from '../../../core/host/host.js';
|
|
6
6
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
7
7
|
import type * as Protocol from '../../../generated/protocol.js';
|
|
8
|
-
import type {ComputedStyleAiWidget, FunctionCallHandlerResult} from '../agents/AiAgent.js';
|
|
8
|
+
import type {ComputedStyleAiWidget, FunctionCallHandlerResult, FunctionHandlerOptions} from '../agents/AiAgent.js';
|
|
9
9
|
import {DOMNodeContext} from '../contexts/DOMNodeContext.js';
|
|
10
10
|
import {debugLog} from '../debug.js';
|
|
11
11
|
|
|
@@ -69,7 +69,11 @@ export class GetStylesTool implements Tool<GetStylesArgs, unknown> {
|
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
async handler(
|
|
72
|
+
async handler(
|
|
73
|
+
params: GetStylesArgs,
|
|
74
|
+
context: ToolContext,
|
|
75
|
+
_options?: FunctionHandlerOptions,
|
|
76
|
+
): Promise<FunctionCallHandlerResult<unknown>> {
|
|
73
77
|
const widgets: ComputedStyleAiWidget[] = [];
|
|
74
78
|
const result:
|
|
75
79
|
Record<string, {computed: Record<string, string|undefined>, authored: Record<string, string|undefined>}> = {};
|
|
@@ -3,13 +3,26 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import type * as Host from '../../../core/host/host.js';
|
|
6
|
-
import type
|
|
6
|
+
import type * as SDK from '../../../core/sdk/sdk.js';
|
|
7
|
+
import type {ConversationContext, FunctionCallHandlerResult, FunctionHandlerOptions} from '../agents/AiAgent.js';
|
|
8
|
+
import type {executeJsCode} from '../agents/ExecuteJavascript.js';
|
|
9
|
+
import type {ChangeManager} from '../ChangeManager.js';
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Context provided to the tool's handler execution.
|
|
10
13
|
*/
|
|
11
14
|
export interface ToolContext {
|
|
12
15
|
conversationContext: ConversationContext<unknown>|null;
|
|
16
|
+
changeManager?: ChangeManager;
|
|
17
|
+
createExtensionScope?: (changes: ChangeManager) => {
|
|
18
|
+
install(): Promise<void>, uninstall(): Promise<void>,
|
|
19
|
+
};
|
|
20
|
+
execJs?: typeof executeJsCode;
|
|
21
|
+
/**
|
|
22
|
+
* Returns the DOM node that acts as the execution context (i.e. `$0` inside the execution context)
|
|
23
|
+
* for running JavaScript.
|
|
24
|
+
*/
|
|
25
|
+
getExecutionContextNode?: () => SDK.DOMModel.DOMNode | null;
|
|
13
26
|
}
|
|
14
27
|
|
|
15
28
|
/**
|
|
@@ -18,6 +31,7 @@ export interface ToolContext {
|
|
|
18
31
|
export type ToolArgs = Record<string, unknown>;
|
|
19
32
|
|
|
20
33
|
export const enum ToolName {
|
|
34
|
+
EXECUTE_JAVASCRIPT = 'executeJavaScript',
|
|
21
35
|
GET_STYLES = 'getStyles',
|
|
22
36
|
}
|
|
23
37
|
|
|
@@ -51,5 +65,6 @@ export interface Tool<Args extends ToolArgs = ToolArgs, ReturnType = unknown, >
|
|
|
51
65
|
handler(
|
|
52
66
|
args: Args,
|
|
53
67
|
context: ToolContext,
|
|
68
|
+
options?: FunctionHandlerOptions,
|
|
54
69
|
): Promise<FunctionCallHandlerResult<ReturnType>>;
|
|
55
70
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
|
+
import {ExecuteJavaScriptTool} from './ExecuteJavaScript.js';
|
|
5
6
|
import {GetStylesTool} from './GetStyles.js';
|
|
6
7
|
import {type Tool, ToolName} from './Tool.js';
|
|
7
8
|
|
|
@@ -10,6 +11,7 @@ import {type Tool, ToolName} from './Tool.js';
|
|
|
10
11
|
* Keep this type concrete (no type-erasure) to preserve exact tool types.
|
|
11
12
|
*/
|
|
12
13
|
export const TOOLS = {
|
|
14
|
+
[ToolName.EXECUTE_JAVASCRIPT]: new ExecuteJavaScriptTool(),
|
|
13
15
|
[ToolName.GET_STYLES]: new GetStylesTool(),
|
|
14
16
|
};
|
|
15
17
|
|