chrome-devtools-frontend 1.0.1706026 → 1.0.1708524

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.
Files changed (86) hide show
  1. package/.agents/skills/code-review/SKILL.md +121 -0
  2. package/front_end/core/sdk/DOMModel.ts +13 -6
  3. package/front_end/core/sdk/NetworkRequest.ts +43 -7
  4. package/front_end/core/sdk/SourceMap.ts +4 -13
  5. package/front_end/core/sdk/SourceMapScopesInfo.ts +134 -86
  6. package/front_end/core/text_utils/ContentData.ts +18 -1
  7. package/front_end/entrypoints/heap_snapshot_worker/ContextAnalyzer.ts +102 -4
  8. package/front_end/generated/InspectorBackendCommands.ts +7 -1
  9. package/front_end/generated/SupportedCSSProperties.ts +11 -2
  10. package/front_end/generated/protocol-mapping.d.ts +31 -0
  11. package/front_end/generated/protocol-proxy-api.d.ts +32 -0
  12. package/front_end/generated/protocol.ts +11 -0
  13. package/front_end/models/ai_assistance/AiAgent2.ts +1 -0
  14. package/front_end/models/ai_assistance/data_formatters/LighthouseFormatter.ts +26 -3
  15. package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +15 -16
  16. package/front_end/models/ai_assistance/skills/Skill.ts +1 -2
  17. package/front_end/models/ai_assistance/skills/SkillRegistry.ts +2 -0
  18. package/front_end/models/ai_assistance/skills/lighthouse.md +33 -0
  19. package/front_end/models/ai_assistance/tools/GetLighthouseAudits.ts +6 -6
  20. package/front_end/models/ai_assistance/tools/RunLighthouse.ts +8 -5
  21. package/front_end/models/bindings/CompilerScriptMapping.ts +102 -45
  22. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +25 -33
  23. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +33 -39
  24. package/front_end/models/bindings/StylesSourceMapping.ts +3 -0
  25. package/front_end/models/extensions/ExtensionEndpoint.ts +27 -6
  26. package/front_end/models/extensions/LanguageExtensionEndpoint.ts +106 -21
  27. package/front_end/models/extensions/RecorderExtensionEndpoint.ts +4 -2
  28. package/front_end/models/javascript_metadata/NativeFunctions.ts +6 -2
  29. package/front_end/models/persistence/NetworkPersistenceManager.ts +4 -3
  30. package/front_end/models/source_map_scopes/NamesResolver.ts +0 -8
  31. package/front_end/models/stack_trace/StackTraceImpl.ts +138 -47
  32. package/front_end/models/stack_trace/StackTraceModel.ts +117 -84
  33. package/front_end/models/stack_trace/Trie.ts +27 -0
  34. package/front_end/panels/accessibility/ARIAAttributesView.ts +6 -6
  35. package/front_end/panels/accessibility/AccessibilityAnnouncementRecordingView.ts +2 -2
  36. package/front_end/panels/accessibility/AccessibilityNodeView.ts +6 -9
  37. package/front_end/panels/accessibility/AccessibilitySidebarView.ts +83 -69
  38. package/front_end/panels/accessibility/AccessibilitySubPane.ts +24 -9
  39. package/front_end/panels/accessibility/SourceOrderView.ts +7 -3
  40. package/front_end/panels/accessibility/accessibilitySidebarView.css +5 -3
  41. package/front_end/panels/application/serviceWorkersView.css +1 -1
  42. package/front_end/panels/common/CommentThreadWidget.ts +30 -1
  43. package/front_end/panels/common/CommentsOverlayWidget.ts +42 -38
  44. package/front_end/panels/common/common-meta.ts +21 -9
  45. package/front_end/panels/console/ConsoleInsightTeaser.ts +25 -19
  46. package/front_end/panels/console/ConsoleViewMessage.ts +51 -21
  47. package/front_end/panels/console/console-meta.ts +1 -5
  48. package/front_end/panels/elements/DOMTreeWidget.ts +207 -586
  49. package/front_end/panels/elements/ElementsPanel.ts +1 -5
  50. package/front_end/panels/elements/StylePropertyTreeElement.ts +100 -5
  51. package/front_end/panels/lighthouse/LighthouseController.ts +9 -4
  52. package/front_end/panels/network/NetworkConfigView.ts +231 -187
  53. package/front_end/panels/network/RequestPayloadView.ts +22 -14
  54. package/front_end/panels/profiler/HeapDetachedElementsDataGrid.ts +0 -1
  55. package/front_end/panels/recorder/RecordingView.ts +42 -47
  56. package/front_end/panels/recorder/StepEditor.ts +1 -0
  57. package/front_end/panels/recorder/recordingView.css +4 -4
  58. package/front_end/panels/sources/CSSPlugin.ts +11 -0
  59. package/front_end/panels/sources/CoveragePlugin.ts +34 -23
  60. package/front_end/panels/sources/NavigatorView.ts +97 -52
  61. package/front_end/panels/sources/Plugin.ts +15 -1
  62. package/front_end/panels/sources/SourcesView.ts +47 -80
  63. package/front_end/panels/sources/TabbedEditorContainer.ts +27 -2
  64. package/front_end/panels/sources/UISourceCodeFrame.ts +11 -2
  65. package/front_end/panels/sources/navigatorTree.css +2 -2
  66. package/front_end/third_party/chromium/README.chromium +1 -1
  67. package/front_end/ui/comments/CommentAnchorResolver.ts +17 -0
  68. package/front_end/ui/components/suggestion_input/SuggestionInput.ts +10 -1
  69. package/front_end/ui/components/text_editor/AiCodeCompletionTeaser.ts +1 -1
  70. package/front_end/ui/components/text_editor/AiCodeGenerationTeaser.ts +2 -2
  71. package/front_end/ui/components/text_editor/aiCodeCompletionTeaser.css +0 -11
  72. package/front_end/ui/components/text_editor/aiCodeGenerationTeaser.css +0 -11
  73. package/front_end/ui/legacy/SoftDropDown.ts +17 -4
  74. package/front_end/ui/legacy/StackPane.ts +141 -0
  75. package/front_end/ui/legacy/TextPrompt.ts +37 -7
  76. package/front_end/ui/legacy/Toolbar.ts +7 -5
  77. package/front_end/ui/legacy/Widget.ts +3 -3
  78. package/front_end/ui/legacy/components/inline_editor/PositionAreaEditor.ts +85 -0
  79. package/front_end/ui/legacy/components/inline_editor/positionAreaEditor.css +61 -0
  80. package/front_end/ui/legacy/components/utils/Linkifier.ts +21 -45
  81. package/front_end/ui/legacy/inspectorCommon.css +11 -0
  82. package/front_end/ui/legacy/legacy.ts +2 -0
  83. package/front_end/ui/legacy/softContextMenu.css +2 -0
  84. package/front_end/ui/settings/ConsoleSettings.ts +7 -0
  85. package/front_end/ui/visual_logging/KnownContextValues.ts +10 -0
  86. package/package.json +1 -1
