chrome-devtools-frontend 1.0.1717196 → 1.0.1721762

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 (381) hide show
  1. package/.agents/rules/models-and-core/core-ai-agent-context-and-prompt-discipline.md +29 -0
  2. package/.agents/rules/models-and-core/core-cdp-and-extension-error-handling.md +34 -0
  3. package/.agents/rules/models-and-core/core-gn-build-and-module-layering.md +23 -0
  4. package/.agents/rules/models-and-core/core-runtime-neutrality-and-platform-utils.md +28 -0
  5. package/.agents/rules/models-and-core/core-sdk-model-and-target-lifecycle.md +35 -0
  6. package/.agents/rules/models-and-core/core-security-origin-and-capability-guards.md +33 -0
  7. package/.agents/rules/models-and-core/core-settings-and-storage-migration.md +31 -0
  8. package/.agents/rules/models-and-core/core-sourcemap-and-workspace-mapping.md +28 -0
  9. package/.agents/rules/models-and-core/core-trace-engine-handler-invariants.md +32 -0
  10. package/.agents/rules/models-and-core/core-trace-insight-models-and-timing-types.md +28 -0
  11. package/.agents/rules/tests/test-cleanup-mutated-globals-and-widgets.md +40 -0
  12. package/.agents/rules/tests/test-deterministic-async-synchronization.md +30 -0
  13. package/.agents/rules/tests/test-modular-hooks-and-test-universe.md +38 -0
  14. package/.agents/rules/tests/test-public-api-and-encapsulation.md +30 -0
  15. package/.agents/rules/tests/test-shared-fixture-and-helper-reuse.md +29 -0
  16. package/.agents/rules/tests/test-single-responsibility-and-conciseness.md +37 -0
  17. package/.agents/rules/tests/test-strict-assertions-and-literal-expectations.md +31 -0
  18. package/.agents/rules/tests/test-type-safe-mocks-and-events.md +30 -0
  19. package/.agents/rules/tests/test-view-and-presenter-isolation.md +32 -0
  20. package/.agents/rules/ui-and-widgets/ui-accessibility-and-semantic-html.md +32 -0
  21. package/.agents/rules/ui-and-widgets/ui-await-update-complete-post-render.md +30 -0
  22. package/.agents/rules/ui-and-widgets/ui-css-scoping-and-flex-layout.md +27 -0
  23. package/.agents/rules/ui-and-widgets/ui-declarative-child-widget-composition.md +29 -0
  24. package/.agents/rules/ui-and-widgets/ui-lit-declarative-templates-and-directives.md +33 -0
  25. package/.agents/rules/ui-and-widgets/ui-localization-and-uistrings-hygiene.md +36 -0
  26. package/.agents/rules/ui-and-widgets/ui-modern-component-and-encapsulation-standards.md +32 -0
  27. package/.agents/rules/ui-and-widgets/ui-panel-and-meta-registration.md +35 -0
  28. package/.agents/rules/ui-and-widgets/ui-performance-and-flamechart-rendering.md +34 -0
  29. package/.agents/rules/ui-and-widgets/ui-pure-view-and-presenter-separation.md +31 -0
  30. package/.agents/rules/ui-and-widgets/ui-reactive-widget-update-lifecycle.md +34 -0
  31. package/.agents/rules/ui-and-widgets/ui-security-and-output-sanitization.md +28 -0
  32. package/.agents/rules/ui-and-widgets/ui-type-safety-and-exhaustiveness.md +37 -0
  33. package/.agents/rules/ui-and-widgets/ui-view-output-and-callback-contracts.md +35 -0
  34. package/.agents/rules/ui-and-widgets/ui-visual-logging-instrumentation.md +29 -0
  35. package/.agents/rules/ui-and-widgets/ui-weak-dom-references-and-observer-cleanup.md +29 -0
  36. package/.agents/rules/ui-and-widgets/ui-widget-dom-and-listener-lifecycle.md +38 -0
  37. package/.agents/skills/code-review/SKILL.md +3 -0
  38. package/.agents/skills/devtools-testing-guidance/SKILL.md +5 -2
  39. package/.agents/skills/review-models-core/SKILL.md +73 -0
  40. package/.agents/skills/review-tests/SKILL.md +67 -0
  41. package/.agents/skills/review-ui-widgets/SKILL.md +115 -0
  42. package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +73 -9
  43. package/.agents/skills/ui-eng-vision-logic-consolidator/SKILL.md +27 -3
  44. package/.agents/skills/ui-eng-vision-orchestrator/SKILL.md +32 -2
  45. package/.agents/skills/ui-eng-vision-test-scaffolder/SKILL.md +37 -7
  46. package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +6 -5
  47. package/.agents/skills/ui-widgets/SKILL.md +11 -9
  48. package/AUTHORS +3 -0
  49. package/DIR_METADATA +51 -1
  50. package/docs/ui_engineering.md +34 -0
  51. package/eslint.config.mjs +63 -21
  52. package/front_end/core/common/Settings.ts +5 -0
  53. package/front_end/core/host/UserMetricsEnums.ts +1 -0
  54. package/front_end/core/platform/api/HostRuntime.ts +1 -0
  55. package/front_end/core/platform/browser/HostRuntime.ts +10 -0
  56. package/front_end/core/platform/node/HostRuntime.ts +1 -0
  57. package/front_end/core/sdk/CSSMatchedStyles.ts +60 -20
  58. package/front_end/core/sdk/CSSModel.ts +21 -0
  59. package/front_end/core/sdk/CSSProperty.ts +2 -2
  60. package/front_end/core/sdk/CSSPropertyParser.ts +11 -2
  61. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +28 -9
  62. package/front_end/core/sdk/DOMModel.ts +1 -1
  63. package/front_end/core/sdk/DebuggerModel.ts +3 -0
  64. package/front_end/core/sdk/EmulationModel.ts +40 -39
  65. package/front_end/core/sdk/NetworkManager.ts +10 -3
  66. package/front_end/core/sdk/NetworkRequest.ts +21 -0
  67. package/front_end/core/sdk/OverlayModel.ts +2 -8
  68. package/front_end/core/sdk/PrivateVerificationTokensModel.ts +79 -0
  69. package/front_end/core/sdk/RuntimeModel.ts +8 -3
  70. package/front_end/core/sdk/SecurityOrigin.ts +1 -1
  71. package/front_end/core/sdk/SourceMapCache.ts +20 -15
  72. package/front_end/core/sdk/SourceMapManager.ts +28 -9
  73. package/front_end/core/sdk/TargetManager.ts +7 -4
  74. package/front_end/core/sdk/WebAuthnModel.ts +11 -2
  75. package/front_end/core/sdk/sdk.ts +2 -0
  76. package/front_end/devtools_compatibility.js +1 -0
  77. package/front_end/entrypoints/inspector_main/InspectorMain.ts +0 -2
  78. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +10 -0
  79. package/front_end/entrypoints/main/GlobalAiButton.ts +1 -1
  80. package/front_end/entrypoints/main/MainImpl.ts +5 -2
  81. package/front_end/foundation/Universe.ts +1 -1
  82. package/front_end/generated/Deprecation.ts +4 -7
  83. package/front_end/generated/InspectorBackendCommands.ts +4 -4
  84. package/front_end/generated/SupportedCSSProperties.ts +89 -17
  85. package/front_end/generated/protocol-mapping.d.ts +1 -0
  86. package/front_end/generated/protocol-proxy-api.d.ts +1 -0
  87. package/front_end/generated/protocol.ts +6 -3
  88. package/front_end/models/{ai_assistance → ai-utils}/AiHistoryStorage.ts +6 -5
  89. package/front_end/models/{ai_assistance → ai-utils}/AiUtils.ts +14 -2
  90. package/front_end/models/{ai_assistance → ai-utils}/BuiltInAi.ts +1 -1
  91. package/front_end/models/ai-utils/ai-utils.ts +17 -0
  92. package/front_end/models/ai_assistance/AiAgent2.ts +14 -6
  93. package/front_end/models/ai_assistance/AiConversation.ts +37 -24
  94. package/front_end/models/ai_assistance/AlwaysAllowedTools.ts +107 -0
  95. package/front_end/models/ai_assistance/ConversationSummary.ts +2 -1
  96. package/front_end/models/ai_assistance/PerformanceAnnotations.ts +3 -1
  97. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +12 -5
  98. package/front_end/models/ai_assistance/agents/AiAgent.ts +261 -127
  99. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +12 -6
  100. package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +3 -1
  101. package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +1 -1
  102. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +3 -1
  103. package/front_end/models/ai_assistance/ai_assistance.ts +9 -10
  104. package/front_end/models/ai_assistance/data_formatters/FileFormatter.ts +27 -6
  105. package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +2 -9
  106. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +3 -3
  107. package/front_end/models/ai_assistance/skills/sources.md +3 -1
  108. package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +1 -0
  109. package/front_end/models/ai_assistance/tools/GetCookieValues.ts +1 -0
  110. package/front_end/models/ai_assistance/tools/GetInsightDetails.ts +3 -1
  111. package/front_end/models/ai_assistance/tools/GetSourceContent.ts +46 -4
  112. package/front_end/models/ai_assistance/tools/GetStorageValues.ts +1 -0
  113. package/front_end/models/ai_assistance/tools/RunLighthouse.ts +6 -3
  114. package/front_end/models/ai_assistance/tools/Tool.ts +11 -1
  115. package/front_end/models/bindings/CompilerScriptMapping.ts +40 -8
  116. package/front_end/models/bindings/ResourceScriptMapping.ts +1 -1
  117. package/front_end/models/breakpoints/BreakpointManager.ts +0 -4
  118. package/front_end/models/change_tracker/ChangeTracker.ts +2 -0
  119. package/front_end/models/comment_manager/CommentManager.ts +12 -0
  120. package/front_end/models/comment_manager/CommentThread.ts +34 -1
  121. package/front_end/models/computed_style/ComputedStyleModel.ts +1 -0
  122. package/front_end/models/elements/ChangeTrackingUtils.ts +37 -0
  123. package/front_end/models/elements/DOMChanges.ts +24 -36
  124. package/front_end/models/elements/StyleChanges.ts +97 -0
  125. package/front_end/models/elements/elements.ts +4 -0
  126. package/front_end/models/emulation/DeviceModeModel.ts +19 -0
  127. package/front_end/models/issues_manager/GenericIssue.ts +18 -0
  128. package/front_end/models/issues_manager/descriptions/genericGeolocationPromptWithoutUserGesture.md +5 -0
  129. package/front_end/models/javascript_metadata/NativeFunctions.ts +11 -5
  130. package/front_end/models/lighthouse/RunTypes.ts +16 -0
  131. package/front_end/models/stack_trace/StackTraceModel.ts +24 -3
  132. package/front_end/models/trace/EventsSerializer.ts +35 -2
  133. package/front_end/models/trace/extras/TraceTree.ts +2 -7
  134. package/front_end/models/trace/handlers/LayoutShiftsHandler.ts +17 -21
  135. package/front_end/models/trace/helpers/SyntheticEvents.ts +4 -2
  136. package/front_end/models/trace/helpers/Timing.ts +11 -22
  137. package/front_end/models/trace/lantern/core/NetworkAnalyzer.ts +12 -8
  138. package/front_end/models/trace/types/File.ts +20 -3
  139. package/front_end/models/trace/types/TraceEvents.ts +8 -3
  140. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +37 -2
  141. package/front_end/panels/ai_assistance/README.md +4 -2
  142. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +1 -1
  143. package/front_end/panels/ai_assistance/ai_assistance.ts +2 -0
  144. package/front_end/panels/ai_assistance/components/ChatInput.ts +5 -43
  145. package/front_end/panels/ai_assistance/components/ChatMessage.ts +52 -147
  146. package/front_end/panels/ai_assistance/components/ChatView.ts +28 -3
  147. package/front_end/panels/ai_assistance/components/PermissionPrompt.ts +151 -0
  148. package/front_end/panels/ai_assistance/components/RelevantDataDisclaimer.ts +73 -0
  149. package/front_end/panels/ai_assistance/components/chatInput.css +0 -59
  150. package/front_end/panels/ai_assistance/components/chatMessage.css +0 -47
  151. package/front_end/panels/ai_assistance/components/chatView.css +5 -30
  152. package/front_end/panels/ai_assistance/components/permissionPrompt.css +55 -0
  153. package/front_end/panels/ai_assistance/components/relevantDataDisclaimer.css +35 -0
  154. package/front_end/panels/application/AppManifestView.ts +1 -4
  155. package/front_end/panels/application/ApplicationPanelSidebar.ts +3 -7
  156. package/front_end/panels/application/BackgroundServiceView.ts +8 -8
  157. package/front_end/panels/application/IndexedDBViews.ts +102 -73
  158. package/front_end/panels/application/OpenedWindowDetailsView.ts +167 -130
  159. package/front_end/panels/application/ServiceWorkerCacheViews.ts +288 -346
  160. package/front_end/panels/application/StorageBucketsTreeElement.ts +22 -27
  161. package/front_end/panels/application/StorageItemsToolbar.ts +2 -2
  162. package/front_end/panels/application/components/StorageMetadataView.ts +207 -160
  163. package/front_end/panels/application/openedWindowDetailsView.css +7 -30
  164. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +1 -1
  165. package/front_end/panels/changes/changesView.css +0 -6
  166. package/front_end/panels/comments/CommentsPane.ts +7 -3
  167. package/front_end/panels/comments/comments-meta.ts +1 -1
  168. package/front_end/panels/common/CommentThreadWidget.ts +67 -25
  169. package/front_end/panels/common/CommentsOverlayWidget.ts +13 -0
  170. package/front_end/panels/console/ConsoleInsightTeaser.ts +5 -1
  171. package/front_end/panels/console/ConsolePinPane.ts +1 -1
  172. package/front_end/panels/console/ConsoleView.ts +1 -0
  173. package/front_end/panels/elements/CSSValueTraceView.ts +5 -5
  174. package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +14 -6
  175. package/front_end/panels/elements/ComputedStyleWidget.ts +14 -5
  176. package/front_end/panels/elements/DOMTreeElementWidget.ts +2 -2
  177. package/front_end/panels/elements/DOMTreeWidget.ts +7 -3
  178. package/front_end/panels/elements/EventListenersWidget.ts +1 -1
  179. package/front_end/panels/elements/LayersWidget.ts +1 -1
  180. package/front_end/panels/elements/PropertyRenderer.ts +178 -10
  181. package/front_end/panels/elements/StandaloneStylesContainer.ts +33 -6
  182. package/front_end/panels/elements/StylePropertiesSection.ts +1 -0
  183. package/front_end/panels/elements/StylePropertyTreeElement.ts +295 -116
  184. package/front_end/panels/elements/StylesContainer.ts +2 -0
  185. package/front_end/panels/elements/StylesSidebarPane.ts +34 -16
  186. package/front_end/panels/elements/components/QueryContainer.ts +1 -1
  187. package/front_end/panels/elements/elementStatePaneWidget.css +1 -1
  188. package/front_end/panels/elements/stylePropertiesTreeOutline.css +7 -2
  189. package/front_end/panels/elements/stylesSidebarPane.css +4 -0
  190. package/front_end/panels/emulation/DeviceModeToolbar.ts +57 -25
  191. package/front_end/panels/emulation/DeviceModeView.ts +27 -1
  192. package/front_end/panels/emulation/InspectedPagePlaceholder.ts +6 -0
  193. package/front_end/panels/emulation/MediaQueryInspector.ts +14 -4
  194. package/front_end/panels/emulation/deviceModeView.css +3 -3
  195. package/front_end/panels/explain/components/ConsoleInsight.ts +2 -3
  196. package/front_end/panels/explain/explain-meta.ts +1 -1
  197. package/front_end/panels/issues/AffectedMetadataAllowedSitesView.ts +67 -34
  198. package/front_end/panels/issues/issues.ts +2 -0
  199. package/front_end/panels/layer_viewer/LayerTreeOutline.ts +7 -3
  200. package/front_end/panels/lighthouse/LighthouseController.ts +29 -22
  201. package/front_end/panels/lighthouse/LighthousePanel.ts +5 -6
  202. package/front_end/panels/lighthouse/LighthouseProtocolService.ts +24 -16
  203. package/front_end/panels/media/PlayerMessagesView.ts +1 -1
  204. package/front_end/panels/mobile_throttling/CPUThrottlingSelector.ts +1 -1
  205. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +45 -15
  206. package/front_end/panels/mobile_throttling/ThrottlingManager.ts +3 -3
  207. package/front_end/panels/network/BinaryResourceView.ts +54 -50
  208. package/front_end/panels/network/RequestHeadersView.ts +6 -2
  209. package/front_end/panels/network/RequestPreviewView.ts +28 -5
  210. package/front_end/panels/network/ResourceWebSocketFrameView.ts +1 -0
  211. package/front_end/panels/network/components/EditableSpan.ts +11 -30
  212. package/front_end/panels/network/components/HeaderSectionRow.ts +2 -2
  213. package/front_end/panels/performance_monitor/PerformanceMonitor.ts +10 -6
  214. package/front_end/panels/profiler/HeapDetachedElementsView.ts +112 -22
  215. package/front_end/panels/profiler/HeapProfileView.ts +3 -3
  216. package/front_end/panels/profiler/HeapSnapshotView.ts +12 -2
  217. package/front_end/panels/profiler/HeapTimelineOverview.ts +16 -2
  218. package/front_end/panels/profiler/profiler.ts +0 -2
  219. package/front_end/panels/protocol_monitor/JSONEditor.ts +1 -1
  220. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +1 -1
  221. package/front_end/panels/recorder/CreateRecordingView.ts +1 -1
  222. package/front_end/panels/recorder/RecordingView.ts +3 -3
  223. package/front_end/panels/recorder/ReplaySection.ts +1 -1
  224. package/front_end/panels/screencast/ScreencastApp.ts +83 -57
  225. package/front_end/panels/screencast/ScreencastView.ts +76 -45
  226. package/front_end/panels/screencast/screencastView.css +1 -1
  227. package/front_end/panels/settings/AISettingsTab.ts +107 -4
  228. package/front_end/panels/settings/aiSettingsTab.css +53 -0
  229. package/front_end/panels/settings/settings-meta.ts +1 -1
  230. package/front_end/panels/settings/settingsScreen.css +0 -4
  231. package/front_end/panels/sources/BreakpointEditDialog.ts +3 -6
  232. package/front_end/panels/sources/BreakpointsView.ts +2 -2
  233. package/front_end/panels/sources/DebuggerPlugin.ts +7 -0
  234. package/front_end/panels/sources/NavigatorView.ts +61 -18
  235. package/front_end/panels/sources/SourcesNavigator.ts +22 -7
  236. package/front_end/panels/sources/SourcesPanel.ts +1 -0
  237. package/front_end/panels/timeline/CountersGraph.ts +1 -1
  238. package/front_end/panels/timeline/README.md +12 -0
  239. package/front_end/panels/timeline/StatusDialog.ts +1 -1
  240. package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -3
  241. package/front_end/panels/timeline/TimelineCommentController.ts +346 -0
  242. package/front_end/panels/timeline/TimelineDetailsView.ts +24 -1
  243. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +34 -30
  244. package/front_end/panels/timeline/TimelineFlameChartView.ts +24 -10
  245. package/front_end/panels/timeline/TimelinePanel.ts +12 -5
  246. package/front_end/panels/timeline/TimelineTreeView.ts +28 -6
  247. package/front_end/panels/timeline/components/LiveMetricsView.ts +1 -1
  248. package/front_end/panels/timeline/components/fieldSettingsDialog.css +2 -2
  249. package/front_end/panels/timeline/components/insights/baseInsightComponent.css +1 -1
  250. package/front_end/panels/timeline/overlays/components/entriesLinkOverlay.css +2 -2
  251. package/front_end/panels/timeline/overlays/components/entryLabelOverlay.css +9 -9
  252. package/front_end/panels/timeline/timeline-meta.ts +2 -2
  253. package/front_end/panels/timeline/timeline.ts +4 -0
  254. package/front_end/panels/timeline/timelineFlamechartPopover.css +2 -2
  255. package/front_end/panels/timeline/timelinePanel.css +2 -2
  256. package/front_end/panels/timeline/utils/EntryNodes.ts +1 -1
  257. package/front_end/panels/web_audio/WebAudioView.ts +7 -4
  258. package/front_end/third_party/chromium/README.chromium +1 -1
  259. package/front_end/third_party/codemirror.next/chunk/angular.js +1 -1
  260. package/front_end/third_party/codemirror.next/chunk/angular.js.map +1 -1
  261. package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
  262. package/front_end/third_party/codemirror.next/chunk/codemirror.js.map +1 -1
  263. package/front_end/third_party/codemirror.next/chunk/cpp.js +1 -1
  264. package/front_end/third_party/codemirror.next/chunk/cpp.js.map +1 -1
  265. package/front_end/third_party/codemirror.next/chunk/java.js +1 -1
  266. package/front_end/third_party/codemirror.next/chunk/java.js.map +1 -1
  267. package/front_end/third_party/codemirror.next/chunk/less.js +1 -1
  268. package/front_end/third_party/codemirror.next/chunk/less.js.map +1 -1
  269. package/front_end/third_party/codemirror.next/chunk/markdown.js +1 -1
  270. package/front_end/third_party/codemirror.next/chunk/markdown.js.map +1 -1
  271. package/front_end/third_party/codemirror.next/chunk/php.js +1 -1
  272. package/front_end/third_party/codemirror.next/chunk/php.js.map +1 -1
  273. package/front_end/third_party/codemirror.next/chunk/python.js +1 -1
  274. package/front_end/third_party/codemirror.next/chunk/python.js.map +1 -1
  275. package/front_end/third_party/codemirror.next/chunk/sass.js +1 -1
  276. package/front_end/third_party/codemirror.next/chunk/sass.js.map +1 -1
  277. package/front_end/third_party/codemirror.next/chunk/svelte.js +1 -1
  278. package/front_end/third_party/codemirror.next/chunk/svelte.js.map +1 -1
  279. package/front_end/third_party/codemirror.next/chunk/vue.js +1 -1
  280. package/front_end/third_party/codemirror.next/chunk/vue.js.map +1 -1
  281. package/front_end/third_party/codemirror.next/chunk/wast.js +1 -1
  282. package/front_end/third_party/codemirror.next/chunk/wast.js.map +1 -1
  283. package/front_end/third_party/codemirror.next/chunk/xml.js +1 -1
  284. package/front_end/third_party/codemirror.next/chunk/xml.js.map +1 -1
  285. package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
  286. package/front_end/third_party/codemirror.next/rollup.config.mjs +1 -1
  287. package/front_end/third_party/puppeteer/README.chromium +2 -2
  288. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +42 -12
  289. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +154 -26
  290. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.d.ts +47 -7
  291. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.d.ts.map +1 -1
  292. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js +56 -4
  293. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js.map +1 -1
  294. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts +6 -4
  295. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts.map +1 -1
  296. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js +5 -2
  297. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js.map +1 -1
  298. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.d.ts +3 -3
  299. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
  300. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.js.map +1 -1
  301. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts +2 -1
  302. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts.map +1 -1
  303. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js +23 -11
  304. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js.map +1 -1
  305. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.d.ts +3 -3
  306. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
  307. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js +1 -2
  308. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js.map +1 -1
  309. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts +13 -7
  310. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  311. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js +26 -11
  312. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js.map +1 -1
  313. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts +2 -1
  314. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts.map +1 -1
  315. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.js.map +1 -1
  316. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.d.ts.map +1 -1
  317. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js +69 -13
  318. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js.map +1 -1
  319. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts +10 -0
  320. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts.map +1 -1
  321. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
  322. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
  323. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js.map +1 -1
  324. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
  325. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
  326. package/front_end/third_party/puppeteer/package/lib/types.d.ts +42 -12
  327. package/front_end/third_party/puppeteer/package/package.json +4 -4
  328. package/front_end/third_party/puppeteer/package/src/api/HTTPRequest.ts +103 -11
  329. package/front_end/third_party/puppeteer/package/src/api/Page.ts +11 -6
  330. package/front_end/third_party/puppeteer/package/src/bidi/HTTPRequest.ts +4 -4
  331. package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +26 -14
  332. package/front_end/third_party/puppeteer/package/src/cdp/HTTPRequest.ts +7 -7
  333. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +40 -18
  334. package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +2 -3
  335. package/front_end/third_party/puppeteer/package/src/cdp/TargetManager.ts +87 -14
  336. package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +10 -0
  337. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  338. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  339. package/front_end/tsconfig.json +1 -1
  340. package/front_end/ui/comments/CommentAnchorResolver.ts +1 -1
  341. package/front_end/ui/components/buttons/Button.ts +29 -18
  342. package/front_end/ui/components/code_highlighter/CodeHighlighter.ts +1 -1
  343. package/front_end/ui/components/dialogs/TypeToAllowDialog.ts +94 -39
  344. package/front_end/ui/components/dialogs/dialog.css +1 -1
  345. package/front_end/ui/components/menus/menuItem.css +11 -0
  346. package/front_end/ui/components/text_editor/AccessiblePlaceholder.ts +1 -1
  347. package/front_end/ui/components/text_editor/AiCodeCompletionTeaser.ts +1 -1
  348. package/front_end/ui/components/text_editor/config.ts +2 -1
  349. package/front_end/ui/components/text_editor/javascript.ts +2 -1
  350. package/front_end/ui/legacy/InspectorView.ts +4 -2
  351. package/front_end/ui/legacy/SplitWidget.ts +23 -24
  352. package/front_end/ui/legacy/TabbedPane.ts +9 -1
  353. package/front_end/ui/legacy/UIUtils.ts +60 -40
  354. package/front_end/ui/legacy/components/color_picker/spectrum.css +2 -2
  355. package/front_end/ui/legacy/components/data_grid/dataGrid.css +9 -0
  356. package/front_end/ui/legacy/components/inline_editor/CSSAngle.ts +0 -1
  357. package/front_end/ui/legacy/components/inline_editor/cssShadowEditor.css +5 -7
  358. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +1 -1
  359. package/front_end/ui/legacy/components/perf_ui/PieChart.ts +11 -0
  360. package/front_end/ui/legacy/components/perf_ui/chartViewport.css +4 -4
  361. package/front_end/ui/legacy/components/quick_open/filteredListWidget.css +6 -0
  362. package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +1 -1
  363. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +38 -13
  364. package/front_end/ui/legacy/dropTarget.css +1 -1
  365. package/front_end/ui/legacy/statusBar.css +7 -0
  366. package/front_end/ui/legacy/tabbedPane.css +0 -7
  367. package/front_end/ui/visual_logging/KnownContextValues.ts +55 -0
  368. package/inspector_overlay/main.ts +2 -15
  369. package/inspector_overlay/tool_persistent.ts +0 -14
  370. package/mcp/mcp.ts +3 -0
  371. package/package.json +1 -1
  372. package/.agents/skills/devtools-ux-writing-refactor/SKILL.md +0 -142
  373. package/front_end/panels/ai_assistance/components/StylingAgentMarkdownRenderer.ts +0 -178
  374. package/front_end/panels/profiler/HeapDetachedElementsDataGrid.ts +0 -147
  375. package/front_end/panels/profiler/heapDetachedElementsDataGrid.css +0 -14
  376. package/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts +0 -62
  377. package/front_end/ui/components/legacy_wrapper/legacy_wrapper.ts +0 -8
  378. package/inspector_overlay/tool_green_dev_anchors.css +0 -54
  379. package/inspector_overlay/tool_green_dev_anchors.ts +0 -164
  380. /package/front_end/models/{ai_assistance → ai-utils}/AiSetting.ts +0 -0
  381. /package/front_end/models/{ai_assistance → ai-utils}/debug.ts +0 -0
