chrome-devtools-frontend 1.0.1643855 → 1.0.1646286

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 (95) hide show
  1. package/.agents/skills/devtools-source-maps/SKILL.md +124 -0
  2. package/docs/README.md +1 -0
  3. package/docs/using_source_maps.md +159 -0
  4. package/front_end/core/host/AidaClientTypes.ts +2 -0
  5. package/front_end/core/host/UserMetrics.ts +5 -3
  6. package/front_end/core/root/Runtime.ts +10 -0
  7. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +2 -3
  8. package/front_end/core/sdk/DebuggerModel.ts +7 -9
  9. package/front_end/core/sdk/NetworkRequest.ts +0 -25
  10. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +37 -0
  11. package/front_end/generated/InspectorBackendCommands.ts +2 -2
  12. package/front_end/generated/SupportedCSSProperties.js +79 -2
  13. package/front_end/generated/protocol.ts +0 -5
  14. package/front_end/models/ai_assistance/AiAgent2.ts +52 -15
  15. package/front_end/models/ai_assistance/AiConversation.ts +4 -2
  16. package/front_end/models/ai_assistance/AiOrigins.ts +63 -2
  17. package/front_end/models/ai_assistance/README.md +20 -8
  18. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +2 -2
  19. package/front_end/models/ai_assistance/agents/FileAgent.ts +9 -42
  20. package/front_end/models/ai_assistance/agents/NetworkAgent.snapshot.txt +2 -2
  21. package/front_end/models/ai_assistance/agents/NetworkAgent.ts +9 -133
  22. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +25 -2
  23. package/front_end/models/ai_assistance/agents/README.md +64 -0
  24. package/front_end/models/ai_assistance/agents/StylingAgent.ts +26 -3
  25. package/front_end/models/ai_assistance/ai_assistance.ts +4 -0
  26. package/front_end/models/ai_assistance/contexts/FileContext.ts +45 -0
  27. package/front_end/models/ai_assistance/contexts/RequestContext.snapshot.txt +48 -0
  28. package/front_end/models/ai_assistance/contexts/RequestContext.ts +116 -0
  29. package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +2 -1
  30. package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +9 -12
  31. package/front_end/models/ai_assistance/tools/GetStyles.ts +19 -12
  32. package/front_end/models/ai_assistance/tools/README.md +45 -0
  33. package/front_end/models/ai_assistance/tools/Tool.ts +74 -11
  34. package/front_end/models/ai_assistance/tools/ToolRegistry.ts +21 -5
  35. package/front_end/models/heap_snapshot/HeapSnapshotModel.ts +18 -2
  36. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +4 -0
  37. package/front_end/models/stack_trace/DetailedErrorStackParser.ts +17 -4
  38. package/front_end/models/stack_trace/StackTraceModel.ts +34 -1
  39. package/front_end/models/trace/Styles.ts +29 -7
  40. package/front_end/models/trace/handlers/NetworkRequestsHandler.ts +15 -11
  41. package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +33 -4
  42. package/front_end/models/trace/helpers/Timing.ts +10 -0
  43. package/front_end/models/trace/types/TraceEvents.ts +22 -2
  44. package/front_end/models/web_mcp/WebMCPModel.ts +8 -48
  45. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +21 -15
  46. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +16 -0
  47. package/front_end/panels/ai_assistance/components/ChatInput.ts +4 -4
  48. package/front_end/panels/application/ApplicationPanelSidebar.ts +69 -0
  49. package/front_end/panels/application/ServiceWorkersView.ts +2 -2
  50. package/front_end/panels/application/WebMCPView.ts +40 -71
  51. package/front_end/panels/application/components/AdsView.ts +31 -28
  52. package/front_end/panels/application/components/BackForwardCacheView.ts +1 -2
  53. package/front_end/panels/application/components/adsView.css +6 -0
  54. package/front_end/panels/common/ExtensionServer.ts +5 -0
  55. package/front_end/panels/console/ConsoleView.ts +6 -1
  56. package/front_end/panels/console/ConsoleViewMessage.ts +46 -213
  57. package/front_end/panels/console/SymbolizedErrorWidget.ts +4 -1
  58. package/front_end/panels/elements/AdoptedStyleSheetTreeElement.ts +0 -1
  59. package/front_end/panels/elements/ElementsTreeElement.ts +0 -2
  60. package/front_end/panels/elements/PropertyRenderer.ts +0 -1
  61. package/front_end/panels/elements/StylesSidebarPane.ts +9 -2
  62. package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
  63. package/front_end/panels/issues/AffectedSourcesView.ts +1 -1
  64. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +0 -1
  65. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +10 -0
  66. package/front_end/panels/network/NetworkDataGridNode.ts +1 -2
  67. package/front_end/panels/network/NetworkLogView.ts +34 -7
  68. package/front_end/panels/profiler/HeapProfileView.ts +0 -1
  69. package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +0 -1
  70. package/front_end/panels/profiler/HeapSnapshotView.ts +1 -1
  71. package/front_end/panels/profiler/IsolateSelector.ts +4 -2
  72. package/front_end/panels/profiler/ProfileLauncherView.ts +194 -126
  73. package/front_end/panels/profiler/ProfilesPanel.ts +1 -3
  74. package/front_end/panels/settings/components/SyncSection.ts +1 -1
  75. package/front_end/panels/timeline/TimelineFlameChartView.ts +5 -4
  76. package/front_end/panels/timeline/TimelinePanel.ts +7 -0
  77. package/front_end/panels/timeline/TimelineUIUtils.ts +13 -14
  78. package/front_end/panels/timeline/TimingsTrackAppender.ts +7 -5
  79. package/front_end/panels/timeline/components/LayoutShiftDetails.ts +0 -1
  80. package/front_end/panels/timeline/components/NetworkRequestDetails.ts +0 -2
  81. package/front_end/panels/timeline/components/insights/ForcedReflow.ts +0 -1
  82. package/front_end/panels/timeline/components/insights/NodeLink.ts +0 -1
  83. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +2 -0
  84. package/front_end/third_party/chromium/README.chromium +1 -1
  85. package/front_end/ui/helpers/OpenInNewTab.ts +3 -3
  86. package/front_end/ui/kit/link/Link.ts +16 -2
  87. package/front_end/ui/legacy/InspectorDrawerView.ts +14 -5
  88. package/front_end/ui/legacy/InspectorView.ts +4 -1
  89. package/front_end/ui/legacy/PlusButton.ts +6 -1
  90. package/front_end/ui/legacy/Widget.ts +19 -1
  91. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +95 -31
  92. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +0 -1
  93. package/front_end/ui/legacy/components/utils/Linkifier.ts +2 -16
  94. package/front_end/ui/visual_logging/KnownContextValues.ts +6 -0
  95. package/package.json +1 -1
