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.
- package/.agents/rules/models-and-core/core-ai-agent-context-and-prompt-discipline.md +29 -0
- package/.agents/rules/models-and-core/core-cdp-and-extension-error-handling.md +34 -0
- package/.agents/rules/models-and-core/core-gn-build-and-module-layering.md +23 -0
- package/.agents/rules/models-and-core/core-runtime-neutrality-and-platform-utils.md +28 -0
- package/.agents/rules/models-and-core/core-sdk-model-and-target-lifecycle.md +35 -0
- package/.agents/rules/models-and-core/core-security-origin-and-capability-guards.md +33 -0
- package/.agents/rules/models-and-core/core-settings-and-storage-migration.md +31 -0
- package/.agents/rules/models-and-core/core-sourcemap-and-workspace-mapping.md +28 -0
- package/.agents/rules/models-and-core/core-trace-engine-handler-invariants.md +32 -0
- package/.agents/rules/models-and-core/core-trace-insight-models-and-timing-types.md +28 -0
- package/.agents/rules/tests/test-cleanup-mutated-globals-and-widgets.md +40 -0
- package/.agents/rules/tests/test-deterministic-async-synchronization.md +30 -0
- package/.agents/rules/tests/test-modular-hooks-and-test-universe.md +38 -0
- package/.agents/rules/tests/test-public-api-and-encapsulation.md +30 -0
- package/.agents/rules/tests/test-shared-fixture-and-helper-reuse.md +29 -0
- package/.agents/rules/tests/test-single-responsibility-and-conciseness.md +37 -0
- package/.agents/rules/tests/test-strict-assertions-and-literal-expectations.md +31 -0
- package/.agents/rules/tests/test-type-safe-mocks-and-events.md +30 -0
- package/.agents/rules/tests/test-view-and-presenter-isolation.md +32 -0
- package/.agents/rules/ui-and-widgets/ui-accessibility-and-semantic-html.md +32 -0
- package/.agents/rules/ui-and-widgets/ui-await-update-complete-post-render.md +30 -0
- package/.agents/rules/ui-and-widgets/ui-css-scoping-and-flex-layout.md +27 -0
- package/.agents/rules/ui-and-widgets/ui-declarative-child-widget-composition.md +29 -0
- package/.agents/rules/ui-and-widgets/ui-lit-declarative-templates-and-directives.md +33 -0
- package/.agents/rules/ui-and-widgets/ui-localization-and-uistrings-hygiene.md +36 -0
- package/.agents/rules/ui-and-widgets/ui-modern-component-and-encapsulation-standards.md +32 -0
- package/.agents/rules/ui-and-widgets/ui-panel-and-meta-registration.md +35 -0
- package/.agents/rules/ui-and-widgets/ui-performance-and-flamechart-rendering.md +34 -0
- package/.agents/rules/ui-and-widgets/ui-pure-view-and-presenter-separation.md +31 -0
- package/.agents/rules/ui-and-widgets/ui-reactive-widget-update-lifecycle.md +34 -0
- package/.agents/rules/ui-and-widgets/ui-security-and-output-sanitization.md +28 -0
- package/.agents/rules/ui-and-widgets/ui-type-safety-and-exhaustiveness.md +37 -0
- package/.agents/rules/ui-and-widgets/ui-view-output-and-callback-contracts.md +35 -0
- package/.agents/rules/ui-and-widgets/ui-visual-logging-instrumentation.md +29 -0
- package/.agents/rules/ui-and-widgets/ui-weak-dom-references-and-observer-cleanup.md +29 -0
- package/.agents/rules/ui-and-widgets/ui-widget-dom-and-listener-lifecycle.md +38 -0
- package/.agents/skills/code-review/SKILL.md +3 -0
- package/.agents/skills/devtools-testing-guidance/SKILL.md +5 -2
- package/.agents/skills/review-models-core/SKILL.md +73 -0
- package/.agents/skills/review-tests/SKILL.md +67 -0
- package/.agents/skills/review-ui-widgets/SKILL.md +115 -0
- package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +73 -9
- package/.agents/skills/ui-eng-vision-logic-consolidator/SKILL.md +27 -3
- package/.agents/skills/ui-eng-vision-orchestrator/SKILL.md +32 -2
- package/.agents/skills/ui-eng-vision-test-scaffolder/SKILL.md +37 -7
- package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +6 -5
- package/.agents/skills/ui-widgets/SKILL.md +11 -9
- package/AUTHORS +3 -0
- package/DIR_METADATA +51 -1
- package/docs/ui_engineering.md +34 -0
- package/eslint.config.mjs +63 -21
- package/front_end/core/common/Settings.ts +5 -0
- package/front_end/core/host/UserMetricsEnums.ts +1 -0
- package/front_end/core/platform/api/HostRuntime.ts +1 -0
- package/front_end/core/platform/browser/HostRuntime.ts +10 -0
- package/front_end/core/platform/node/HostRuntime.ts +1 -0
- package/front_end/core/sdk/CSSMatchedStyles.ts +60 -20
- package/front_end/core/sdk/CSSModel.ts +21 -0
- package/front_end/core/sdk/CSSProperty.ts +2 -2
- package/front_end/core/sdk/CSSPropertyParser.ts +11 -2
- package/front_end/core/sdk/CSSPropertyParserMatchers.ts +28 -9
- package/front_end/core/sdk/DOMModel.ts +1 -1
- package/front_end/core/sdk/DebuggerModel.ts +3 -0
- package/front_end/core/sdk/EmulationModel.ts +40 -39
- package/front_end/core/sdk/NetworkManager.ts +10 -3
- package/front_end/core/sdk/NetworkRequest.ts +21 -0
- package/front_end/core/sdk/OverlayModel.ts +2 -8
- package/front_end/core/sdk/PrivateVerificationTokensModel.ts +79 -0
- package/front_end/core/sdk/RuntimeModel.ts +8 -3
- package/front_end/core/sdk/SecurityOrigin.ts +1 -1
- package/front_end/core/sdk/SourceMapCache.ts +20 -15
- package/front_end/core/sdk/SourceMapManager.ts +28 -9
- package/front_end/core/sdk/TargetManager.ts +7 -4
- package/front_end/core/sdk/WebAuthnModel.ts +11 -2
- package/front_end/core/sdk/sdk.ts +2 -0
- package/front_end/devtools_compatibility.js +1 -0
- package/front_end/entrypoints/inspector_main/InspectorMain.ts +0 -2
- package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +10 -0
- package/front_end/entrypoints/main/GlobalAiButton.ts +1 -1
- package/front_end/entrypoints/main/MainImpl.ts +5 -2
- package/front_end/foundation/Universe.ts +1 -1
- package/front_end/generated/Deprecation.ts +4 -7
- package/front_end/generated/InspectorBackendCommands.ts +4 -4
- package/front_end/generated/SupportedCSSProperties.ts +89 -17
- package/front_end/generated/protocol-mapping.d.ts +1 -0
- package/front_end/generated/protocol-proxy-api.d.ts +1 -0
- package/front_end/generated/protocol.ts +6 -3
- package/front_end/models/{ai_assistance → ai-utils}/AiHistoryStorage.ts +6 -5
- package/front_end/models/{ai_assistance → ai-utils}/AiUtils.ts +14 -2
- package/front_end/models/{ai_assistance → ai-utils}/BuiltInAi.ts +1 -1
- package/front_end/models/ai-utils/ai-utils.ts +17 -0
- package/front_end/models/ai_assistance/AiAgent2.ts +14 -6
- package/front_end/models/ai_assistance/AiConversation.ts +37 -24
- package/front_end/models/ai_assistance/AlwaysAllowedTools.ts +107 -0
- package/front_end/models/ai_assistance/ConversationSummary.ts +2 -1
- package/front_end/models/ai_assistance/PerformanceAnnotations.ts +3 -1
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +12 -5
- package/front_end/models/ai_assistance/agents/AiAgent.ts +261 -127
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +12 -6
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +3 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +1 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +3 -1
- package/front_end/models/ai_assistance/ai_assistance.ts +9 -10
- package/front_end/models/ai_assistance/data_formatters/FileFormatter.ts +27 -6
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +2 -9
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +3 -3
- package/front_end/models/ai_assistance/skills/sources.md +3 -1
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +1 -0
- package/front_end/models/ai_assistance/tools/GetCookieValues.ts +1 -0
- package/front_end/models/ai_assistance/tools/GetInsightDetails.ts +3 -1
- package/front_end/models/ai_assistance/tools/GetSourceContent.ts +46 -4
- package/front_end/models/ai_assistance/tools/GetStorageValues.ts +1 -0
- package/front_end/models/ai_assistance/tools/RunLighthouse.ts +6 -3
- package/front_end/models/ai_assistance/tools/Tool.ts +11 -1
- package/front_end/models/bindings/CompilerScriptMapping.ts +40 -8
- package/front_end/models/bindings/ResourceScriptMapping.ts +1 -1
- package/front_end/models/breakpoints/BreakpointManager.ts +0 -4
- package/front_end/models/change_tracker/ChangeTracker.ts +2 -0
- package/front_end/models/comment_manager/CommentManager.ts +12 -0
- package/front_end/models/comment_manager/CommentThread.ts +34 -1
- package/front_end/models/computed_style/ComputedStyleModel.ts +1 -0
- package/front_end/models/elements/ChangeTrackingUtils.ts +37 -0
- package/front_end/models/elements/DOMChanges.ts +24 -36
- package/front_end/models/elements/StyleChanges.ts +97 -0
- package/front_end/models/elements/elements.ts +4 -0
- package/front_end/models/emulation/DeviceModeModel.ts +19 -0
- package/front_end/models/issues_manager/GenericIssue.ts +18 -0
- package/front_end/models/issues_manager/descriptions/genericGeolocationPromptWithoutUserGesture.md +5 -0
- package/front_end/models/javascript_metadata/NativeFunctions.ts +11 -5
- package/front_end/models/lighthouse/RunTypes.ts +16 -0
- package/front_end/models/stack_trace/StackTraceModel.ts +24 -3
- package/front_end/models/trace/EventsSerializer.ts +35 -2
- package/front_end/models/trace/extras/TraceTree.ts +2 -7
- package/front_end/models/trace/handlers/LayoutShiftsHandler.ts +17 -21
- package/front_end/models/trace/helpers/SyntheticEvents.ts +4 -2
- package/front_end/models/trace/helpers/Timing.ts +11 -22
- package/front_end/models/trace/lantern/core/NetworkAnalyzer.ts +12 -8
- package/front_end/models/trace/types/File.ts +20 -3
- package/front_end/models/trace/types/TraceEvents.ts +8 -3
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +37 -2
- package/front_end/panels/ai_assistance/README.md +4 -2
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +1 -1
- package/front_end/panels/ai_assistance/ai_assistance.ts +2 -0
- package/front_end/panels/ai_assistance/components/ChatInput.ts +5 -43
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +52 -147
- package/front_end/panels/ai_assistance/components/ChatView.ts +28 -3
- package/front_end/panels/ai_assistance/components/PermissionPrompt.ts +151 -0
- package/front_end/panels/ai_assistance/components/RelevantDataDisclaimer.ts +73 -0
- package/front_end/panels/ai_assistance/components/chatInput.css +0 -59
- package/front_end/panels/ai_assistance/components/chatMessage.css +0 -47
- package/front_end/panels/ai_assistance/components/chatView.css +5 -30
- package/front_end/panels/ai_assistance/components/permissionPrompt.css +55 -0
- package/front_end/panels/ai_assistance/components/relevantDataDisclaimer.css +35 -0
- package/front_end/panels/application/AppManifestView.ts +1 -4
- package/front_end/panels/application/ApplicationPanelSidebar.ts +3 -7
- package/front_end/panels/application/BackgroundServiceView.ts +8 -8
- package/front_end/panels/application/IndexedDBViews.ts +102 -73
- package/front_end/panels/application/OpenedWindowDetailsView.ts +167 -130
- package/front_end/panels/application/ServiceWorkerCacheViews.ts +288 -346
- package/front_end/panels/application/StorageBucketsTreeElement.ts +22 -27
- package/front_end/panels/application/StorageItemsToolbar.ts +2 -2
- package/front_end/panels/application/components/StorageMetadataView.ts +207 -160
- package/front_end/panels/application/openedWindowDetailsView.css +7 -30
- package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +1 -1
- package/front_end/panels/changes/changesView.css +0 -6
- package/front_end/panels/comments/CommentsPane.ts +7 -3
- package/front_end/panels/comments/comments-meta.ts +1 -1
- package/front_end/panels/common/CommentThreadWidget.ts +67 -25
- package/front_end/panels/common/CommentsOverlayWidget.ts +13 -0
- package/front_end/panels/console/ConsoleInsightTeaser.ts +5 -1
- package/front_end/panels/console/ConsolePinPane.ts +1 -1
- package/front_end/panels/console/ConsoleView.ts +1 -0
- package/front_end/panels/elements/CSSValueTraceView.ts +5 -5
- package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +14 -6
- package/front_end/panels/elements/ComputedStyleWidget.ts +14 -5
- package/front_end/panels/elements/DOMTreeElementWidget.ts +2 -2
- package/front_end/panels/elements/DOMTreeWidget.ts +7 -3
- package/front_end/panels/elements/EventListenersWidget.ts +1 -1
- package/front_end/panels/elements/LayersWidget.ts +1 -1
- package/front_end/panels/elements/PropertyRenderer.ts +178 -10
- package/front_end/panels/elements/StandaloneStylesContainer.ts +33 -6
- package/front_end/panels/elements/StylePropertiesSection.ts +1 -0
- package/front_end/panels/elements/StylePropertyTreeElement.ts +295 -116
- package/front_end/panels/elements/StylesContainer.ts +2 -0
- package/front_end/panels/elements/StylesSidebarPane.ts +34 -16
- package/front_end/panels/elements/components/QueryContainer.ts +1 -1
- package/front_end/panels/elements/elementStatePaneWidget.css +1 -1
- package/front_end/panels/elements/stylePropertiesTreeOutline.css +7 -2
- package/front_end/panels/elements/stylesSidebarPane.css +4 -0
- package/front_end/panels/emulation/DeviceModeToolbar.ts +57 -25
- package/front_end/panels/emulation/DeviceModeView.ts +27 -1
- package/front_end/panels/emulation/InspectedPagePlaceholder.ts +6 -0
- package/front_end/panels/emulation/MediaQueryInspector.ts +14 -4
- package/front_end/panels/emulation/deviceModeView.css +3 -3
- package/front_end/panels/explain/components/ConsoleInsight.ts +2 -3
- package/front_end/panels/explain/explain-meta.ts +1 -1
- package/front_end/panels/issues/AffectedMetadataAllowedSitesView.ts +67 -34
- package/front_end/panels/issues/issues.ts +2 -0
- package/front_end/panels/layer_viewer/LayerTreeOutline.ts +7 -3
- package/front_end/panels/lighthouse/LighthouseController.ts +29 -22
- package/front_end/panels/lighthouse/LighthousePanel.ts +5 -6
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +24 -16
- package/front_end/panels/media/PlayerMessagesView.ts +1 -1
- package/front_end/panels/mobile_throttling/CPUThrottlingSelector.ts +1 -1
- package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +45 -15
- package/front_end/panels/mobile_throttling/ThrottlingManager.ts +3 -3
- package/front_end/panels/network/BinaryResourceView.ts +54 -50
- package/front_end/panels/network/RequestHeadersView.ts +6 -2
- package/front_end/panels/network/RequestPreviewView.ts +28 -5
- package/front_end/panels/network/ResourceWebSocketFrameView.ts +1 -0
- package/front_end/panels/network/components/EditableSpan.ts +11 -30
- package/front_end/panels/network/components/HeaderSectionRow.ts +2 -2
- package/front_end/panels/performance_monitor/PerformanceMonitor.ts +10 -6
- package/front_end/panels/profiler/HeapDetachedElementsView.ts +112 -22
- package/front_end/panels/profiler/HeapProfileView.ts +3 -3
- package/front_end/panels/profiler/HeapSnapshotView.ts +12 -2
- package/front_end/panels/profiler/HeapTimelineOverview.ts +16 -2
- package/front_end/panels/profiler/profiler.ts +0 -2
- package/front_end/panels/protocol_monitor/JSONEditor.ts +1 -1
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +1 -1
- package/front_end/panels/recorder/CreateRecordingView.ts +1 -1
- package/front_end/panels/recorder/RecordingView.ts +3 -3
- package/front_end/panels/recorder/ReplaySection.ts +1 -1
- package/front_end/panels/screencast/ScreencastApp.ts +83 -57
- package/front_end/panels/screencast/ScreencastView.ts +76 -45
- package/front_end/panels/screencast/screencastView.css +1 -1
- package/front_end/panels/settings/AISettingsTab.ts +107 -4
- package/front_end/panels/settings/aiSettingsTab.css +53 -0
- package/front_end/panels/settings/settings-meta.ts +1 -1
- package/front_end/panels/settings/settingsScreen.css +0 -4
- package/front_end/panels/sources/BreakpointEditDialog.ts +3 -6
- package/front_end/panels/sources/BreakpointsView.ts +2 -2
- package/front_end/panels/sources/DebuggerPlugin.ts +7 -0
- package/front_end/panels/sources/NavigatorView.ts +61 -18
- package/front_end/panels/sources/SourcesNavigator.ts +22 -7
- package/front_end/panels/sources/SourcesPanel.ts +1 -0
- package/front_end/panels/timeline/CountersGraph.ts +1 -1
- package/front_end/panels/timeline/README.md +12 -0
- package/front_end/panels/timeline/StatusDialog.ts +1 -1
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -3
- package/front_end/panels/timeline/TimelineCommentController.ts +346 -0
- package/front_end/panels/timeline/TimelineDetailsView.ts +24 -1
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +34 -30
- package/front_end/panels/timeline/TimelineFlameChartView.ts +24 -10
- package/front_end/panels/timeline/TimelinePanel.ts +12 -5
- package/front_end/panels/timeline/TimelineTreeView.ts +28 -6
- package/front_end/panels/timeline/components/LiveMetricsView.ts +1 -1
- package/front_end/panels/timeline/components/fieldSettingsDialog.css +2 -2
- package/front_end/panels/timeline/components/insights/baseInsightComponent.css +1 -1
- package/front_end/panels/timeline/overlays/components/entriesLinkOverlay.css +2 -2
- package/front_end/panels/timeline/overlays/components/entryLabelOverlay.css +9 -9
- package/front_end/panels/timeline/timeline-meta.ts +2 -2
- package/front_end/panels/timeline/timeline.ts +4 -0
- package/front_end/panels/timeline/timelineFlamechartPopover.css +2 -2
- package/front_end/panels/timeline/timelinePanel.css +2 -2
- package/front_end/panels/timeline/utils/EntryNodes.ts +1 -1
- package/front_end/panels/web_audio/WebAudioView.ts +7 -4
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/codemirror.next/chunk/angular.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/angular.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/codemirror.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/cpp.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/cpp.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/java.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/java.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/less.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/less.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/markdown.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/markdown.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/php.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/php.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/python.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/python.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/sass.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/sass.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/svelte.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/svelte.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/vue.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/vue.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/wast.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/wast.js.map +1 -1
- package/front_end/third_party/codemirror.next/chunk/xml.js +1 -1
- package/front_end/third_party/codemirror.next/chunk/xml.js.map +1 -1
- package/front_end/third_party/codemirror.next/codemirror.next.js +1 -1
- package/front_end/third_party/codemirror.next/rollup.config.mjs +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +42 -12
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +154 -26
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.d.ts +47 -7
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js +56 -4
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts +6 -4
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js +5 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts +2 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js +23 -11
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js +1 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts +13 -7
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js +26 -11
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts +2 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js +69 -13
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts +10 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/types.d.ts +42 -12
- package/front_end/third_party/puppeteer/package/package.json +4 -4
- package/front_end/third_party/puppeteer/package/src/api/HTTPRequest.ts +103 -11
- package/front_end/third_party/puppeteer/package/src/api/Page.ts +11 -6
- package/front_end/third_party/puppeteer/package/src/bidi/HTTPRequest.ts +4 -4
- package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +26 -14
- package/front_end/third_party/puppeteer/package/src/cdp/HTTPRequest.ts +7 -7
- package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +40 -18
- package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +2 -3
- package/front_end/third_party/puppeteer/package/src/cdp/TargetManager.ts +87 -14
- package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +10 -0
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/tsconfig.json +1 -1
- package/front_end/ui/comments/CommentAnchorResolver.ts +1 -1
- package/front_end/ui/components/buttons/Button.ts +29 -18
- package/front_end/ui/components/code_highlighter/CodeHighlighter.ts +1 -1
- package/front_end/ui/components/dialogs/TypeToAllowDialog.ts +94 -39
- package/front_end/ui/components/dialogs/dialog.css +1 -1
- package/front_end/ui/components/menus/menuItem.css +11 -0
- package/front_end/ui/components/text_editor/AccessiblePlaceholder.ts +1 -1
- package/front_end/ui/components/text_editor/AiCodeCompletionTeaser.ts +1 -1
- package/front_end/ui/components/text_editor/config.ts +2 -1
- package/front_end/ui/components/text_editor/javascript.ts +2 -1
- package/front_end/ui/legacy/InspectorView.ts +4 -2
- package/front_end/ui/legacy/SplitWidget.ts +23 -24
- package/front_end/ui/legacy/TabbedPane.ts +9 -1
- package/front_end/ui/legacy/UIUtils.ts +60 -40
- package/front_end/ui/legacy/components/color_picker/spectrum.css +2 -2
- package/front_end/ui/legacy/components/data_grid/dataGrid.css +9 -0
- package/front_end/ui/legacy/components/inline_editor/CSSAngle.ts +0 -1
- package/front_end/ui/legacy/components/inline_editor/cssShadowEditor.css +5 -7
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +1 -1
- package/front_end/ui/legacy/components/perf_ui/PieChart.ts +11 -0
- package/front_end/ui/legacy/components/perf_ui/chartViewport.css +4 -4
- package/front_end/ui/legacy/components/quick_open/filteredListWidget.css +6 -0
- package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +1 -1
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +38 -13
- package/front_end/ui/legacy/dropTarget.css +1 -1
- package/front_end/ui/legacy/statusBar.css +7 -0
- package/front_end/ui/legacy/tabbedPane.css +0 -7
- package/front_end/ui/visual_logging/KnownContextValues.ts +55 -0
- package/inspector_overlay/main.ts +2 -15
- package/inspector_overlay/tool_persistent.ts +0 -14
- package/mcp/mcp.ts +3 -0
- package/package.json +1 -1
- package/.agents/skills/devtools-ux-writing-refactor/SKILL.md +0 -142
- package/front_end/panels/ai_assistance/components/StylingAgentMarkdownRenderer.ts +0 -178
- package/front_end/panels/profiler/HeapDetachedElementsDataGrid.ts +0 -147
- package/front_end/panels/profiler/heapDetachedElementsDataGrid.css +0 -14
- package/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts +0 -62
- package/front_end/ui/components/legacy_wrapper/legacy_wrapper.ts +0 -8
- package/inspector_overlay/tool_green_dev_anchors.css +0 -54
- package/inspector_overlay/tool_green_dev_anchors.ts +0 -164
- /package/front_end/models/{ai_assistance → ai-utils}/AiSetting.ts +0 -0
- /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 {
|
|
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
|
-
|
|
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)],
|
|
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#
|
|
64
|
-
* `AiConversation` starts a new run with the agent for the
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
994
|
-
|
|
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
|
|
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
|
-
|
|
1095
|
+
functionCalls = fetchResult.functionCalls;
|
|
1025
1096
|
|
|
1026
|
-
if (!
|
|
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 (!
|
|
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 (!
|
|
1143
|
+
if (!functionCalls) {
|
|
1073
1144
|
break;
|
|
1074
1145
|
}
|
|
1075
1146
|
}
|
|
1076
1147
|
|
|
1077
|
-
if (
|
|
1078
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
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
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
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
|
-
|
|
1171
|
-
options?: FunctionHandlerOptions&{explanation?: string},
|
|
1297
|
+
options?: FunctionHandlerOptions,
|
|
1172
1298
|
): AsyncGenerator<FunctionCallResponseData, {
|
|
1173
1299
|
result: unknown,
|
|
1174
1300
|
widgets?: AiWidget[],
|
|
1175
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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 (
|
|
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
|
|
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:
|
|
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",
|