@@ -8,18 +8,22 @@ import * as Root from '../../../core/root/root.js';
8
8
  import * as SDK from '../../../core/sdk/sdk.js';
9
9
  import type * as TextUtils from '../../../core/text_utils/text_utils.js';
10
10
  import type * as Protocol from '../../../generated/protocol.js';
11
+ import * as AiUtils from '../../ai-utils/ai-utils.js';
11
12
  import type * as LHModel from '../../lighthouse/lighthouse.js';
12
13
  import type * as Trace from '../../trace/trace.js';
13
14
  import type * as Workspace from '../../workspace/workspace.js';
14
- import {debugLog, isStructuredLogEnabled} from '../debug.js';
15
+ import type {AlwaysAllowedTools} from '../AlwaysAllowedTools.js';
15
16
  import {dispatchAiAssistanceDoneEvent} from '../DOMHelpers.js';
16
17
  import {
17
18
  type ContextHandlerResult,
18
19
  type DataHandlerResult,
19
20
  PermissionDecision,
20
- type PermissionPrompt,
21
+ PermissionPrompt,
22
+ type ToolName,
21
23
  } from '../tools/Tool.js';
22
24
 
25
+ const {debugLog, isStructuredLogEnabled} = AiUtils.Debug;
26
+
23
27
  type UrlString = Platform.DevToolsPath.UrlString;