@@ -248,6 +248,8 @@ export const generatedProperties = [
248
248
  "name": "accent-color"
249
249
  },
250
250
  {
251
+ "is_descriptor": true,
252
+ "is_property": false,
251
253
  "name": "additive-symbols"
252
254
  },
253
255
  {
@@ -933,6 +935,8 @@ export const generatedProperties = [
933
935
  "name": "appearance"
934
936
  },
935
937
  {
938
+ "is_descriptor": true,
939
+ "is_property": false,
936
940
  "name": "ascent-override"
937
941
  },
938
942
  {
@@ -1053,9 +1057,13 @@ export const generatedProperties = [
1053
1057
  "name": "background-size"
1054
1058
  },
1055
1059
  {
1060
+ "is_descriptor": true,
1061
+ "is_property": false,
1056
1062
  "name": "base-palette"
1057
1063
  },
1058
1064
  {
1065
+ "is_descriptor": true,
1066
+ "is_property": false,
1059
1067
  "name": "base-url"
1060
1068
  },
1061
1069
  {
@@ -2338,6 +2346,8 @@ export const generatedProperties = [
2338
2346
  "name": "d"
2339
2347
  },
2340
2348
  {
2349
+ "is_descriptor": true,
2350
+ "is_property": false,
2341
2351
  "name": "descent-override"
2342
2352
  },
2343
2353
  {
@@ -2418,6 +2428,8 @@ export const generatedProperties = [
2418
2428
  "name": "empty-cells"
2419
2429
  },
2420
2430
  {
2431
+ "is_descriptor": true,
2432
+ "is_property": false,
2421
2433
  "name": "fallback"
2422
2434
  },
2423
2435
  {
@@ -2553,14 +2565,18 @@ export const generatedProperties = [
2553
2565
  "name": "font"
2554
2566
  },
2555
2567
  {
2568
+ "is_descriptor": true,
2569
+ "is_property": false,
2556
2570
  "name": "font-display"
2557
2571
  },
2558
2572
  {
2559
2573
  "inherited": true,
2574
+ "is_descriptor": true,
2560
2575
  "name": "font-family"
2561
2576
  },
2562
2577
  {
2563
2578
  "inherited": true,
2579
+ "is_descriptor": true,
2564
2580
  "keywords": [
2565
2581
  "normal"
2566
2582
  ],
@@ -2631,6 +2647,7 @@ export const generatedProperties = [
2631
2647
  },
2632
2648
  {
2633
2649
  "inherited": true,
2650
+ "is_descriptor": true,
2634
2651
  "keywords": [
2635
2652
  "normal",
2636
2653
  "ultra-condensed",
@@ -2646,6 +2663,7 @@ export const generatedProperties = [
2646
2663
  },
2647
2664
  {
2648
2665
  "inherited": true,
2666
+ "is_descriptor": true,
2649
2667
  "keywords": [
2650
2668
  "normal",
2651
2669
  "italic",
@@ -2688,6 +2706,7 @@ export const generatedProperties = [
2688
2706
  },
2689
2707
  {
2690
2708
  "inherited": true,
2709
+ "is_descriptor": true,
2691
2710
  "longhands": [
2692
2711
  "font-variant-ligatures",
2693
2712
  "font-variant-caps",
@@ -2787,6 +2806,7 @@ export const generatedProperties = [
2787
2806
  },
2788
2807
  {
2789
2808
  "inherited": true,
2809
+ "is_descriptor": true,
2790
2810
  "keywords": [
2791
2811
  "normal"
2792
2812
  ],
@@ -2794,6 +2814,7 @@ export const generatedProperties = [
2794
2814
  },
2795
2815
  {
2796
2816
  "inherited": true,
2817
+ "is_descriptor": true,
2797
2818
  "keywords": [
2798
2819
  "normal",
2799
2820
  "bold",
@@ -2972,6 +2993,8 @@ export const generatedProperties = [
2972
2993
  "name": "hanging-punctuation"
2973
2994
  },
2974
2995
  {
2996
+ "is_descriptor": true,
2997
+ "is_property": false,
2975
2998
  "name": "hash"
2976
2999
  },
2977
3000
  {
@@ -2984,6 +3007,8 @@ export const generatedProperties = [
2984
3007
  "name": "height"
2985
3008
  },
2986
3009
  {
3010
+ "is_descriptor": true,
3011
+ "is_property": false,
2987
3012
  "name": "hostname"
2988
3013
  },
2989
3014
  {
@@ -3033,6 +3058,8 @@ export const generatedProperties = [
3033
3058
  "name": "image-rendering"
3034
3059
  },
3035
3060
  {
3061
+ "is_descriptor": true,
3062
+ "is_property": false,
3036
3063
  "name": "inherits"
3037
3064
  },
3038
3065
  {
@@ -3045,6 +3072,8 @@ export const generatedProperties = [
3045
3072
  "name": "initial-letter"
3046
3073
  },
3047
3074
  {
3075
+ "is_descriptor": true,
3076
+ "is_property": false,
3048
3077
  "name": "initial-value"
3049
3078
  },
3050
3079
  {
@@ -3173,6 +3202,8 @@ export const generatedProperties = [
3173
3202
  "name": "line-clamp"
3174
3203
  },
3175
3204
  {
3205
+ "is_descriptor": true,
3206
+ "is_property": false,
3176
3207
  "name": "line-gap-override"
3177
3208
  },
3178
3209
  {
@@ -3468,9 +3499,13 @@ export const generatedProperties = [
3468
3499
  "name": "mix-blend-mode"
3469
3500
  },
3470
3501
  {
3502
+ "is_descriptor": true,
3503
+ "is_property": false,
3471
3504
  "name": "navigation"
3472
3505
  },
3473
3506
  {
3507
+ "is_descriptor": true,
3508
+ "is_property": false,
3474
3509
  "name": "negative"
3475
3510
  },
3476
3511
  {
@@ -3657,6 +3692,8 @@ export const generatedProperties = [
3657
3692
  "name": "overlay"
3658
3693
  },
3659
3694
  {
3695
+ "is_descriptor": true,
3696
+ "is_property": false,
3660
3697
  "name": "override-colors"
3661
3698
  },
3662
3699
  {
@@ -3691,6 +3728,8 @@ export const generatedProperties = [
3691
3728
  "name": "overscroll-behavior-y"
3692
3729
  },
3693
3730
  {
3731
+ "is_descriptor": true,
3732
+ "is_property": false,
3694
3733
  "name": "pad"
3695
3734
  },
3696
3735
  {
@@ -3765,6 +3804,7 @@ export const generatedProperties = [
3765
3804
  "name": "page-break-inside"
3766
3805
  },
3767
3806
  {
3807
+ "is_descriptor": true,
3768
3808
  "keywords": [
3769
3809
  "none",
3770
3810
  "clamp",
@@ -3773,6 +3813,7 @@ export const generatedProperties = [
3773
3813
  "name": "page-margin-safety"
3774
3814
  },
3775
3815
  {
3816
+ "is_descriptor": true,
3776
3817
  "name": "page-orientation"
3777
3818
  },
3778
3819
  {
@@ -3792,9 +3833,13 @@ export const generatedProperties = [
3792
3833
  "name": "path-length"
3793
3834
  },
3794
3835
  {
3836
+ "is_descriptor": true,
3837
+ "is_property": false,
3795
3838
  "name": "pathname"
3796
3839
  },
3797
3840
  {
3841
+ "is_descriptor": true,
3842
+ "is_property": false,
3798
3843
  "name": "pattern"
3799
3844
  },
3800
3845
  {
@@ -3845,6 +3890,8 @@ export const generatedProperties = [
3845
3890
  "name": "pointer-events"
3846
3891
  },
3847
3892
  {
3893
+ "is_descriptor": true,
3894
+ "is_property": false,
3848
3895
  "name": "port"
3849
3896
  },
3850
3897
  {
@@ -3860,7 +3907,8 @@ export const generatedProperties = [
3860
3907
  {
3861
3908
  "keywords": [
3862
3909
  "auto",
3863
- "none"
3910
+ "none",
3911
+ "normal"
3864
3912
  ],
3865
3913
  "name": "position-anchor"
3866
3914
  },
@@ -3921,6 +3969,8 @@ export const generatedProperties = [
3921
3969
  "name": "position-visibility"
3922
3970
  },
3923
3971
  {
3972
+ "is_descriptor": true,
3973
+ "is_property": false,
3924
3974
  "name": "prefix"
3925
3975
  },
3926
3976
  {
@@ -3932,6 +3982,8 @@ export const generatedProperties = [
3932
3982
  "name": "print-color-adjust"
3933
3983
  },
3934
3984
  {
3985
+ "is_descriptor": true,
3986
+ "is_property": false,
3935
3987
  "name": "protocol"
3936
3988
  },
3937
3989
  {
@@ -3946,6 +3998,8 @@ export const generatedProperties = [
3946
3998
  "name": "r"
3947
3999
  },
3948
4000
  {
4001
+ "is_descriptor": true,
4002
+ "is_property": false,
3949
4003
  "name": "range"
3950
4004
  },
3951
4005
  {
@@ -3975,6 +4029,8 @@ export const generatedProperties = [
3975
4029
  "name": "resize"
3976
4030
  },
3977
4031
  {
4032
+ "is_descriptor": true,
4033
+ "is_property": false,
3978
4034
  "name": "result"
3979
4035
  },
3980
4036
  {
@@ -4474,6 +4530,8 @@ export const generatedProperties = [
4474
4530
  "name": "scrollbar-width"
4475
4531
  },
4476
4532
  {
4533
+ "is_descriptor": true,
4534
+ "is_property": false,
4477
4535
  "name": "search"
4478
4536
  },
4479
4537
  {
@@ -4505,6 +4563,8 @@ export const generatedProperties = [
4505
4563
  "name": "size"
4506
4564
  },
4507
4565
  {
4566
+ "is_descriptor": true,
4567
+ "is_property": false,
4508
4568
  "name": "size-adjust"
4509
4569
  },
4510
4570
  {
@@ -4520,9 +4580,13 @@ export const generatedProperties = [
4520
4580
  "name": "speak"
4521
4581
  },
4522
4582
  {
4583
+ "is_descriptor": true,
4584
+ "is_property": false,
4523
4585
  "name": "speak-as"
4524
4586
  },
4525
4587
  {
4588
+ "is_descriptor": true,
4589
+ "is_property": false,
4526
4590
  "name": "src"
4527
4591
  },
4528
4592
  {
@@ -4580,15 +4644,23 @@ export const generatedProperties = [
4580
4644
  "name": "stroke-width"
4581
4645
  },
4582
4646
  {
4647
+ "is_descriptor": true,
4648
+ "is_property": false,
4583
4649
  "name": "suffix"
4584
4650
  },
4585
4651
  {
4652
+ "is_descriptor": true,
4653
+ "is_property": false,
4586
4654
  "name": "symbols"
4587
4655
  },
4588
4656
  {
4657
+ "is_descriptor": true,
4658
+ "is_property": false,
4589
4659
  "name": "syntax"
4590
4660
  },
4591
4661
  {
4662
+ "is_descriptor": true,
4663
+ "is_property": false,
4592
4664
  "name": "system"
4593
4665
  },
4594
4666
  {
@@ -5051,6 +5123,8 @@ export const generatedProperties = [
5051
5123
  "name": "trigger-scope"
5052
5124
  },
5053
5125
  {
5126
+ "is_descriptor": true,
5127
+ "is_property": false,
5054
5128
  "name": "types"
5055
5129
  },
5056
5130
  {
@@ -5065,6 +5139,8 @@ export const generatedProperties = [
5065
5139
  "name": "unicode-bidi"
5066
5140
  },
5067
5141
  {
5142
+ "is_descriptor": true,
5143
+ "is_property": false,
5068
5144
  "name": "unicode-range"
5069
5145
  },
5070
5146
  {
@@ -6987,7 +7063,8 @@ export const generatedPropertyValues = {
6987
7063
  "position-anchor": {
6988
7064
  "values": [
6989
7065
  "auto",
6990
- "none"
7066
+ "none",
7067
+ "normal"
6991
7068
  ]
6992
7069
  },
6993
7070
  "position-area": {
@@ -11136,10 +11136,6 @@ export namespace Network {
11136
11136
  export const enum CookieExemptionReason {
11137
11137
  None = 'None',
11138
11138
  UserSetting = 'UserSetting',
11139
- TPCDMetadata = 'TPCDMetadata',
11140
- TPCDDeprecationTrial = 'TPCDDeprecationTrial',
11141
- TopLevelTPCDDeprecationTrial = 'TopLevelTPCDDeprecationTrial',
11142
- TPCDHeuristics = 'TPCDHeuristics',
11143
11139
  EnterprisePolicy = 'EnterprisePolicy',
11144
11140
  StorageAccess = 'StorageAccess',
11145
11141
  TopLevelStorageAccess = 'TopLevelStorageAccess',
@@ -14604,7 +14600,6 @@ export namespace Page {
14604
14600
  DigitalCredentialsGet = 'digital-credentials-get',
14605
14601
  DirectSockets = 'direct-sockets',
14606
14602
  DirectSocketsMulticast = 'direct-sockets-multicast',
14607
- DirectSocketsPrivate = 'direct-sockets-private',
14608
14603
  DisplayCapture = 'display-capture',
14609
14604
  DocumentDomain = 'document-domain',
14610
14605
  EncryptedMedia = 'encrypted-media',
@@ -3,9 +3,11 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import * as Host from '../../core/host/host.js';
6
+ import * as SDK from '../../core/sdk/sdk.js';
6
7
 
7
8
  import {
8
9
  AiAgent,
10
+ type AllowedOriginResult,
9
11
  type ContextResponse,
10
12
  type ConversationContext,
11
13
  type MultimodalInputType,
@@ -19,22 +21,50 @@ import {debugLog} from './debug.js';
19
21
  import {ExtensionScope} from './ExtensionScope.js';
20
22
  import type {Skill, SkillName} from './skills/Skill.js';
21
23
  import {SKILLS} from './skills/SkillRegistry.js';
22
- import type {Tool} from './tools/Tool.js';
24
+ import type {AllToolsContext, Tool, ToolArgs} from './tools/Tool.js';
23
25
  import {ToolRegistry} from './tools/ToolRegistry.js';
24
26
 
25
27
  const SKILL_DISPLAY_NAMES: Record<SkillName, string> = {
26
28
  styling: 'CSS and styling',
27
29
  };
28
30
 
31
+ const preamble = `You are the most advanced unified AI assistant integrated into Chrome DevTools.
32
+ Your role is to help web developers debug, analyze, and optimize web applications by learning specialized skills and utilizing tools.
33
+
34
+ # Style Guidelines
35
+ * **Precision and Brevity**: Use the precision of Strunk & White, the brevity of Hemingway, and the simple clarity of Vonnegut. Keep answers short, direct, and avoid repeated information or filler.
36
+ * **Tone**: Technical, precise, educational, and supportive.
37
+ * **No Self-Reference**: Do not mention that you are an AI, or refer to yourself in the third person. Simulate a senior web development expert.
38
+ * **No Internal Details**: Do not mention internal implementation details like the names of functions or tools you called (e.g., do not say "I called getStyles").
39
+
40
+ # Workflow
41
+ 1. **Analyze**: Understand the user's intent, the context provided, and what they are trying to achieve.
42
+ 2. **Investigate**: Proactively use your learned skills and tools to gather live data. Do not make assumptions or guess without sufficient evidence.
43
+ 3. **Analyze**: Explore multiple potential explanations and solutions. Distinguish between the primary root cause and contributing factors.
44
+ 4. **Respond**: Provide a structured, clear, and actionable response.
45
+
46
+ # Response Structure
47
+ If the user asks a question that requires an investigation or debugging, use this structure:
48
+ * **Root Cause(s)**: Point out the root cause(s) of the problem.
49
+ - Example: "**Root Cause**: [reason]" or "**Root Causes**:" followed by a bulleted list.
50
+ * **Suggestion(s)**: List actionable solution suggestion(s) in order of impact.
51
+ - Example: "**Suggestion**: [Suggestion]" or "**Suggestions**:" followed by a bulleted list.
52
+
53
+ # Constraints
54
+ * **CRITICAL**: You are a web development assistant. NEVER provide answers to questions of unrelated topics (such as legal advice, financial advice, personal opinions, medical advice, religion, race, politics, sexuality, gender, or any other non-web-development topics). If asked about these, respond with: "Sorry, I can't answer that. I'm best at questions about web development and debugging."
55
+ * **CRITICAL**: Do not write full Python programs or other scripts to interact with the environment. Only invoke the allowed tools.
56
+ * **CRITICAL**: Do not expose raw, internal system identifiers (such as database IDs, internal node paths, or event keys) directly to the user. Use descriptive names instead.`;
57
+
29
58
  export class AiAgent2 extends AiAgent<unknown> {
30
59
  // TODO: The static preamble is a placeholder and will eventually live server-side.
31
- readonly preamble = 'You are a unified AI assistant in Chrome DevTools. You can learn skills to help the user.';
32
- readonly clientFeature = Host.AidaClient.ClientFeature.CHROME_STYLING_AGENT; // Placeholder
60
+ readonly preamble = preamble;
61
+ readonly clientFeature = Host.AidaClient.ClientFeature.CHROME_DEVTOOLS_V2_AGENT;
33
62
  readonly userTier = 'TESTERS';
34
63
 
35
64
  #skillsInjected = false;
36
65
  #changes = new ChangeManager();
37
66
  #execJs: typeof executeJsCode;
67
+ readonly #allowedOrigin?: () => AllowedOriginResult;
38
68
 
39
69
  get options(): RequestOptions {
40
70
  return {};
@@ -46,6 +76,7 @@ export class AiAgent2 extends AiAgent<unknown> {
46
76
  constructor(opts: ExecuteJsAgentOptions) {
47
77
  super(opts);
48
78
  this.#execJs = opts.execJs ?? executeJsCode;
79
+ this.#allowedOrigin = opts.allowedOrigin;
49
80
  this.#declaredTools.add('learnSkills');
50
81
  const skillsList = Object.keys(SKILLS).join(', ');
51
82
  this.declareFunction<{skills: SkillName[]}>('learnSkills', {
@@ -169,7 +200,7 @@ User query: ${enhancedQuery}`;
169
200
  * Declares a tool to be available to the agent model, verifying first that
170
201
  * it hasn't already been declared to prevent duplicate declaration errors.
171
202
  */
172
- #declareTool(tool: Tool): void {
203
+ #declareTool(tool: Tool<ToolArgs, unknown, AllToolsContext>): void {
173
204
  if (this.#declaredTools.has(tool.name)) {
174
205
  debugLog(`AiAgent2: Tool ${tool.name} is already declared`);
175
206
  return;
@@ -179,20 +210,26 @@ User query: ${enhancedQuery}`;
179
210
  description: tool.description,
180
211
  parameters: tool.parameters,
181
212
  displayInfoFromArgs: tool.displayInfoFromArgs,
182
- handler: (args, options) => tool.handler(
183
- args,
184
- {
185
- conversationContext: this.context ?? null,
186
- changeManager: this.#changes,
187
- createExtensionScope: this.#createExtensionScope.bind(this),
188
- execJs: this.#execJs,
189
- getExecutionContextNode: () => this.context instanceof DOMNodeContext ? this.context.getItem() : null,
190
- },
191
- options,
192
- ),
213
+ handler: (args, options) => {
214
+ const context: AllToolsContext = {
215
+ conversationContext: this.context ?? null,
216
+ changeManager: this.#changes,
217
+ createExtensionScope: this.#createExtensionScope.bind(this),
218
+ execJs: this.#execJs,
219
+ getExecutionContextNode: () => this.context instanceof DOMNodeContext ? this.context.getItem() : null,
220
+ getTarget: () => SDK.TargetManager.TargetManager.instance().primaryPageTarget(),
221
+ getEstablishedOrigin: () => this.#getConversationOrigin(),
222
+ };
223
+ return tool.handler(args, context, options);
224
+ },
193
225
  });
194
226
  }
195
227
 
228
+ #getConversationOrigin(): string|undefined {
229
+ const allowed = this.#allowedOrigin?.();
230
+ return allowed && 'origin' in allowed ? allowed.origin : undefined;
231
+ }
232
+
196
233
  get activeSkills(): Set<SkillName> {
197
234
  return this.#activeSkills;
198
235
  }
@@ -25,8 +25,8 @@ import {
25
25
  type UserQuery
26
26
  } from './agents/AiAgent.js';
27
27
  import {ContextSelectionAgent} from './agents/ContextSelectionAgent.js';
28
- import {FileAgent, FileContext} from './agents/FileAgent.js';
29
- import {NetworkAgent, RequestContext} from './agents/NetworkAgent.js';
28
+ import {FileAgent} from './agents/FileAgent.js';
29
+ import {NetworkAgent} from './agents/NetworkAgent.js';
30
30
  import {PerformanceAgent, PerformanceTraceContext} from './agents/PerformanceAgent.js';
31
31
  import {StorageAgent, StorageContext} from './agents/StorageAgent.js';
32
32
  import {StylingAgent} from './agents/StylingAgent.js';
@@ -34,6 +34,8 @@ import {AiAgent2} from './AiAgent2.js';
34
34
  import {AiHistoryStorage, ConversationType, type SerializedConversation} from './AiHistoryStorage.js';
35
35
  import type {ChangeManager} from './ChangeManager.js';
36
36
  import {DOMNodeContext} from './contexts/DOMNodeContext.js';
37
+ import {FileContext} from './contexts/FileContext.js';
38
+ import {RequestContext} from './contexts/RequestContext.js';
37
39
 
38
40
  export const NOT_FOUND_IMAGE_DATA = '';
39
41
  export const CONTEXT_TITLE = 'Analyzing data';
@@ -9,6 +9,8 @@ import type * as Platform from '../../core/platform/platform.js';
9
9
  * Returns true if the origin is considered opaque and should be blocked from
10
10
  * AI assistance to prevent potential data leakage.
11
11
  *
12
+ * @param origin The origin string to check.
13
+ * @returns True if the origin is opaque and blocked.
12
14
  * @see https://crbug.com/513732588
13
15
  */
14
16
  export function isOpaqueOrigin(origin: string): boolean {
@@ -16,13 +18,22 @@ export function isOpaqueOrigin(origin: string): boolean {
16
18
  * Origins starting with 'about' (like about:blank or about:srcdoc) are
17
19
  * considered opaque. 'about://' is the sentinel used by DevTools
18
20
  * ParsedURL.securityOrigin() for these.
21
+ *
22
+ * We also treat empty origins, 'undefined', and 'null' as opaque to prevent
23
+ * bypasses when URL parsing fails or variables are uninitialized.
19
24
  */
20
- return origin === 'null' || origin === 'data:' || origin.startsWith('about') || origin.startsWith('detached');
25
+ const lower = origin.toLowerCase();
26
+ return lower === '' || lower === 'null' || lower === 'data:' || lower.startsWith('about') ||
27
+ lower.startsWith('detached') || lower.startsWith('undefined');
21
28
  }
22
29
 
23
30
  /**
24
31
  * Extracts the origin from a context URL or identifier.
25
- * Handles special cases like "detached" nodes and trace identifiers.
32
+ * Handles special cases like "detached" nodes, trace identifiers,
33
+ * opaque blob URLs, and isolates local file paths.
34
+ *
35
+ * @param contextURL The context URL or trace/node identifier.
36
+ * @returns The extracted origin string.
26
37
  */
27
38
  export function extractContextOrigin(contextURL: string): string {
28
39
  if (isOpaqueOrigin(contextURL)) {
@@ -31,6 +42,28 @@ export function extractContextOrigin(contextURL: string): string {
31
42
  if (contextURL.startsWith('trace-')) {
32
43
  return contextURL;
33
44
  }
45
+ // If a blob URL has an opaque inner origin (e.g. blob:null/uuid, blob:about:blank),
46
+ // it won't contain "://". We classify these as opaque ('null') to prevent cross-origin leaks.
47
+ if (/^blob:/i.test(contextURL)) {
48
+ const innerURL = contextURL.substring(5);
49
+ if (!innerURL.includes('://')) {
50
+ return 'null';
51
+ }
52
+ }
53
+ // Local files collapse to a generic "file://" origin by default. We isolate them
54
+ // by appending the normalized path, ensuring distinct files are treated as different origins.
55
+ if (/^file:\/\//i.test(contextURL)) {
56
+ const parsed = Common.ParsedURL.ParsedURL.fromString(contextURL as Platform.DevToolsPath.UrlString);
57
+ if (parsed) {
58
+ // Include host and port (authority) to preserve server names in Windows UNC paths
59
+ // (e.g. file://server/path) so different network shares are isolated.
60
+ const authority = parsed.host + (parsed.port ? ':' + parsed.port : '');
61
+ return 'file://' + authority + parsed.path;
62
+ }
63
+ // Fallback to 'null' (opaque) if parsing fails. This prevents malformed file URLs
64
+ // from bypassing isolation by collapsing to the same 'file://' string.
65
+ return 'null';
66
+ }
34
67
  return Common.ParsedURL.ParsedURL.extractOrigin(contextURL as Platform.DevToolsPath.UrlString);
35
68
  }
36
69
 
@@ -44,3 +77,31 @@ export function areOriginsEquivalent(origin1: string, origin2: string): boolean
44
77
  }
45
78
  return origin1 === origin2;
46
79
  }
80
+
81
+ /**
82
+ * Validates if the source code contents of a file (identified by targetURL) can be retrieved
83
+ * and shared with the AI, based on the origin of the active trace context.
84
+ *
85
+ * This function handles the following branches:
86
+ * 1. **Opaque origins**: If either the trace origin or target file origin is opaque
87
+ * (e.g., data URLs, about:blank, sandboxed frames), access is blocked.
88
+ * 2. **Fresh Recordings**: For live page recordings, a strict same-origin comparison
89
+ * (scheme, host, and port matching) is enforced.
90
+ *
91
+ * @param targetURL The URL of the file to be read.
92
+ * @param traceOrigin The allowed origin of the trace context.
93
+ * @returns true if reading the file is permitted; false otherwise.
94
+ */
95
+ export function canResourceContentsBeReadForTrace(targetURL: string, traceOrigin: string): boolean {
96
+ // We explicitly block all file:// URLs. While we want to allow users to debug
97
+ // traces on local sites, allowing file:// access poses security risks (e.g.,
98
+ // reading local files like /etc/passwd via prompt injection) because file://
99
+ // origins are not sufficiently isolated from each other in DevTools' origin model.
100
+ if (traceOrigin.startsWith('file://') || targetURL.startsWith('file://')) {
101
+ return false;
102
+ }
103
+
104
+ const targetOrigin = extractContextOrigin(targetURL);
105
+
106
+ return areOriginsEquivalent(targetOrigin, traceOrigin);
107
+ }
@@ -11,12 +11,14 @@ Each agent has a _context_ defined, which represents the selected data that form
11
11
  - The `PerformanceAgent` has an individual performance trace and a specific focus (an insight, or a call tree) as its context.
12
12
  - The `StylingAgent` has a DOM Node as its context.
13
13
 
14
- When defining a context, they must extend the `ConversationContext` interface, which defines a few methods which must be implemented, including:
14
+ Contexts are defined as subclasses extending the `ConversationContext` abstract class, which defines the following key methods:
15
15
 
16
- - `getOrigin()`: the origin of the data. This is important as for security concerns if the user swaps to a new context with a different origin, a new conversation must be started to avoid any concerns of sharing data across origins.
17
- - `getTitle()` which are used to represent the context in the UI.
16
+ - `getOrigin()`: the origin of the data. This is critical for security: if the user switches to a new context with a different origin, the panel forces a new conversation to avoid cross-origin data exposure.
17
+ - `getTitle()`: returns the user-facing title of the context.
18
+ - `getPromptDetails()`: returns a Markdown formatted description of the context item to be directly included in the LLM prompt.
19
+ - `getUserFacingDetails()`: returns structured details (such as request/response headers, timings, etc.) displayed to the user in the UI under the "Analyzing data" accordion.
18
20
 
19
- When the user begins a conversation with the AI, we want to include information based on the active context to send as part of the prompt. This is done in the agent implementation by overriding the `enhanceQuery()` method, which takes the active context as the second argument. This method can be used to enrich the query with contextual information.
21
+ Encapsulating prompt formatting and UI generation within the context classes simplifies agent implementations and promotes reusability. Contexts are located in the `contexts/` directory.
20
22
 
21
23
  ### Formatters
22
24
 
@@ -24,7 +26,7 @@ To deal with the work to take an object that is the AI agent's context and turn
24
26
 
25
27
  ## Future Architecture (V2) - WIP
26
28
 
27
- We are currently working on migrating the DevTools AI Assistance from a siloed multi-agent architecture to a unified, skill-based single-agent architecture (`AIAgent2`).
29
+ We are migrating the DevTools AI Assistance from a siloed multi-agent architecture to a unified, skill-based single-agent architecture (`AIAgent2`).
28
30
 
29
31
  In this new architecture:
30
32
  - A single agent (`AIAgent2`) handles multiple domains.
@@ -36,15 +38,16 @@ This work is currently in progress and behind a feature flag.
36
38
  ### Skills Build System
37
39
 
38
40
  To support dynamic loading of skills, we generate JavaScript files from Markdown files containing skill definitions.
39
- We use a nested `BUILD.gn` file in the `skills/` subdirectory specifically for this purpose. This ensures that GN's `target_gen_dir` points to `gen/front_end/models/ai_assistance/skills/`, placing the generated `.skill.js` files in the same relative structure as their source `.md` files. This allows TypeScript files in the `skills/` directory (like `map.ts`) to import the generated files using relative paths (e.g., `./styling.skill.js`) seamlessly.
41
+ We use a nested `BUILD.gn` file in the `skills/` subdirectory specifically for this purpose. This ensures that GN's `target_gen_dir` points to `gen/front_end/models/ai_assistance/skills/`, placing the generated `.skill.js` files in the same relative structure as their source `.md` files. This allows TypeScript files in the `skills/` directory (like `map.ts`) to import the generated files using relative paths (e.g., `./styling.skill.js`) seamlessly. See the [Skills README](skills/README.md) for full details.
40
42
 
41
43
  ### Tools and ToolRegistry
42
44
 
43
45
  To support skills requiring execution of code or fetching page state (like computed styles), the architecture defines **Tools** in the `tools/` directory.
44
46
 
45
47
  - **BaseTool**: A non-generic base interface capturing tool metadata (`name`, `description`, `parameters`). This acts as the type-erased representation for generic registry storage and fallback string lookups.
46
- - **Tool**: A generic interface extending `BaseTool` that binds argument types (`Args`) to the schema `parameters` and the `handler()` method. This ensures compile-time safety and alignment inside each tool implementation.
47
- - **ToolRegistry**: A static registry (`ToolRegistry`) storing instantiated tools. It uses TypeScript function overloading and generic lookups (`static get<K extends keyof typeof TOOLS>(name: K): typeof TOOLS[K]`) to return the precise class type of each tool, preventing type-erasure and escape-hatches (such as `any` or `as unknown` type assertions) at integration points like `AiAgent.ts`.
48
+ - **Tool**: A generic interface parameterized by `<Args, ReturnType, ContextType>` that binds parameter argument types and handler execution to strict contracts. `ContextType` defaults to `BaseToolCapability`, ensuring that each tool explicitly requests only the dependencies it requires.
49
+ - **Capability Contexts**: Instead of passing a monolithic grab-bag context to all tools, dependencies are broken into narrow capability interfaces (e.g. `PageExecutionCapability`, `StyleMutationCapability`, `TargetCapability`, `OriginLockCapability`). Tools declare their required dependencies by intersecting these interfaces on their generic `ContextType` definition. The caller/Agent fulfills the complete capability context (`AllToolsContext`), guaranteeing 100% compile-time type safety for dependencies without runtime checks.
50
+ - **ToolRegistry**: A static registry (`ToolRegistry`) storing instantiated tools. It uses TypeScript function overloading and generic lookups (`static get<K extends keyof typeof TOOLS>(name: K): typeof TOOLS[K]`) to return the precise class type of each tool, preventing type-erasure and escape-hatches (such as `any` or `as unknown` type assertions) at integration points like `AiAgent2.ts`. See the [Tools README](tools/README.md) for authoring instructions.
48
51
 
49
52
  ## Performance specific documentation
50
53
 
@@ -101,3 +104,12 @@ To aid debugging, you can enable the AI Assistance logging. This setting is stor
101
104
  4. In the console, run `setDebugAiAssistanceEnabled(true)`.
102
105
 
103
106
  Now, when interacting with the AI and sending requests, you will see output logged to the console. You can use the `debugLog` helper to add your own logging as you are building out your feature.
107
+
108
+ ## Security & Origin Isolation
109
+
110
+ To prevent prompt injection attacks and cross-origin data leaks, the AI Assistance panel enforces strict origin-lock boundaries:
111
+
112
+ * **Origin Locking**: Once a conversation session begins, it locks to the origin of the initial data context (e.g. `https://google.com` or a specific file path).
113
+ * **Opaque Origins**: Any origin classified as opaque (e.g. `data:`, `about:`, `detached` nodes, unparsed `undefined://` or empty origins) is blocked from starting AI assistance (`isOpaqueOrigin()`).
114
+ * **File Isolation**: Local files (`file://`) do not share a single wildcard origin. Instead, the path is appended (e.g. `file:///path/to/file.js`) to treat each local file as its own unique origin. Swapping local files in the same conversation is blocked.
115
+ * **Equivalence**: `areOriginsEquivalent()` ensures opaque origins are never equivalent to anything (including themselves), forcing a conversation reset on transitions.