@@ -28,6 +28,11 @@ type ScopeInfoNodeIndex = Platform.Brand.Brand<number, 'ScopeInfoNodeIndex'>;
28
28
  */
29
29
  type ContextNodeIndex = Platform.Brand.Brand<number, 'ContextNodeIndex'>;
30
30
 
31
+ /**
32
+ * Index of a `system / Map` node within the heap snapshot's node array.
33
+ */
34
+ type MapNodeIndex = Platform.Brand.Brand<number, 'MapNodeIndex'>;
35
+
31
36
  /**
32
37
  * Values addressed by scope. Since a `ScopeId` is only unique within its
33
38
  * script, scopes are keyed by script first.
@@ -74,6 +79,8 @@ interface ScopeAccumulator {
74
79
  }
75
80
 
76
81
  interface LiveClosure {
82
+ // The JSFunction or generator object this entry was created for.
83
+ ownerNodeIndex: number;
77
84
  contextNodeIndex: ContextNodeIndex;
78
85
  scriptNodeIndex: ScriptNodeIndex;
79
86
  scopeId: ScopeId;
@@ -99,6 +106,8 @@ interface HeapScan {
99
106
  scripts: Map<ScriptNodeIndex, ScriptInfo>;
100
107
  contextNodes: ContextNodeInfo[];
101
108
  liveClosures: LiveClosure[];
109
+ // Top-level functions of modules that finished evaluating.
110
+ finishedModuleFunctionNodeIndexes: Set<number>;
102
111
  // Maps a ScopeInfo to the script it belongs to. A stored `undefined` is a memoized
103
112
  // failed lookup. It is therefore not the same as an absent entry, which merely means
104
113
  // "not resolved yet".
@@ -114,7 +123,7 @@ export function analyzeContexts(snapshot: HeapSnapshot): HeapSnapshotModel.HeapS
114
123
  const scan = scanHeap(snapshot);
115
124
 
116
125
  // (3) Group live closures by function scope and record the context chains they can reach.
117
- const liveFunctionsByScript = buildLiveFunctions(snapshot, scan.liveClosures);
126
+ const liveFunctionsByScript = buildLiveFunctions(snapshot, scan.liveClosures, scan.finishedModuleFunctionNodeIndexes);
118
127
 
119
128
  // (4) Correlate contexts and their field values with embedded scopes.
120
129
  const {scopes, scriptsWithoutScopes} = correlateContextsWithScopes(snapshot, scan, scopesByScript);
@@ -240,6 +249,9 @@ function scanHeap(snapshot: HeapSnapshot): HeapScan {
240
249
  const scripts = new Map<ScriptNodeIndex, ScriptInfo>();
241
250
  const contextNodes: ContextNodeInfo[] = [];
242
251
  const liveClosures: LiveClosure[] = [];
252
+ const finishedModuleFunctionNodeIndexes = new Set<number>();
253
+ // Caches for each map whether it belongs to a generator object. See `isGeneratorObject`.
254
+ const generatorMapNodeIndexes = new Map<MapNodeIndex, boolean>();
243
255
  const scopeInfoScriptNodeIndexes = new Map<ScopeInfoNodeIndex, ScriptNodeIndex|undefined>();
244
256
  const node = snapshot.createNode();
245
257
  const nodes = snapshot.nodes;
@@ -257,10 +269,12 @@ function scanHeap(snapshot: HeapSnapshot): HeapScan {
257
269
  processContext(contextNodes, node);
258
270
  } else if (node.rawType() === nodeClosureType) {
259
271
  processClosure(liveClosures, node);
272
+ } else if (isGeneratorObject(generatorMapNodeIndexes, node)) {
273
+ processGeneratorObject(liveClosures, finishedModuleFunctionNodeIndexes, node);
260
274
  }
261
275
  }
262
276
 
263
- return {scripts, contextNodes, liveClosures, scopeInfoScriptNodeIndexes};
277
+ return {scripts, contextNodes, liveClosures, finishedModuleFunctionNodeIndexes, scopeInfoScriptNodeIndexes};
264
278
  }
265
279
 
266
280
  function processScript(scripts: Map<ScriptNodeIndex, ScriptInfo>, node: HeapSnapshotNode): void {
@@ -426,6 +440,11 @@ function processClosure(liveClosures: LiveClosure[], node: HeapSnapshotNode): vo
426
440
  if (!sharedFunctionInfo || !closureContext) {
427
441
  return;
428
442
  }
443
+ addLiveClosure(liveClosures, node, sharedFunctionInfo, closureContext);
444
+ }
445
+
446
+ function addLiveClosure(liveClosures: LiveClosure[], ownerNode: HeapSnapshotNode, sharedFunctionInfo: HeapSnapshotNode,
447
+ contextNode: HeapSnapshotNode): void {
429
448
  const script = sharedFunctionInfo.findInternalEdgeTarget('script');
430
449
  if (!script) {
431
450
  return;
@@ -433,18 +452,97 @@ function processClosure(liveClosures: LiveClosure[], node: HeapSnapshotNode): vo
433
452
  const scopeId = sharedFunctionInfo.findInternalEdgeTarget('scope_id')?.nodeValueAsInt() as ScopeId | undefined;
434
453
  if (scopeId !== undefined) {
435
454
  liveClosures.push({
436
- contextNodeIndex: closureContext.nodeIndex as ContextNodeIndex,
455
+ ownerNodeIndex: ownerNode.nodeIndex,
456
+ contextNodeIndex: contextNode.nodeIndex as ContextNodeIndex,
437
457
  scriptNodeIndex: script.nodeIndex as ScriptNodeIndex,
438
458
  scopeId,
439
459
  });
440
460
  }
441
461
  }
442
462
 
443
- function buildLiveFunctions(snapshot: HeapSnapshot, liveClosures: LiveClosure[]): ByScope<LiveFunction> {
463
+ // V8's `JSGeneratorObject::kGeneratorClosed`: the generator has finished and can't be resumed.
464
+ const GENERATOR_CLOSED = -1;
465
+
466
+ /**
467
+ * Handles generator objects, which V8 uses for generators, async functions, async generators and
468
+ * the top-level code of modules.
469
+ */
470
+ function processGeneratorObject(liveClosures: LiveClosure[], finishedModuleFunctionNodeIndexes: Set<number>,
471
+ node: HeapSnapshotNode): void {
472
+ const continuation = node.findInternalEdgeTarget('continuation')?.nodeValueAsInt();
473
+ const generatorFunction = node.findInternalEdgeTarget('function');
474
+ if (continuation === undefined || generatorFunction?.rawType() !== node.snapshot.nodeClosureType) {
475
+ return;
476
+ }
477
+ const sharedFunctionInfo = generatorFunction.findInternalEdgeTarget('shared');
478
+ if (!sharedFunctionInfo) {
479
+ return;
480
+ }
481
+ if (continuation === GENERATOR_CLOSED) {
482
+ const scopeId = sharedFunctionInfo.findInternalEdgeTarget('scope_id')?.nodeValueAsInt();
483
+
484
+ // Only the top-level code of a module is both a generator and a root scope.
485
+ if (scopeId !== undefined && isScriptRootScopeId(scopeId)) {
486
+ // A module stores a reference to its generator object. The generator object then
487
+ // references the top-level JSFunction. Once the generator object is finished its
488
+ // JSFunction can't run anymore and user code can't call it. Here we record such closures
489
+ // in order to skip them later in buildLiveFunctions().
490
+ finishedModuleFunctionNodeIndexes.add(generatorFunction.nodeIndex);
491
+ }
492
+
493
+ // A finished generator can't run again, so it doesn't get a LiveClosure. That way the fields
494
+ // of its context can be reported as dead.
495
+ return;
496
+ }
497
+ const generatorContext = node.findInternalEdgeTarget('context');
498
+ if (generatorContext) {
499
+ // The context of the generator's function is the one the function was created in. The body
500
+ // of the generator, however, runs in a context of its own, which only the generator object
501
+ // refers to. A generator therefore counts as a closure of its function with the context
502
+ // it resumes in.
503
+ addLiveClosure(liveClosures, node, sharedFunctionInfo, generatorContext);
504
+ }
505
+ }
506
+
507
+ // V8's instance types of `JSGeneratorObject` and its subclasses.
508
+ const GENERATOR_INSTANCE_TYPE_NAMES = new Set([
509
+ 'JS_GENERATOR_OBJECT_TYPE',
510
+ 'JS_ASYNC_FUNCTION_OBJECT_TYPE',
511
+ 'JS_ASYNC_GENERATOR_OBJECT_TYPE',
512
+ ]);
513
+
514
+ /**
515
+ * Checks the instance type of the object's map, so that other objects with fields of the same name
516
+ * aren't mistaken for generator objects. The result is cached for each map.
517
+ */
518
+ function isGeneratorObject(generatorMapNodeIndexes: Map<MapNodeIndex, boolean>, node: HeapSnapshotNode): boolean {
519
+ if (node.rawType() !== node.snapshot.nodeObjectType) {
520
+ return false;
521
+ }
522
+ const map = node.findInternalEdgeTarget('map');
523
+ if (!map) {
524
+ return false;
525
+ }
526
+ const mapNodeIndex = map.nodeIndex as MapNodeIndex;
527
+ let isGenerator = generatorMapNodeIndexes.get(mapNodeIndex);
528
+ if (isGenerator === undefined) {
529
+ const instanceTypeName = map.findInternalEdgeTarget('instance_type_name')?.rawName();
530
+ isGenerator = instanceTypeName !== undefined && GENERATOR_INSTANCE_TYPE_NAMES.has(instanceTypeName);
531
+ generatorMapNodeIndexes.set(mapNodeIndex, isGenerator);
532
+ }
533
+ return isGenerator;
534
+ }
535
+
536
+ function buildLiveFunctions(snapshot: HeapSnapshot, liveClosures: LiveClosure[],
537
+ finishedModuleFunctionNodeIndexes: Set<number>): ByScope<LiveFunction> {
444
538
  const liveFunctionsByScript: ByScope<LiveFunction> = new Map();
445
539
  const node = snapshot.createNode();
446
540
 
447
541
  for (const closure of liveClosures) {
542
+ if (finishedModuleFunctionNodeIndexes.has(closure.ownerNodeIndex)) {
543
+ // The top-level code of this module has finished and can't run anymore.
544
+ continue;
545
+ }
448
546
  let scriptFunctions = liveFunctionsByScript.get(closure.scriptNodeIndex);
449
547
  if (!scriptFunctions) {
450
548
  scriptFunctions = new Map<ScopeId, LiveFunction>();
@@ -663,6 +663,12 @@ inspectorBackend.registerType("FileSystem.File", [{"name": "name", "type": "stri
663
663
  inspectorBackend.registerType("FileSystem.Directory", [{"name": "name", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "nestedDirectories", "type": "array", "optional": false, "description": "", "typeRef": "string"}, {"name": "nestedFiles", "type": "array", "optional": false, "description": "Files that are directly nested under this directory.", "typeRef": "FileSystem.File"}]);
664
664
  inspectorBackend.registerType("FileSystem.BucketFileSystemLocator", [{"name": "storageKey", "type": "string", "optional": false, "description": "Storage key", "typeRef": "Storage.SerializedStorageKey"}, {"name": "bucketName", "type": "string", "optional": true, "description": "Bucket name. Not passing a `bucketName` will retrieve the default Bucket. (https://developer.mozilla.org/en-US/docs/Web/API/Storage_API#storage_buckets)", "typeRef": null}, {"name": "pathComponents", "type": "array", "optional": false, "description": "Path to the directory using each path component as an array item.", "typeRef": "string"}]);
665
665
 
666
+ // FindInPage.
667
+ inspectorBackend.registerCommand("FindInPage.findFirst", [{"name": "query", "type": "string", "optional": false, "description": "", "typeRef": null}], [], "Forwards `query` to the find-in-page facility, starting a new find session. Where exactly the search starts from is implementation-specific.");
668
+ inspectorBackend.registerCommand("FindInPage.findNext", [], [], "Moves to the next match for the query passed to the most recent findFirst() call.");
669
+ inspectorBackend.registerCommand("FindInPage.findPrev", [], [], "Moves to the previous match for the query passed to the most recent findFirst() call.");
670
+ inspectorBackend.registerCommand("FindInPage.stop", [], [], "Ends the current find session, if any, and clears its highlighting.");
671
+
666
672
  // HeadlessExperimental.
667
673
  inspectorBackend.registerEnum("HeadlessExperimental.ScreenshotParamsFormat", {Jpeg: "jpeg", Png: "png", Webp: "webp"});
668
674
  inspectorBackend.registerCommand("HeadlessExperimental.beginFrame", [{"name": "frameTimeTicks", "type": "number", "optional": true, "description": "Timestamp of this BeginFrame in Renderer TimeTicks (milliseconds of uptime). If not set, the current time will be used.", "typeRef": null}, {"name": "interval", "type": "number", "optional": true, "description": "The interval between BeginFrames that is reported to the compositor, in milliseconds. Defaults to a 60 frames/second interval, i.e. about 16.666 milliseconds.", "typeRef": null}, {"name": "noDisplayUpdates", "type": "boolean", "optional": true, "description": "Whether updates should not be committed and drawn onto the display. False by default. If true, only side effects of the BeginFrame will be run, such as layout and animations, but any visual updates may not be visible on the display or in screenshots.", "typeRef": null}, {"name": "screenshot", "type": "object", "optional": true, "description": "If set, a screenshot of the frame will be captured and returned in the response. Otherwise, no screenshot will be captured. Note that capturing a screenshot can fail, for example, during renderer initialization. In such a case, no screenshot data will be returned.", "typeRef": "HeadlessExperimental.ScreenshotParams"}], ["hasDamage", "screenshotData"], "Sends a BeginFrame to the target and returns when the frame was completed. Optionally captures a screenshot from the resulting frame. Requires that the target was created with enabled BeginFrameControl. Designed for use with --run-all-compositor-stages-before-draw, see also https://goo.gle/chrome-headless-rendering for more background.");
@@ -1052,7 +1058,7 @@ inspectorBackend.registerEnum("Page.AdFrameExplanation", {ParentIsAd: "ParentIsA
1052
1058
  inspectorBackend.registerEnum("Page.SecureContextType", {Secure: "Secure", SecureLocalhost: "SecureLocalhost", InsecureScheme: "InsecureScheme", InsecureAncestor: "InsecureAncestor"});
1053
1059
  inspectorBackend.registerEnum("Page.CrossOriginIsolatedContextType", {Isolated: "Isolated", NotIsolated: "NotIsolated", NotIsolatedFeatureDisabled: "NotIsolatedFeatureDisabled"});
1054
1060
  inspectorBackend.registerEnum("Page.GatedAPIFeatures", {SharedArrayBuffers: "SharedArrayBuffers", SharedArrayBuffersTransferAllowed: "SharedArrayBuffersTransferAllowed", PerformanceMeasureMemory: "PerformanceMeasureMemory", PerformanceProfile: "PerformanceProfile"});
1055
- inspectorBackend.registerEnum("Page.PermissionsPolicyFeature", {Accelerometer: "accelerometer", AllScreensCapture: "all-screens-capture", AmbientLightSensor: "ambient-light-sensor", AriaNotify: "aria-notify", Autofill: "autofill", Autoplay: "autoplay", Bluetooth: "bluetooth", BrowsingTopics: "browsing-topics", Camera: "camera", CapturedSurfaceControl: "captured-surface-control", ChDpr: "ch-dpr", ChDeviceMemory: "ch-device-memory", ChDownlink: "ch-downlink", ChEct: "ch-ect", ChPrefersColorScheme: "ch-prefers-color-scheme", ChPrefersReducedMotion: "ch-prefers-reduced-motion", ChPrefersReducedTransparency: "ch-prefers-reduced-transparency", ChRtt: "ch-rtt", ChSaveData: "ch-save-data", ChUa: "ch-ua", ChUaArch: "ch-ua-arch", ChUaBitness: "ch-ua-bitness", ChUaHighEntropyValues: "ch-ua-high-entropy-values", ChUaPlatform: "ch-ua-platform", ChUaModel: "ch-ua-model", ChUaMobile: "ch-ua-mobile", ChUaFormFactors: "ch-ua-form-factors", ChUaFullVersion: "ch-ua-full-version", ChUaFullVersionList: "ch-ua-full-version-list", ChUaPlatformVersion: "ch-ua-platform-version", ChUaWow64: "ch-ua-wow64", ChViewportHeight: "ch-viewport-height", ChViewportWidth: "ch-viewport-width", ChWidth: "ch-width", ClipboardRead: "clipboard-read", ClipboardWrite: "clipboard-write", ComputePressure: "compute-pressure", ControlledFrame: "controlled-frame", CrossOriginIsolated: "cross-origin-isolated", DeferredFetch: "deferred-fetch", DeferredFetchMinimal: "deferred-fetch-minimal", DeviceAttributes: "device-attributes", DigitalCredentialsCreate: "digital-credentials-create", DigitalCredentialsGet: "digital-credentials-get", DirectSockets: "direct-sockets", DirectSocketsMulticast: "direct-sockets-multicast", DisplayCapture: "display-capture", DocumentDomain: "document-domain", EncryptedMedia: "encrypted-media", ExecutionWhileOutOfViewport: "execution-while-out-of-viewport", ExecutionWhileNotRendered: "execution-while-not-rendered", FocusWithoutUserActivation: "focus-without-user-activation", Fullscreen: "fullscreen", Frobulate: "frobulate", Gamepad: "gamepad", Geolocation: "geolocation", Gyroscope: "gyroscope", Haptics: "haptics", Hid: "hid", IdentityCredentialsGet: "identity-credentials-get", IdleDetection: "idle-detection", InterestCohort: "interest-cohort", KeyboardMap: "keyboard-map", LanguageDetector: "language-detector", LanguageModel: "language-model", LocalFonts: "local-fonts", LocalNetwork: "local-network", LocalNetworkAccess: "local-network-access", LoopbackNetwork: "loopback-network", Magnetometer: "magnetometer", ManualText: "manual-text", MediaPlaybackWhileNotVisible: "media-playback-while-not-visible", Microphone: "microphone", Midi: "midi", OnDeviceSpeechRecognition: "on-device-speech-recognition", OtpCredentials: "otp-credentials", Payment: "payment", PictureInPicture: "picture-in-picture", PrivateStateTokenIssuance: "private-state-token-issuance", PrivateStateTokenRedemption: "private-state-token-redemption", PublickeyCredentialsCreate: "publickey-credentials-create", PublickeyCredentialsGet: "publickey-credentials-get", Rewriter: "rewriter", ScreenWakeLock: "screen-wake-lock", Serial: "serial", SharedStorage: "shared-storage", SharedStorageSelectUrl: "shared-storage-select-url", SmartCard: "smart-card", SpeakerSelection: "speaker-selection", StorageAccess: "storage-access", SubApps: "sub-apps", Summarizer: "summarizer", SyncXhr: "sync-xhr", Tools: "tools", Translator: "translator", Unload: "unload", Usb: "usb", UsbUnrestricted: "usb-unrestricted", VerticalScroll: "vertical-scroll", WebAppInstallation: "web-app-installation", Webnn: "webnn", WebPrinting: "web-printing", WebShare: "web-share", WindowManagement: "window-management", Writer: "writer", XrSpatialTracking: "xr-spatial-tracking"});
1061
+ inspectorBackend.registerEnum("Page.PermissionsPolicyFeature", {Accelerometer: "accelerometer", AllScreensCapture: "all-screens-capture", AmbientLightSensor: "ambient-light-sensor", AriaNotify: "aria-notify", Autofill: "autofill", Autoplay: "autoplay", Bluetooth: "bluetooth", BrowsingTopics: "browsing-topics", Camera: "camera", CapturedSurfaceControl: "captured-surface-control", ChDpr: "ch-dpr", ChDeviceMemory: "ch-device-memory", ChDownlink: "ch-downlink", ChEct: "ch-ect", ChPrefersColorScheme: "ch-prefers-color-scheme", ChPrefersReducedMotion: "ch-prefers-reduced-motion", ChPrefersReducedTransparency: "ch-prefers-reduced-transparency", ChRtt: "ch-rtt", ChSaveData: "ch-save-data", ChUa: "ch-ua", ChUaArch: "ch-ua-arch", ChUaBitness: "ch-ua-bitness", ChUaHighEntropyValues: "ch-ua-high-entropy-values", ChUaPlatform: "ch-ua-platform", ChUaModel: "ch-ua-model", ChUaMobile: "ch-ua-mobile", ChUaFormFactors: "ch-ua-form-factors", ChUaFullVersion: "ch-ua-full-version", ChUaFullVersionList: "ch-ua-full-version-list", ChUaPlatformVersion: "ch-ua-platform-version", ChUaWow64: "ch-ua-wow64", ChViewportHeight: "ch-viewport-height", ChViewportWidth: "ch-viewport-width", ChWidth: "ch-width", ClipboardRead: "clipboard-read", ClipboardWrite: "clipboard-write", ComputePressure: "compute-pressure", ControlledFrame: "controlled-frame", CrossOriginIsolated: "cross-origin-isolated", DeferredFetch: "deferred-fetch", DeferredFetchMinimal: "deferred-fetch-minimal", DeviceAttributes: "device-attributes", DigitalCredentialsCreate: "digital-credentials-create", DigitalCredentialsGet: "digital-credentials-get", DirectSockets: "direct-sockets", DirectSocketsMulticast: "direct-sockets-multicast", DisplayCapture: "display-capture", DocumentDomain: "document-domain", EncryptedMedia: "encrypted-media", ExecutionWhileOutOfViewport: "execution-while-out-of-viewport", ExecutionWhileNotRendered: "execution-while-not-rendered", FocusWithoutUserActivation: "focus-without-user-activation", Fullscreen: "fullscreen", Frobulate: "frobulate", Gamepad: "gamepad", Geolocation: "geolocation", Gyroscope: "gyroscope", Haptics: "haptics", Hid: "hid", IdentityCredentialsGet: "identity-credentials-get", IdleDetection: "idle-detection", InterestCohort: "interest-cohort", KeyboardMap: "keyboard-map", LanguageDetector: "language-detector", LanguageModel: "language-model", LocalFonts: "local-fonts", LocalNetwork: "local-network", LocalNetworkAccess: "local-network-access", LoopbackNetwork: "loopback-network", Magnetometer: "magnetometer", ManualText: "manual-text", MediaPlaybackWhileNotVisible: "media-playback-while-not-visible", Microphone: "microphone", Midi: "midi", OnDeviceSpeechRecognition: "on-device-speech-recognition", OtpCredentials: "otp-credentials", Payment: "payment", PictureInPicture: "picture-in-picture", PrivateStateTokenIssuance: "private-state-token-issuance", PrivateStateTokenRedemption: "private-state-token-redemption", PublickeyCredentialsCreate: "publickey-credentials-create", PublickeyCredentialsGet: "publickey-credentials-get", PublickeyCredentialsRemoteClientDataJson: "publickey-credentials-remote-client-data-json", Rewriter: "rewriter", ScreenWakeLock: "screen-wake-lock", Serial: "serial", SharedStorage: "shared-storage", SharedStorageSelectUrl: "shared-storage-select-url", SmartCard: "smart-card", SpeakerSelection: "speaker-selection", StorageAccess: "storage-access", SubApps: "sub-apps", Summarizer: "summarizer", SyncXhr: "sync-xhr", Tools: "tools", Translator: "translator", Unload: "unload", Usb: "usb", UsbUnrestricted: "usb-unrestricted", VerticalScroll: "vertical-scroll", WebAppInstallation: "web-app-installation", Webnn: "webnn", WebPrinting: "web-printing", WebShare: "web-share", WindowManagement: "window-management", Writer: "writer", XrSpatialTracking: "xr-spatial-tracking"});
1056
1062
  inspectorBackend.registerEnum("Page.PermissionsPolicyBlockReason", {Header: "Header", IframeAttribute: "IframeAttribute", InFencedFrameTree: "InFencedFrameTree", InIsolatedApp: "InIsolatedApp"});
1057
1063
  inspectorBackend.registerEnum("Page.OriginTrialTokenStatus", {Success: "Success", NotSupported: "NotSupported", Insecure: "Insecure", Expired: "Expired", WrongOrigin: "WrongOrigin", InvalidSignature: "InvalidSignature", Malformed: "Malformed", WrongVersion: "WrongVersion", FeatureDisabled: "FeatureDisabled", TokenDisabled: "TokenDisabled", FeatureDisabledForUser: "FeatureDisabledForUser", UnknownTrial: "UnknownTrial"});
1058
1064
  inspectorBackend.registerEnum("Page.OriginTrialStatus", {Enabled: "Enabled", ValidTokenNotProvided: "ValidTokenNotProvided", OSNotSupported: "OSNotSupported", TrialNotAllowed: "TrialNotAllowed"});
@@ -4603,8 +4603,16 @@ export const generatedProperties: CSSProperty[] = [
4603
4603
  "name": "position-try-order"
4604
4604
  },
4605
4605
  {
4606
+ "devtools_keywords": [
4607
+ "always",
4608
+ "anchor-valid",
4609
+ "anchor-visible",
4610
+ "no-overflow"
4611
+ ],
4606
4612
  "keywords": [
4607
4613
  "always",
4614
+ "anchor-valid",
4615
+ "anchor-visible",
4608
4616
  "anchors-visible",
4609
4617
  "no-overflow"
4610
4618
  ],
@@ -5482,7 +5490,7 @@ export const generatedProperties: CSSProperty[] = [
5482
5490
  ],
5483
5491
  "name": "text-decoration-inset",
5484
5492
  "runtime_flag": "CSSTextDecorationInset",
5485
- "runtime_flag_status": "experimental"
5493
+ "runtime_flag_status": "stable"
5486
5494
  },
5487
5495
  {
5488
5496
  "keywords": [
@@ -8484,7 +8492,8 @@ export const generatedPropertyValues: Record<string, CSSPropertyValue> = {
8484
8492
  "position-visibility": {
8485
8493
  "values": [
8486
8494
  "always",
8487
- "anchors-visible",
8495
+ "anchor-valid",
8496
+ "anchor-visible",
8488
8497
  "no-overflow"
8489
8498
  ]
8490
8499
  },
@@ -3082,6 +3082,37 @@ export namespace ProtocolMapping {
3082
3082
  paramsType: [Protocol.FileSystem.GetDirectoryRequest];
3083
3083
  returnType: Protocol.FileSystem.GetDirectoryResponse;
3084
3084
  };
3085
+ /**
3086
+ * Forwards `query` to the find-in-page facility, starting a new find session.
3087
+ * Where exactly the search starts from is implementation-specific.
3088
+ */
3089
+ 'FindInPage.findFirst': {
3090
+ paramsType: [Protocol.FindInPage.FindFirstRequest];
3091
+ returnType: void;
3092
+ };
3093
+ /**
3094
+ * Moves to the next match for the query passed to the most recent
3095
+ * findFirst() call.
3096
+ */
3097
+ 'FindInPage.findNext': {
3098
+ paramsType: [];
3099
+ returnType: void;
3100
+ };
3101
+ /**
3102
+ * Moves to the previous match for the query passed to the most recent
3103
+ * findFirst() call.
3104
+ */
3105
+ 'FindInPage.findPrev': {
3106
+ paramsType: [];
3107
+ returnType: void;
3108
+ };
3109
+ /**
3110
+ * Ends the current find session, if any, and clears its highlighting.
3111
+ */
3112
+ 'FindInPage.stop': {
3113
+ paramsType: [];
3114
+ returnType: void;
3115
+ };
3085
3116
  /**
3086
3117
  * Sends a BeginFrame to the target and returns when the frame was completed. Optionally captures a
3087
3118
  * screenshot from the resulting frame. Requires that the target was created with enabled
@@ -68,6 +68,8 @@ declare namespace ProtocolProxyApi {
68
68
 
69
69
  FileSystem: FileSystemApi;
70
70
 
71
+ FindInPage: FindInPageApi;
72
+
71
73
  HeadlessExperimental: HeadlessExperimentalApi;
72
74
 
73
75
  IO: IOApi;
@@ -185,6 +187,8 @@ declare namespace ProtocolProxyApi {
185
187
 
186
188
  FileSystem: FileSystemDispatcher;
187
189
 
190
+ FindInPage: FindInPageDispatcher;
191
+
188
192
  HeadlessExperimental: HeadlessExperimentalDispatcher;
189
193
 
190
194
  IO: IODispatcher;
@@ -2181,6 +2185,34 @@ declare namespace ProtocolProxyApi {
2181
2185
  export interface FileSystemDispatcher {
2182
2186
  }
2183
2187
 
2188
+ export interface FindInPageApi {
2189
+ /**
2190
+ * Forwards `query` to the find-in-page facility, starting a new find session.
2191
+ * Where exactly the search starts from is implementation-specific.
2192
+ */
2193
+ invoke_findFirst(params: Protocol.FindInPage.FindFirstRequest): Promise<Protocol.ProtocolResponseWithError>;
2194
+
2195
+ /**
2196
+ * Moves to the next match for the query passed to the most recent
2197
+ * findFirst() call.
2198
+ */
2199
+ invoke_findNext(): Promise<Protocol.ProtocolResponseWithError>;
2200
+
2201
+ /**
2202
+ * Moves to the previous match for the query passed to the most recent
2203
+ * findFirst() call.
2204
+ */
2205
+ invoke_findPrev(): Promise<Protocol.ProtocolResponseWithError>;
2206
+
2207
+ /**
2208
+ * Ends the current find session, if any, and clears its highlighting.
2209
+ */
2210
+ invoke_stop(): Promise<Protocol.ProtocolResponseWithError>;
2211
+
2212
+ }
2213
+ export interface FindInPageDispatcher {
2214
+ }
2215
+
2184
2216
  export interface HeadlessExperimentalApi {
2185
2217
  /**
2186
2218
  * Sends a BeginFrame to the target and returns when the frame was completed. Optionally captures a
@@ -8702,6 +8702,16 @@ export namespace FileSystem {
8702
8702
  }
8703
8703
  }
8704
8704
 
8705
+ /**
8706
+ * This domain provides commands to trigger the "Find in page" feature.
8707
+ */
8708
+ export namespace FindInPage {
8709
+
8710
+ export interface FindFirstRequest {
8711
+ query: string;
8712
+ }
8713
+ }
8714
+
8705
8715
  /**
8706
8716
  * This domain provides experimental commands only supported in headless mode.
8707
8717
  */
@@ -14808,6 +14818,7 @@ export namespace Page {
14808
14818
  PrivateStateTokenRedemption = 'private-state-token-redemption',
14809
14819
  PublickeyCredentialsCreate = 'publickey-credentials-create',
14810
14820
  PublickeyCredentialsGet = 'publickey-credentials-get',
14821
+ PublickeyCredentialsRemoteClientDataJson = 'publickey-credentials-remote-client-data-json',
14811
14822
  Rewriter = 'rewriter',
14812
14823
  ScreenWakeLock = 'screen-wake-lock',
14813
14824
  Serial = 'serial',
@@ -41,6 +41,7 @@ const SKILL_DISPLAY_NAMES: Record<SkillName, string> = {
41
41
  performance: 'Performance',
42
42
  storage: 'Storage',
43
43
  sources: 'Sources',
44
+ lighthouse: 'Lighthouse',
44
45
  };
45
46
 
46
47
  const preamble = `You are the most advanced unified AI assistant integrated into Chrome DevTools.
@@ -6,6 +6,12 @@ import type * as LHModel from '../../lighthouse/lighthouse.js';
6
6
 
7
7
  import {bytes, millis} from './UnitFormatters.js';
8
8
 
9
+ /**
10
+ * Category argument for Lighthouse tools, accepting a specific category ID or `'all'`
11
+ * to target a full report across all standard categories.
12
+ */
13
+ export type LighthouseCategoryArg = 'all'|LHModel.RunTypes.CategoryId;
14
+
9
15
  /**
10
16
  * A formatter that takes a raw Lighthouse report JSON and creates a markdown
11
17
  * summary for an AI Agent.
@@ -29,14 +35,31 @@ export class LighthouseFormatter {
29
35
  return lines.join('\n');
30
36
  }
31
37
 
38
+ /**
39
+ * Formats a Lighthouse report for an AI Agent. If categoryId is 'all', includes
40
+ * the overall summary followed by each category's audits. Otherwise, returns audits
41
+ * for the specified category.
42
+ */
43
+ formatReport(report: LHModel.ReporterTypes.ReportJSON, categoryId: LighthouseCategoryArg): string {
44
+ if (categoryId === 'all') {
45
+ const sections: string[] = [this.summary(report)];
46
+ for (const category of Object.values(report.categories)) {
47
+ sections.push(this.audits(report, category));
48
+ }
49
+ return sections.join('\n\n');
50
+ }
51
+ return this.audits(report, categoryId);
52
+ }
53
+
32
54
  /**
33
55
  * Returns a markdown list of all audits in a given category.
34
56
  * Highlight failing audits (score < 90).
35
57
  */
36
- audits(report: LHModel.ReporterTypes.ReportJSON, categoryId: LHModel.RunTypes.CategoryId): string {
37
- const category = report.categories[categoryId];
58
+ audits(report: LHModel.ReporterTypes.ReportJSON,
59
+ categoryOrId: LHModel.RunTypes.CategoryId|LHModel.ReporterTypes.CategoryJSON): string {
60
+ const category = typeof categoryOrId === 'string' ? report.categories[categoryOrId] : categoryOrId;
38
61
  if (!category) {
39
- return `Category "${categoryId}" not found.`;
62
+ return `Category "${categoryOrId}" not found.`;
40
63
  }
41
64
 
42
65
  const lines: string[] = [];
@@ -2,7 +2,6 @@
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 type * as Platform from '../../../core/platform/platform.js';
6
5
  import * as SDK from '../../../core/sdk/sdk.js';
7
6
  import * as TextUtils from '../../../core/text_utils/text_utils.js';
8
7
  import * as Protocol from '../../../generated/protocol.js';
@@ -122,14 +121,19 @@ export class NetworkRequestFormatter {
122
121
  return `${title}\n<binary data>`;
123
122
  }
124
123
 
124
+ /**
125
+ * Returns the URL of `initiator` if it is same-origin with `request`, or a redaction
126
+ * placeholder otherwise.
127
+ *
128
+ * Both sides use `requestURLSecurityOrigin()`, so imported HAR requests are compared
129
+ * using their `imported-har://` origins.
130
+ */
125
131
  static formatInitiatorUrl(
126
- initiatorUrl: Platform.DevToolsPath.UrlString,
127
- allowedOrigin: Platform.DevToolsPath.UrlString,
132
+ initiator: SDK.NetworkRequest.NetworkRequest,
133
+ request: SDK.NetworkRequest.NetworkRequest,
128
134
  ): string {
129
- const initiatorOrigin = SDK.SecurityOrigin.SecurityOrigin.create(initiatorUrl);
130
- const targetOrigin = SDK.SecurityOrigin.SecurityOrigin.create(allowedOrigin);
131
- if (initiatorOrigin.isSameOriginWith(targetOrigin)) {
132
- return initiatorUrl;
135
+ if (initiator.requestURLSecurityOrigin().isSameOriginWith(request.requestURLSecurityOrigin())) {
136
+ return initiator.url();
133
137
  }
134
138
  return '<redacted cross-origin initiator URL>';
135
139
  }
@@ -329,18 +333,15 @@ export function formatRequestInitiatorChain(
329
333
  request: SDK.NetworkRequest.NetworkRequest,
330
334
  networkLog: Logs.NetworkLog.NetworkLog,
331
335
  ): string {
332
- const allowedOrigin = request.url();
333
336
  let initiatorChain = '';
334
337
  let lineStart = '- URL: ';
335
338
  const graph = networkLog.initiatorGraphForRequest(request);
336
339
 
337
340
  for (const initiator of Array.from(graph.initiators).reverse()) {
338
- initiatorChain =
339
- initiatorChain + lineStart + NetworkRequestFormatter.formatInitiatorUrl(initiator.url(), allowedOrigin) + '\n';
341
+ initiatorChain = initiatorChain + lineStart + NetworkRequestFormatter.formatInitiatorUrl(initiator, request) + '\n';
340
342
  lineStart = '\t' + lineStart;
341
343
  if (initiator === request) {
342
- initiatorChain =
343
- formatRequestInitiated(graph.initiated, request, request, initiatorChain, lineStart, allowedOrigin);
344
+ initiatorChain = formatRequestInitiated(graph.initiated, request, request, initiatorChain, lineStart);
344
345
  }
345
346
  }
346
347
 
@@ -353,7 +354,6 @@ function formatRequestInitiated(
353
354
  parentRequest: SDK.NetworkRequest.NetworkRequest,
354
355
  initiatorChain: string,
355
356
  lineStart: string,
356
- allowedOrigin: Platform.DevToolsPath.UrlString,
357
357
  ): string {
358
358
  const visited = new Set<SDK.NetworkRequest.NetworkRequest>();
359
359
 
@@ -363,10 +363,9 @@ function formatRequestInitiated(
363
363
  if (initiatedRequest === parentRequest) {
364
364
  if (!visited.has(keyRequest)) {
365
365
  visited.add(keyRequest);
366
- initiatorChain = initiatorChain + lineStart +
367
- NetworkRequestFormatter.formatInitiatorUrl(keyRequest.url(), allowedOrigin) + '\n';
368
366
  initiatorChain =
369
- formatRequestInitiated(initiated, rootRequest, keyRequest, initiatorChain, '\t' + lineStart, allowedOrigin);
367
+ initiatorChain + lineStart + NetworkRequestFormatter.formatInitiatorUrl(keyRequest, rootRequest) + '\n';
368
+ initiatorChain = formatRequestInitiated(initiated, rootRequest, keyRequest, initiatorChain, '\t' + lineStart);
370
369
  }
371
370
  }
372
371
  }
@@ -2,8 +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
- // This will become a union type as we add more skills (e.g. 'styling' | 'network').
6
- export type SkillName = 'styling'|'network'|'accessibility'|'performance'|'storage'|'sources';
5
+ export type SkillName = 'styling'|'network'|'accessibility'|'performance'|'storage'|'sources'|'lighthouse';
7
6
 
8
7
  export interface Skill {
9
8
  name: SkillName;
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import {skill as accessibilitySkill} from './accessibility.skill.js';
6
+ import {skill as lighthouseSkill} from './lighthouse.skill.js';
6
7
  import {skill as networkSkill} from './network.skill.js';
7
8
  import {skill as performanceSkill} from './performance.skill.js';
8
9
  import type {Skill, SkillName} from './Skill.js';
@@ -17,4 +18,5 @@ export const SKILLS: Record<SkillName, Skill> = {
17
18
  performance: performanceSkill,
18
19
  storage: storageSkill,
19
20
  sources: sourcesSkill,
21
+ lighthouse: lighthouseSkill,
20
22
  };
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: lighthouse
3
+ description: Running Lighthouse reports and audits, full-page audits (performance, accessibility, best practices, Search Engine Optimization (SEO)), and inspecting Lighthouse scores.
4
+ allowed-tools:
5
+ - runLighthouse
6
+ - getLighthouseAudits
7
+ - resolveDevtoolsNodePath
8
+ ---
9
+ You are an expert web quality and audit assistant integrated into Chrome DevTools.
10
+ Your role is to evaluate websites using Lighthouse audits across performance, accessibility, best practices, and SEO.
11
+
12
+ # Tools & Workflow
13
+
14
+ 1. **Lighthouse Audits (`runLighthouse` & `getLighthouseAudits`)**:
15
+ - If an active Lighthouse report context already exists and no fresh audit is requested:
16
+ - To inspect the entire report or multiple categories, call `getLighthouseAudits` with `categoryId: 'all'`.
17
+ - For a specific category, call `getLighthouseAudits` with the corresponding category ID (e.g. `'performance'`, `'accessibility'`, `'best-practices'`, `'seo'`).
18
+ - If no active report exists or a fresh audit is requested, call `runLighthouse`:
19
+ - If the user asks for a general report or multiple categories, use `categoryId: 'all'`.
20
+ - For a single category, pass that category ID.
21
+ - Execution mode:
22
+ - Use `"navigation"` mode for full page-load audits (default for full site reviews).
23
+ - Use `"snapshot"` mode to re-evaluate live in-page DOM/CSS modifications without reloading.
24
+ - Use `"timespan"` mode for user interaction flows.
25
+ - Always honor explicit mode requests from the user.
26
+
27
+ 2. **Resolving Node References (`resolveDevtoolsNodePath`)**:
28
+ - When an audit references failing elements by DevTools node path (e.g. `"1,HTML,1,BODY,2,BUTTON"`), use `resolveDevtoolsNodePath` to resolve the path to a `backendNodeId` to identify the failing element (or inspect it using tools from other skills if active).
29
+
30
+ # Considerations
31
+
32
+ - Base all analysis on empirical Lighthouse audit data. Never fabricate audit scores or results.
33
+ - When summarizing a full Lighthouse run, highlight overall category scores first, then detail failing audits (score < 90).
@@ -3,8 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as Host from '../../../core/host/host.js';
6
- import type * as LHModel from '../../lighthouse/lighthouse.js';
7
- import {LighthouseFormatter} from '../data_formatters/LighthouseFormatter.js';
6
+ import {type LighthouseCategoryArg, LighthouseFormatter} from '../data_formatters/LighthouseFormatter.js';
8
7
 
9
8
  import {
10
9
  type BaseToolCapability,
@@ -16,14 +15,14 @@ import {
16
15
  } from './Tool.js';
17
16
 
18
17
  export interface GetLighthouseAuditsArgs extends ToolArgs {
19
- categoryId: LHModel.RunTypes.CategoryId;
18
+ categoryId: LighthouseCategoryArg;
20
19
  }
21
20
 
22
21
  export class GetLighthouseAuditsTool implements
23
22
  DataTool<GetLighthouseAuditsArgs, {audits: string}, BaseToolCapability&LighthouseReportCapability> {
24
23
  readonly name: ToolName = ToolName.GET_LIGHTHOUSE_AUDITS;
25
24
  readonly description: string =
26
- 'Retrieves audit results and diagnostic details from the active Lighthouse report for a specific category (e.g., \'accessibility\').';
25
+ 'Retrieves audit results and diagnostic details from the active Lighthouse report for all categories (using categoryId: "all") or a specific category (e.g., \'accessibility\').';
27
26
 
28
27
  readonly parameters: Host.AidaClient.FunctionObjectParam<keyof GetLighthouseAuditsArgs> = {
29
28
  type: Host.AidaClient.ParametersTypes.OBJECT,
@@ -32,7 +31,8 @@ export class GetLighthouseAuditsTool implements
32
31
  properties: {
33
32
  categoryId: {
34
33
  type: Host.AidaClient.ParametersTypes.STRING,
35
- description: 'The category of audits to retrieve. E.g. "accessibility".',
34
+ description:
35
+ 'The category of audits to retrieve. Use "all" to retrieve the full report and all categories, or specify a category: "accessibility", "performance", "best-practices", "seo".',
36
36
  nullable: false,
37
37
  },
38
38
  },
@@ -52,7 +52,7 @@ export class GetLighthouseAuditsTool implements
52
52
  if (!report) {
53
53
  return {error: 'Error: Active context is not a Lighthouse report.'};
54
54
  }
55
- const audits = new LighthouseFormatter().audits(report, params.categoryId);
55
+ const audits = new LighthouseFormatter().formatReport(report, params.categoryId);
56
56
  return {
57
57
  result: {audits},
58
58
  widgets: [{name: 'LIGHTHOUSE_REPORT', data: {report}}],