24
28
  const MAX_SUGGESTION_LENGTH = 200;
25
29
 
@@ -37,12 +41,22 @@ const MAX_SUGGESTION_LENGTH = 200;
37
41
  * QUERYING
38
42
  * one of:
39
43
  * ANSWER (complete: false)*, ANSWER (complete: true) text-only reply; the run ends
40
- * [ANSWER (complete: true)], <tool call events> function call, optionally with text
44
+ * ANSWER (complete: false)*, [ANSWER (complete: true)],
45
+ * <tool call events>+ one or more function calls, optionally with text
41
46
  * ERROR the run ends
42
47
  * ```
43
48
  *
49
+ * When a model response contains several function calls,
50
+ * `AiAgent#runFunctionCalls()` runs them one after another, so each call's
51
+ * events finish before the next call's events start. A denied call does not
52
+ * stop the calls after it, and neither does a failed call: an unknown tool
53
+ * name or an error thrown by the handler becomes an error result for that
54
+ * call.
55
+ *
44
56
  * An `ERROR` can also follow the tool call events, for example when the user
45
57
  * aborts, the page navigates cross-origin, or the run reaches `MAX_STEPS`.
58
+ * The remaining calls in that model response do not run after an abort or a
59
+ * cross-origin navigation.
46
60
  *
47
61
  * ## Events for one tool call
48
62
  *
@@ -60,8 +74,18 @@ const MAX_SUGGESTION_LENGTH = 200;
60
74
  * ```
61
75
  *
62
76
  * If the tool switches context instead of returning a result, there is no
63
- * result `ACTION`. `AiAgent#run()` yields `CONTEXT_CHANGE` and returns, and
64
- * `AiConversation` starts a new run with the agent for the new context.
77
+ * result `ACTION`. `AiAgent#runFunctionCalls()` yields `CONTEXT_CHANGE` and
78
+ * the run ends, and `AiConversation` starts a new run with the agent for the
79
+ * new context. The remaining calls in that model response do not run.
80
+ *
81
+ * ## Model history for function calls
82
+ *
83
+ * This is the history sent to the model, separate from the saved history
84
+ * below. `AiAgent#runFunctionCalls()` stores the model's explanation text and
85
+ * every function call in a response as one `MODEL` turn. The next request
86
+ * carries one `functionResponse` per call, in the same order. A denied call
87
+ * gets a response that says it did not run. After a context change, each call
88
+ * that did not run gets a "Not executed" response.
65
89
  *
66
90
  * ## Saved history
67
91
  *
@@ -229,6 +253,11 @@ export interface ContextChangeResponse {
229
253
  description: string;
230
254
  context: ConversationContext<unknown>;
231
255
  widgets?: AiWidget[];
256
+ /**
257
+ * The name of the tool that triggered this context change. Used by the panel
258
+ * to emit UI telemetry.
259
+ */
260
+ toolName?: string;
232
261
  }
233
262
 
234
263
  interface SerializedSideEffectResponse extends Omit<SideEffectResponse, 'confirm'> {}
@@ -265,6 +294,11 @@ export interface ActionResponse extends ToolCallEvent {
265
294
  * output of tools annotated with `REDACT_FROM_HISTORY`.
266
295
  */
267
296
  toolName?: string;
297
+ /**
298
+ * Skills newly loaded by a `learnSkills` call. Used by the panel to emit
299
+ * `ai-v2-learn-skill` visual logging events.
300
+ */
301
+ loadedSkills?: string[];
268
302
  }
269
303
 
270
304
  /**
@@ -317,8 +351,9 @@ export interface AgentOptions {
317
351
  onInspectElement?: () => Promise<SDK.DOMModel.DOMNode|null>;
318
352
  history?: Host.AidaClient.Content[];
319
353
  allowedOrigin?: () => AllowedOriginResult;
320
- lighthouseRecording?: (overrides?: LHModel.RunTypes.RunOverrides) => Promise<LHModel.ReporterTypes.ReportJSON|null>;
354
+ lighthouseRecording?: (overrides?: LHModel.RunTypes.RunOverrides) => Promise<LHModel.RunTypes.RunResult>;
321
355
  targetManager?: SDK.TargetManager.TargetManager;
356
+ alwaysAllowedTools?: AlwaysAllowedTools;
322
357
  }
323
358
 
324
359
  export interface ParsedAnswer {
@@ -330,6 +365,22 @@ export type ParsedResponse = ParsedAnswer;
330
365
 
331
366
  export const MAX_STEPS = 20;
332
367
 
368
+ /**
369
+ * The response sent for each function call that did not run because an
370
+ * earlier call in the same model response switched the context. Every
371
+ * `functionCall` in the history needs a matching `functionResponse`.
372
+ */
373
+ const NOT_EXECUTED_AFTER_CONTEXT_CHANGE =
374
+ 'Not executed: the conversation switched to a new context before this call ran.';
375
+
376
+ /**
377
+ * The response sent to the model for a call that the user denied. The other
378
+ * calls in the same model response still run after a denial, so the message
379
+ * points the model to their responses to see what did run.
380
+ */
381
+ const USER_DENIED_CALL =
382
+ 'Error: The user denied this call, so it did not run. Other calls in the same response were handled separately; check their responses.';
383
+
333
384
  export interface ConversationSuggestion {
334
385
  title: string;
335
386
  jslogContext?: string;
@@ -647,9 +698,34 @@ export interface FunctionDeclaration<Args extends Record<string, unknown>, Retur
647
698
  handler(args: Args, options?: FunctionHandlerOptions): Promise<ToolResult<ReturnType>>;
648
699
  }
649
700
 
701
+ /**
702
+ * The function calls in one model response. A response that has function
703
+ * calls has at least one.
704
+ */
705
+ type FunctionCalls = [Host.AidaClient.AidaFunctionCall, ...Host.AidaClient.AidaFunctionCall[]];
706
+
707
+ /**
708
+ * What happened after `AiAgent#runFunctionCalls()` ran the calls in one model
709
+ * response:
710
+ * - `responses`: every call ran. `functionResponses` go to the model in the
711
+ * next request.
712
+ * - `contextChanged`: a call switched the context. The run ends, and
713
+ * `AiConversation` starts a new run in the new context.
714
+ * - `stopped`: an abort, a cross-origin navigation or an unexpected error
715
+ * stopped the run. The ERROR response has already been yielded.
716
+ */
717
+ type FunctionCallsOutcome = {
718
+ type: 'responses',
719
+ functionResponses: Host.AidaClient.Part[],
720
+ }|{
721
+ type: 'contextChanged',
722
+ }|{
723
+ type: 'stopped',
724
+ };
725
+
650
726
  interface AidaFetchResult {
651
727
  text?: string;
652
- functionCall?: Host.AidaClient.AidaFunctionCall;
728
+ functionCalls?: FunctionCalls;
653
729
  completed: boolean;
654
730
  rpcId?: Host.AidaClient.RpcGlobalId;
655
731
  }
@@ -692,6 +768,7 @@ export abstract class AiAgent<T> {
692
768
  readonly #functionDeclarations = new Map<string, FunctionDeclaration<Record<string, unknown>, unknown>>();
693
769
  readonly #allowedOrigin?: () => AllowedOriginResult;
694
770
  readonly #targetManager: SDK.TargetManager.TargetManager;
771
+ readonly #alwaysAllowedTools?: AlwaysAllowedTools;
695
772
 
696
773
  /**
697
774
  * Used in the debug mode and evals.
@@ -728,6 +805,7 @@ export abstract class AiAgent<T> {
728
805
  this.#allowedOrigin = opts.allowedOrigin;
729
806
  // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
730
807
  this.#targetManager = opts.targetManager ?? SDK.TargetManager.TargetManager.instance();
808
+ this.#alwaysAllowedTools = opts.alwaysAllowedTools;
731
809
  }
732
810
 
733
811
  async enhanceQuery(query: string, selected: ConversationContext<T>|null,
@@ -785,10 +863,6 @@ export abstract class AiAgent<T> {
785
863
  this.#serverSideLoggingActive = false;
786
864
  }
787
865
 
788
- popPendingMultimodalInput(): MultimodalInput|undefined {
789
- return undefined;
790
- }
791
-
792
866
  /**
793
867
  * Preamble features appended to the `client_version` in metadata.
794
868
  * This is required ONLY for the Styling Agent for legacy reasons to serve
@@ -990,8 +1064,8 @@ export abstract class AiAgent<T> {
990
1064
  }
991
1065
  Host.userMetrics.freestylerQueryLength(enhancedQuery.length);
992
1066
 
993
- let query: Host.AidaClient.Part|Host.AidaClient.Part[];
994
- query = multimodalInput ? [{text: enhancedQuery}, multimodalInput.input] : [{text: enhancedQuery}];
1067
+ const query: Host.AidaClient.Part[] =
1068
+ multimodalInput ? [{text: enhancedQuery}, multimodalInput.input] : [{text: enhancedQuery}];
995
1069
  // Request is built here to capture history up to this point.
996
1070
  let request = this.buildRequest(query, Host.AidaClient.Role.USER);
997
1071
 
@@ -1007,23 +1081,20 @@ export abstract class AiAgent<T> {
1007
1081
 
1008
1082
  if (i === 0) {
1009
1083
  debugLog('[AiAgent] Step 1: Sending user prompt to model:', enhancedQuery);
1010
- } else if (!Array.isArray(query) && 'functionResponse' in query) {
1011
- debugLog(`[AiAgent] Step ${i + 1}: Sending function response for '${query.functionResponse.name}' to model:`,
1012
- query.functionResponse.response);
1013
1084
  } else {
1014
1085
  debugLog(`[AiAgent] Step ${i + 1}: Sending request to model:`, request.current_message);
1015
1086
  }
1016
1087
 
1017
1088
  let rpcId: Host.AidaClient.RpcGlobalId|undefined;
1018
1089
  let textResponse = '';
1019
- let functionCall: Host.AidaClient.AidaFunctionCall|undefined = undefined;
1090
+ let functionCalls: FunctionCalls|undefined;
1020
1091
  try {
1021
1092
  for await (const fetchResult of this.#aidaFetch(request, {signal: options.signal})) {
1022
1093
  rpcId = fetchResult.rpcId;
1023
1094
  textResponse = fetchResult.text ?? '';
1024
- functionCall = fetchResult.functionCall;
1095
+ functionCalls = fetchResult.functionCalls;
1025
1096
 
1026
- if (!functionCall && !fetchResult.completed) {
1097
+ if (!functionCalls && !fetchResult.completed) {
1027
1098
  const parsed = this.parsePartialTextResponse(textResponse);
1028
1099
  const partialAnswer = 'answer' in parsed ? parsed.answer : '';
1029
1100
  if (!partialAnswer) {
@@ -1052,7 +1123,7 @@ export abstract class AiAgent<T> {
1052
1123
  if (!('answer' in parsedResponse)) {
1053
1124
  throw new Error('Expected a completed response to have an answer');
1054
1125
  }
1055
- if (!functionCall) {
1126
+ if (!functionCalls) {
1056
1127
  debugLog(`[AiAgent] Step ${i + 1}: Model returned text response:`, parsedResponse.answer);
1057
1128
  this.#history.push({
1058
1129
  parts: [{
@@ -1069,135 +1140,184 @@ export abstract class AiAgent<T> {
1069
1140
  complete: true,
1070
1141
  rpcId,
1071
1142
  });
1072
- if (!functionCall) {
1143
+ if (!functionCalls) {
1073
1144
  break;
1074
1145
  }
1075
1146
  }
1076
1147
 
1077
- if (functionCall) {
1078
- debugLog(`[AiAgent] Step ${i + 1}: Model requested function call: ${functionCall.name}`, functionCall.args);
1148
+ if (!functionCalls) {
1149
+ yield this.#createErrorResponse(ErrorType.UNKNOWN);
1150
+ break;
1151
+ }
1152
+
1153
+ debugLog(`[AiAgent] Step ${i + 1}: Model requested function calls:`, functionCalls);
1154
+ const outcome = yield* this.#runFunctionCalls(functionCalls, textResponse, options);
1155
+ if (outcome.type === 'contextChanged') {
1156
+ return;
1157
+ }
1158
+ if (outcome.type === 'stopped') {
1159
+ break;
1160
+ }
1161
+
1162
+ if (i === MAX_STEPS - 1) {
1163
+ // Normally, the functionResponses are pushed at the start of the next
1164
+ // iteration. Since no further iteration will run, push them here so the
1165
+ // last functionCalls are not left unpaired in history.
1166
+ this.#history.push({
1167
+ parts: outcome.functionResponses,
1168
+ role: Host.AidaClient.Role.ROLE_UNSPECIFIED,
1169
+ });
1170
+ yield this.#createErrorResponse(ErrorType.MAX_STEPS);
1171
+ break;
1172
+ }
1173
+
1174
+ request = this.buildRequest(outcome.functionResponses, Host.AidaClient.Role.ROLE_UNSPECIFIED);
1175
+ }
1176
+
1177
+ if (isStructuredLogEnabled()) {
1178
+ dispatchAiAssistanceDoneEvent();
1179
+ }
1180
+ return;
1181
+ }
1182
+
1183
+ /**
1184
+ * Runs every function call in one model response, one after another, in the
1185
+ * order the model returned them.
1186
+ *
1187
+ * The model's text and all calls are stored in history as one MODEL turn.
1188
+ * Every `functionCall` in history gets a matching `functionResponse`: in the
1189
+ * returned `functionResponses`, or, after a context change, in history
1190
+ * directly. When the run stops, the ERROR response removes the run from
1191
+ * history instead.
1192
+ */
1193
+ async *
1194
+ #runFunctionCalls(functionCalls: FunctionCalls, textResponse: string, options: {signal?: AbortSignal}):
1195
+ AsyncGenerator<ResponseData, FunctionCallsOutcome, void> {
1196
+ // Each call keeps its own `thoughtSignature`, if it has one.
1197
+ const modelParts: Host.AidaClient.Part[] = textResponse ? [{text: textResponse}] : [];
1198
+ modelParts.push(...functionCalls.map(functionCall => ({functionCall})));
1199
+ this.#history.push({
1200
+ parts: modelParts,
1201
+ role: Host.AidaClient.Role.MODEL,
1202
+ });
1203
+
1204
+ const functionResponses: Host.AidaClient.Part[] = [];
1205
+ try {
1206
+ for (const [index, functionCall] of functionCalls.entries()) {
1079
1207
  const allowedOriginResult = this.#allowedOrigin?.();
1080
1208
  if (allowedOriginResult && 'blocked' in allowedOriginResult) {
1081
- // Abort immediately if the page navigated before we could lock the origin.
1209
+ // Stop if the page navigated before the origin was locked.
1082
1210
  // This prevents the AI from accessing data from the new page.
1083
- yield this.#createErrorResponse(ErrorType.CROSS_ORIGIN);
1084
- break;
1211
+ throw new CrossOriginError();
1085
1212
  }
1086
- try {
1087
- const result = yield*
1088
- this.#callFunction(
1089
- functionCall.name,
1090
- functionCall.args,
1091
- functionCall.thoughtSignature,
1092
- {
1093
- ...options,
1094
- explanation: textResponse,
1095
- },
1096
- );
1097
-
1098
- if (options.signal?.aborted) {
1099
- yield this.#createErrorResponse(ErrorType.ABORT);
1100
- break;
1101
- }
1102
1213
 
1103
- if ('context' in result) {
1104
- // Pair the functionCall with a functionResponse so history stays valid
1105
- // if this agent instance is re-run after the context change (AiAgent2).
1106
- // The new context reaches the model through the next USER query.
1107
- this.#history.push({
1108
- parts: [{
1109
- functionResponse: {
1110
- name: functionCall.name,
1111
- response: {result: result.description},
1112
- },
1113
- }],
1114
- role: Host.AidaClient.Role.ROLE_UNSPECIFIED,
1115
- });
1116
- yield {
1117
- type: ResponseType.CONTEXT_CHANGE,
1118
- description: result.description,
1119
- context: result.context,
1120
- widgets: result.widgets,
1121
- };
1214
+ const result = yield* this.#callFunction(functionCall.name, functionCall.args, options);
1122
1215
 
1123
- return;
1124
- }
1216
+ if (options.signal?.aborted) {
1217
+ // The remaining calls do not run. The ABORT response removes the run
1218
+ // from history.
1219
+ yield this.#createErrorResponse(ErrorType.ABORT);
1220
+ return {type: 'stopped'};
1221
+ }
1125
1222
 
1126
- query = {
1127
- functionResponse: {
1128
- name: functionCall.name,
1129
- // Widgets are not sent back to the LLM
1130
- response: {...result, widgets: undefined},
1131
- },
1223
+ if ('context' in result) {
1224
+ functionResponses.push(
1225
+ ...this.#contextChangeResponses(functionCall, functionCalls.slice(index + 1), result.description));
1226
+ this.#history.push({
1227
+ parts: functionResponses,
1228
+ role: Host.AidaClient.Role.ROLE_UNSPECIFIED,
1229
+ });
1230
+ yield {
1231
+ type: ResponseType.CONTEXT_CHANGE,
1232
+ description: result.description,
1233
+ context: result.context,
1234
+ widgets: result.widgets,
1235
+ toolName: functionCall.name,
1132
1236
  };
1133
- if (i === MAX_STEPS - 1) {
1134
- // Normally, the functionResponse is pushed at the start of the next
1135
- // iteration. Since no further iteration will run, push it here so the
1136
- // last functionCall is not left unpaired in history.
1137
- this.#history.push({
1138
- parts: [query],
1139
- role: Host.AidaClient.Role.ROLE_UNSPECIFIED,
1140
- });
1141
- yield this.#createErrorResponse(ErrorType.MAX_STEPS);
1142
- break;
1143
- }
1144
- request = this.buildRequest(query, Host.AidaClient.Role.ROLE_UNSPECIFIED);
1145
- } catch (err) {
1146
- if (err instanceof CrossOriginError) {
1147
- yield this.#createErrorResponse(ErrorType.CROSS_ORIGIN);
1148
- break;
1149
- }
1150
- debugLog('Error handling function call', err);
1151
- yield this.#createErrorResponse(ErrorType.UNKNOWN);
1152
- break;
1237
+ return {type: 'contextChanged'};
1153
1238
  }
1154
- } else {
1155
- yield this.#createErrorResponse(ErrorType.UNKNOWN);
1156
- break;
1239
+
1240
+ functionResponses.push({
1241
+ functionResponse: {
1242
+ name: functionCall.name,
1243
+ // Widgets and UI telemetry metadata are not sent back to the LLM.
1244
+ response: {
1245
+ ...result,
1246
+ widgets: undefined,
1247
+ ...('loadedSkills' in result ? {loadedSkills: undefined} : {}),
1248
+ },
1249
+ },
1250
+ });
1251
+ }
1252
+ } catch (err) {
1253
+ if (err instanceof CrossOriginError) {
1254
+ yield this.#createErrorResponse(ErrorType.CROSS_ORIGIN);
1255
+ return {type: 'stopped'};
1157
1256
  }
1257
+ debugLog('Error handling function call', err);
1258
+ yield this.#createErrorResponse(ErrorType.UNKNOWN);
1259
+ return {type: 'stopped'};
1158
1260
  }
1159
1261
 
1160
- if (isStructuredLogEnabled()) {
1161
- dispatchAiAssistanceDoneEvent();
1162
- }
1163
- return;
1262
+ return {type: 'responses', functionResponses};
1263
+ }
1264
+
1265
+ /**
1266
+ * Returns the function responses for `switchingCall`, which switched the
1267
+ * context, and for `skippedCalls`, which come after it and do not run.
1268
+ *
1269
+ * Pairing every `functionCall` with a `functionResponse` keeps the history
1270
+ * valid if this agent instance runs again after the context change
1271
+ * (`AiAgent2`). The new context reaches the model through the next USER
1272
+ * query.
1273
+ */
1274
+ #contextChangeResponses(switchingCall: Host.AidaClient.AidaFunctionCall,
1275
+ skippedCalls: Host.AidaClient.AidaFunctionCall[],
1276
+ description: string): Host.AidaClient.Part[] {
1277
+ return [
1278
+ {
1279
+ functionResponse: {
1280
+ name: switchingCall.name,
1281
+ response: {result: description},
1282
+ },
1283
+ },
1284
+ ...skippedCalls.map(skippedCall => ({
1285
+ functionResponse: {
1286
+ name: skippedCall.name,
1287
+ response: {result: NOT_EXECUTED_AFTER_CONTEXT_CHANGE},
1288
+ },
1289
+ })),
1290
+ ];
1164
1291
  }
1165
1292
 
1166
1293
  async *
1167
1294
  #callFunction(
1168
1295
  name: string,
1169
1296
  args: Record<string, unknown>,
1170
- thoughtSignature?: string,
1171
- options?: FunctionHandlerOptions&{explanation?: string},
1297
+ options?: FunctionHandlerOptions,
1172
1298
  ): AsyncGenerator<FunctionCallResponseData, {
1173
1299
  result: unknown,
1174
1300
  widgets?: AiWidget[],
1175
- }|{context: ConversationContext<unknown>, description: string, widgets?: AiWidget[]}> {
1301
+ loadedSkills?: string[],
1302
+ }|{error: string}|{context: ConversationContext<unknown>, description: string, widgets?: AiWidget[]}> {
1303
+ const callId = crypto.randomUUID();
1176
1304
  const call = this.#functionDeclarations.get(name);
1177
1305
  if (!call) {
1178
- throw new Error(`Function ${name} is not found.`);
1306
+ // Answer with an error instead of throwing, so the other calls in the
1307
+ // same model response still run and the history keeps their results.
1308
+ const error = `Error: Function ${name} is not found.`;
1309
+ debugLog(`[AiAgent] Tool '${name}' is not declared.`);
1310
+ yield {
1311
+ type: ResponseType.ACTION,
1312
+ callId,
1313
+ output: error,
1314
+ canceled: false,
1315
+ toolName: name,
1316
+ };
1317
+ return {error};
1179
1318
  }
1180
1319
  debugLog(`[AiAgent] Executing tool '${name}' with args:`, args);
1181
- const parts: Host.AidaClient.Part[] = [];
1182
- if (options?.explanation) {
1183
- parts.push({
1184
- text: options.explanation,
1185
- });
1186
- }
1187
- const functionCall: Host.AidaClient.AidaFunctionCall = {
1188
- name,
1189
- args,
1190
- };
1191
- if (thoughtSignature) {
1192
- functionCall.thoughtSignature = thoughtSignature;
1193
- }
1194
- parts.push({functionCall});
1195
- this.#history.push({
1196
- parts,
1197
- role: Host.AidaClient.Role.MODEL,
1198
- });
1199
1320
 
1200
- const callId = crypto.randomUUID();
1201
1321
  let code;
1202
1322
  if (call.displayInfoFromArgs) {
1203
1323
  const {title, thought, action: callCode} = call.displayInfoFromArgs(args);
@@ -1224,7 +1344,21 @@ export abstract class AiAgent<T> {
1224
1344
  return Boolean(allowedOriginResult && 'blocked' in allowedOriginResult);
1225
1345
  };
1226
1346
 
1227
- let result = await call.handler(args, options);
1347
+ // Turns an error thrown by the handler into an error result, so the other
1348
+ // calls in the same model response still run and the history keeps their
1349
+ // results.
1350
+ const runHandler = async(handlerOptions?: FunctionHandlerOptions): Promise<ToolResult<unknown>> => {
1351
+ try {
1352
+ const isAlwaysAllowed = call.permissionPrompt === PermissionPrompt.ALLOW_ONCE_OR_ALWAYS &&
1353
+ this.#alwaysAllowedTools?.isAllowed(name as ToolName);
1354
+ return await call.handler(args, isAlwaysAllowed ? {...handlerOptions, approved: true} : handlerOptions);
1355
+ } catch (err) {
1356
+ debugLog(`[AiAgent] Tool '${name}' threw:`, err);
1357
+ return {error: `Error: ${err instanceof Error ? err.message : String(err)}`};
1358
+ }
1359
+ };
1360
+
1361
+ let result = await runHandler(options);
1228
1362
 
1229
1363
  // Check 1: After first handler execution.
1230
1364
  // Navigation could have occurred during the async handler execution.
@@ -1276,6 +1410,9 @@ export abstract class AiAgent<T> {
1276
1410
  } finally {
1277
1411
  options?.signal?.removeEventListener('abort', onAbort);
1278
1412
  }
1413
+ if (decision === PermissionDecision.ALLOW_ALWAYS) {
1414
+ this.#alwaysAllowedTools?.allow(name as ToolName);
1415
+ }
1279
1416
  if (decision === PermissionDecision.REJECT) {
1280
1417
  yield {
1281
1418
  type: ResponseType.ACTION,
@@ -1286,7 +1423,7 @@ export abstract class AiAgent<T> {
1286
1423
  };
1287
1424
  debugLog(`[AiAgent] Tool '${name}' denied by user.`);
1288
1425
  return {
1289
- result: 'Error: User denied code execution with side effects.',
1426
+ result: USER_DENIED_CALL,
1290
1427
  };
1291
1428
  }
1292
1429
 
@@ -1298,7 +1435,7 @@ export abstract class AiAgent<T> {
1298
1435
  throw new CrossOriginError();
1299
1436
  }
1300
1437
 
1301
- result = await call.handler(args, {
1438
+ result = await runHandler({
1302
1439
  ...options,
1303
1440
  approved: true,
1304
1441
  });
@@ -1319,6 +1456,7 @@ export abstract class AiAgent<T> {
1319
1456
  widgets: result.widgets,
1320
1457
  canceled: false,
1321
1458
  toolName: name,
1459
+ ...(result.loadedSkills ? {loadedSkills: result.loadedSkills} : {}),
1322
1460
  };
1323
1461
  }
1324
1462
 
@@ -1350,13 +1488,9 @@ export abstract class AiAgent<T> {
1350
1488
 
1351
1489
  for await (aidaResponse of this.#aidaClient.doConversation(request, options)) {
1352
1490
  if (aidaResponse.functionCalls?.length) {
1353
- if (aidaResponse.functionCalls.length > 1) {
1354
- debugLog(`[AiAgent] Unexpected: received ${aidaResponse.functionCalls.length} function calls in response:`,
1355
- aidaResponse.functionCalls);
1356
- }
1357
1491
  yield {
1358
1492
  rpcId,
1359
- functionCall: aidaResponse.functionCalls[0],
1493
+ functionCalls: aidaResponse.functionCalls,
1360
1494
  completed: true,
1361
1495
  text: aidaResponse.explanation,
1362
1496
  };
@@ -6,6 +6,7 @@ import * as Host from '../../../core/host/host.js';
6
6
  import * as i18n from '../../../core/i18n/i18n.js';
7
7
  import * as Root from '../../../core/root/root.js';
8
8
  import type * as SDK from '../../../core/sdk/sdk.js';
9
+ import * as AiUtils from '../../ai-utils/ai-utils.js';
9
10
  import type * as LHModel from '../../lighthouse/lighthouse.js';
10
11
  import * as Logs from '../../logs/logs.js';
11
12
  import * as NetworkTimeCalculator from '../../network_time_calculator/network_time_calculator.js';
@@ -18,7 +19,6 @@ import {PerformanceTraceContext} from '../contexts/PerformanceTraceContext.js';
18
19
  import {RequestContext} from '../contexts/RequestContext.js';
19
20
  import {StorageContext} from '../contexts/StorageContext.js';
20
21
  import {formatBytesToKb, seconds} from '../data_formatters/UnitFormatters.js';
21
- import {debugLog} from '../debug.js';
22
22
  import {StorageItem} from '../StorageItem.js';
23
23
  import {isOriginAllowedByLock} from '../tools/Tool.js';
24
24
 
@@ -30,6 +30,8 @@ import {
30
30
  type RequestOptions,
31
31
  } from './AiAgent.js';
32
32
 
33
+ const {debugLog} = AiUtils.Debug;
34
+
33
35
  type NetworkRequest = SDK.NetworkRequest.NetworkRequest;
34
36
 
35
37
  const lockedString = i18n.i18n.lockedString;
@@ -106,8 +108,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
106
108
  readonly #performanceRecordAndReload?: () => Promise<Trace.TraceModel.ParsedTrace>;
107
109
  readonly #onInspectElement?: () => Promise<SDK.DOMModel.DOMNode|null>;
108
110
  readonly #networkTimeCalculator?: NetworkTimeCalculator.NetworkTransferTimeCalculator;
109
- readonly #lighthouseRecording?:
110
- (overrides?: LHModel.RunTypes.RunOverrides) => Promise<LHModel.ReporterTypes.ReportJSON|null>;
111
+ readonly #lighthouseRecording?: (overrides?: LHModel.RunTypes.RunOverrides) => Promise<LHModel.RunTypes.RunResult>;
111
112
  #allowedOrigin: () => AllowedOriginResult;
112
113
  readonly #networkLog: Logs.NetworkLog.NetworkLog;
113
114
  readonly #workspace: Workspace.Workspace.WorkspaceImpl;
@@ -439,14 +440,19 @@ export class ContextSelectionAgent extends AiAgent<never> {
439
440
  const mode = parseLighthouseMode(params.mode);
440
441
  debugLog(`Recording with Lighthouse; runMode=${mode}`);
441
442
  const result = await this.#lighthouseRecording({mode});
442
- if (!result) {
443
+ if (result.status === 'cancelled') {
444
+ return {
445
+ error: 'The user cancelled the Lighthouse audit. Do not run it again unless the user asks you to.',
446
+ };
447
+ }
448
+ if (result.status === 'failed') {
443
449
  return {error: 'Failed to generate Lighthouse report.'};
444
450
  }
445
451
 
446
452
  return {
447
- context: new LighthouseContext(result),
453
+ context: new LighthouseContext(result.report),
448
454
  description: 'User has selected a Lighthouse report',
449
- widgets: [{name: 'LIGHTHOUSE_REPORT', data: {report: result}}],
455
+ widgets: [{name: 'LIGHTHOUSE_REPORT', data: {report: result.report}}],
450
456
  };
451
457
  },
452
458
  });
@@ -8,7 +8,7 @@ import * as Platform from '../../../core/platform/platform.js';
8
8
  import * as Root from '../../../core/root/root.js';
9
9
  import * as SDK from '../../../core/sdk/sdk.js';
10
10
  import type * as Protocol from '../../../generated/protocol.js';
11
- import {isNaturalLanguageInterfaceEnabled} from '../AiUtils.js';
11
+ import * as AiUtils from '../../ai-utils/ai-utils.js';
12
12
  import type {ChangeManager} from '../ChangeManager.js';
13
13
  import {EvaluateAction, formatError, SideEffectError} from '../EvaluateAction.js';
14
14
  import {FREESTYLER_WORLD_CSP, FREESTYLER_WORLD_NAME} from '../injected.js';
@@ -16,6 +16,8 @@ import type {DataHandlerResult} from '../tools/Tool.js';
16
16
 
17
17
  import type {AgentOptions as BaseAgentOptions, FunctionHandlerOptions} from './AiAgent.js';
18
18
 
19
+ const {isNaturalLanguageInterfaceEnabled} = AiUtils.AiUtils;
20
+
19
21
  const lockedString = i18n.i18n.lockedString;
20
22
 
21
23
  export type CreateExtensionScopeFunction = (changes: ChangeManager) => {
@@ -39,7 +39,7 @@ Content:
39
39
  " - LCP breakdown:",
40
40
  " - TTFB: 553 ms, bounds: {min: 465456489730µs, max: 465457042737µs}",
41
41
  " - Render delay: 123 ms, bounds: {min: 465457042737µs, max: 465457166052µs}",
42
- " - CLS: 0.02, event: (eventKey: s-14250, ts: 465457121239)",
42
+ " - CLS: 0.02, event: (eventKey: c-14250, ts: 465457121239)",
43
43
  "Metrics (field / real users): n/a – no data for this page in CrUX",
44
44
  "Available insights:",
45
45
  " - insight name: RenderBlocking",