chrome-devtools-frontend 1.0.1645245 → 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.
- package/.agents/skills/devtools-source-maps/SKILL.md +124 -0
- package/docs/README.md +1 -0
- package/docs/using_source_maps.md +159 -0
- package/front_end/core/host/AidaClientTypes.ts +2 -0
- package/front_end/core/host/UserMetrics.ts +2 -1
- package/front_end/core/root/Runtime.ts +10 -0
- package/front_end/core/sdk/DebuggerModel.ts +7 -9
- package/front_end/core/sdk/NetworkRequest.ts +0 -24
- package/front_end/generated/InspectorBackendCommands.ts +2 -2
- package/front_end/generated/SupportedCSSProperties.js +75 -0
- package/front_end/generated/protocol.ts +0 -5
- package/front_end/models/ai_assistance/AiAgent2.ts +29 -2
- package/front_end/models/ai_assistance/AiConversation.ts +4 -2
- package/front_end/models/ai_assistance/AiOrigins.ts +63 -2
- package/front_end/models/ai_assistance/README.md +15 -4
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +2 -2
- package/front_end/models/ai_assistance/agents/FileAgent.ts +9 -42
- package/front_end/models/ai_assistance/agents/NetworkAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +9 -133
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +10 -2
- package/front_end/models/ai_assistance/agents/README.md +7 -0
- package/front_end/models/ai_assistance/ai_assistance.ts +4 -0
- package/front_end/models/ai_assistance/contexts/FileContext.ts +45 -0
- package/front_end/models/ai_assistance/contexts/RequestContext.snapshot.txt +48 -0
- package/front_end/models/ai_assistance/contexts/RequestContext.ts +116 -0
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +2 -1
- package/front_end/models/ai_assistance/tools/README.md +1 -1
- package/front_end/models/trace/handlers/NetworkRequestsHandler.ts +15 -11
- package/front_end/models/web_mcp/WebMCPModel.ts +8 -48
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +13 -13
- package/front_end/panels/ai_assistance/components/ChatInput.ts +4 -4
- package/front_end/panels/application/ApplicationPanelSidebar.ts +25 -0
- package/front_end/panels/application/WebMCPView.ts +40 -70
- package/front_end/panels/application/components/AdsView.ts +31 -28
- package/front_end/panels/application/components/adsView.css +6 -0
- package/front_end/panels/common/ExtensionServer.ts +5 -0
- package/front_end/panels/profiler/IsolateSelector.ts +4 -2
- package/front_end/panels/profiler/ProfileLauncherView.ts +194 -126
- package/front_end/panels/profiler/ProfilesPanel.ts +1 -3
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- 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
|
{
|
|
@@ -3922,6 +3969,8 @@ export const generatedProperties = [
|
|
|
3922
3969
|
"name": "position-visibility"
|
|
3923
3970
|
},
|
|
3924
3971
|
{
|
|
3972
|
+
"is_descriptor": true,
|
|
3973
|
+
"is_property": false,
|
|
3925
3974
|
"name": "prefix"
|
|
3926
3975
|
},
|
|
3927
3976
|
{
|
|
@@ -3933,6 +3982,8 @@ export const generatedProperties = [
|
|
|
3933
3982
|
"name": "print-color-adjust"
|
|
3934
3983
|
},
|
|
3935
3984
|
{
|
|
3985
|
+
"is_descriptor": true,
|
|
3986
|
+
"is_property": false,
|
|
3936
3987
|
"name": "protocol"
|
|
3937
3988
|
},
|
|
3938
3989
|
{
|
|
@@ -3947,6 +3998,8 @@ export const generatedProperties = [
|
|
|
3947
3998
|
"name": "r"
|
|
3948
3999
|
},
|
|
3949
4000
|
{
|
|
4001
|
+
"is_descriptor": true,
|
|
4002
|
+
"is_property": false,
|
|
3950
4003
|
"name": "range"
|
|
3951
4004
|
},
|
|
3952
4005
|
{
|
|
@@ -3976,6 +4029,8 @@ export const generatedProperties = [
|
|
|
3976
4029
|
"name": "resize"
|
|
3977
4030
|
},
|
|
3978
4031
|
{
|
|
4032
|
+
"is_descriptor": true,
|
|
4033
|
+
"is_property": false,
|
|
3979
4034
|
"name": "result"
|
|
3980
4035
|
},
|
|
3981
4036
|
{
|
|
@@ -4475,6 +4530,8 @@ export const generatedProperties = [
|
|
|
4475
4530
|
"name": "scrollbar-width"
|
|
4476
4531
|
},
|
|
4477
4532
|
{
|
|
4533
|
+
"is_descriptor": true,
|
|
4534
|
+
"is_property": false,
|
|
4478
4535
|
"name": "search"
|
|
4479
4536
|
},
|
|
4480
4537
|
{
|
|
@@ -4506,6 +4563,8 @@ export const generatedProperties = [
|
|
|
4506
4563
|
"name": "size"
|
|
4507
4564
|
},
|
|
4508
4565
|
{
|
|
4566
|
+
"is_descriptor": true,
|
|
4567
|
+
"is_property": false,
|
|
4509
4568
|
"name": "size-adjust"
|
|
4510
4569
|
},
|
|
4511
4570
|
{
|
|
@@ -4521,9 +4580,13 @@ export const generatedProperties = [
|
|
|
4521
4580
|
"name": "speak"
|
|
4522
4581
|
},
|
|
4523
4582
|
{
|
|
4583
|
+
"is_descriptor": true,
|
|
4584
|
+
"is_property": false,
|
|
4524
4585
|
"name": "speak-as"
|
|
4525
4586
|
},
|
|
4526
4587
|
{
|
|
4588
|
+
"is_descriptor": true,
|
|
4589
|
+
"is_property": false,
|
|
4527
4590
|
"name": "src"
|
|
4528
4591
|
},
|
|
4529
4592
|
{
|
|
@@ -4581,15 +4644,23 @@ export const generatedProperties = [
|
|
|
4581
4644
|
"name": "stroke-width"
|
|
4582
4645
|
},
|
|
4583
4646
|
{
|
|
4647
|
+
"is_descriptor": true,
|
|
4648
|
+
"is_property": false,
|
|
4584
4649
|
"name": "suffix"
|
|
4585
4650
|
},
|
|
4586
4651
|
{
|
|
4652
|
+
"is_descriptor": true,
|
|
4653
|
+
"is_property": false,
|
|
4587
4654
|
"name": "symbols"
|
|
4588
4655
|
},
|
|
4589
4656
|
{
|
|
4657
|
+
"is_descriptor": true,
|
|
4658
|
+
"is_property": false,
|
|
4590
4659
|
"name": "syntax"
|
|
4591
4660
|
},
|
|
4592
4661
|
{
|
|
4662
|
+
"is_descriptor": true,
|
|
4663
|
+
"is_property": false,
|
|
4593
4664
|
"name": "system"
|
|
4594
4665
|
},
|
|
4595
4666
|
{
|
|
@@ -5052,6 +5123,8 @@ export const generatedProperties = [
|
|
|
5052
5123
|
"name": "trigger-scope"
|
|
5053
5124
|
},
|
|
5054
5125
|
{
|
|
5126
|
+
"is_descriptor": true,
|
|
5127
|
+
"is_property": false,
|
|
5055
5128
|
"name": "types"
|
|
5056
5129
|
},
|
|
5057
5130
|
{
|
|
@@ -5066,6 +5139,8 @@ export const generatedProperties = [
|
|
|
5066
5139
|
"name": "unicode-bidi"
|
|
5067
5140
|
},
|
|
5068
5141
|
{
|
|
5142
|
+
"is_descriptor": true,
|
|
5143
|
+
"is_property": false,
|
|
5069
5144
|
"name": "unicode-range"
|
|
5070
5145
|
},
|
|
5071
5146
|
{
|
|
@@ -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',
|
|
@@ -28,10 +28,37 @@ const SKILL_DISPLAY_NAMES: Record<SkillName, string> = {
|
|
|
28
28
|
styling: 'CSS and styling',
|
|
29
29
|
};
|
|
30
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
|
+
|
|
31
58
|
export class AiAgent2 extends AiAgent<unknown> {
|
|
32
59
|
// TODO: The static preamble is a placeholder and will eventually live server-side.
|
|
33
|
-
readonly preamble =
|
|
34
|
-
readonly clientFeature = Host.AidaClient.ClientFeature.
|
|
60
|
+
readonly preamble = preamble;
|
|
61
|
+
readonly clientFeature = Host.AidaClient.ClientFeature.CHROME_DEVTOOLS_V2_AGENT;
|
|
35
62
|
readonly userTier = 'TESTERS';
|
|
36
63
|
|
|
37
64
|
#skillsInjected = false;
|
|
@@ -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
|
|
29
|
-
import {NetworkAgent
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
17
|
-
- `getTitle()
|
|
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
|
-
|
|
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
|
|
|
@@ -102,3 +104,12 @@ To aid debugging, you can enable the AI Assistance logging. This setting is stor
|
|
|
102
104
|
4. In the console, run `setDebugAiAssistanceEnabled(true)`.
|
|
103
105
|
|
|
104
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.
|
|
@@ -15,6 +15,8 @@ import type * as Trace from '../../trace/trace.js';
|
|
|
15
15
|
import * as Workspace from '../../workspace/workspace.js';
|
|
16
16
|
import {isOpaqueOrigin} from '../AiOrigins.js';
|
|
17
17
|
import {DOMNodeContext} from '../contexts/DOMNodeContext.js';
|
|
18
|
+
import {FileContext} from '../contexts/FileContext.js';
|
|
19
|
+
import {getRequestContextOrigin, RequestContext} from '../contexts/RequestContext.js';
|
|
18
20
|
import {debugLog} from '../debug.js';
|
|
19
21
|
import {StorageItem} from '../StorageItem.js';
|
|
20
22
|
|
|
@@ -26,8 +28,6 @@ import {
|
|
|
26
28
|
type ContextResponse,
|
|
27
29
|
type RequestOptions,
|
|
28
30
|
} from './AiAgent.js';
|
|
29
|
-
import {FileContext} from './FileAgent.js';
|
|
30
|
-
import {getRequestContextOrigin, RequestContext} from './NetworkAgent.js';
|
|
31
31
|
import {PerformanceTraceContext} from './PerformanceAgent.js';
|
|
32
32
|
import {StorageContext} from './StorageAgent.js';
|
|
33
33
|
|
|
@@ -5,13 +5,11 @@
|
|
|
5
5
|
import * as Host from '../../../core/host/host.js';
|
|
6
6
|
import * as Root from '../../../core/root/root.js';
|
|
7
7
|
import type * as Workspace from '../../workspace/workspace.js';
|
|
8
|
-
import {FileFormatter} from '../data_formatters/FileFormatter.js';
|
|
9
8
|
|
|
10
9
|
import {
|
|
11
10
|
AiAgent,
|
|
12
|
-
type ContextDetail,
|
|
13
11
|
type ContextResponse,
|
|
14
|
-
ConversationContext,
|
|
12
|
+
type ConversationContext,
|
|
15
13
|
type RequestOptions,
|
|
16
14
|
ResponseType,
|
|
17
15
|
} from './AiAgent.js';
|
|
@@ -75,31 +73,6 @@ External Resources:
|
|
|
75
73
|
MDN Web Docs: JavaScript Functions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
|
|
76
74
|
`;
|
|
77
75
|
|
|
78
|
-
export class FileContext extends ConversationContext<Workspace.UISourceCode.UISourceCode> {
|
|
79
|
-
#file: Workspace.UISourceCode.UISourceCode;
|
|
80
|
-
|
|
81
|
-
constructor(file: Workspace.UISourceCode.UISourceCode) {
|
|
82
|
-
super();
|
|
83
|
-
this.#file = file;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
override getURL(): string {
|
|
87
|
-
return this.#file.url();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
override getItem(): Workspace.UISourceCode.UISourceCode {
|
|
91
|
-
return this.#file;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
override getTitle(): string {
|
|
95
|
-
return this.#file.displayName();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
override async refresh(): Promise<void> {
|
|
99
|
-
await this.#file.requestContentData();
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
76
|
/**
|
|
104
77
|
* One agent instance handles one conversation. Create a new agent
|
|
105
78
|
* instance for a new conversation.
|
|
@@ -126,27 +99,21 @@ export class FileAgent extends AiAgent<Workspace.UISourceCode.UISourceCode> {
|
|
|
126
99
|
return;
|
|
127
100
|
}
|
|
128
101
|
|
|
102
|
+
const details = await selectedFile.getUserFacingDetails();
|
|
103
|
+
if (!details) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
129
107
|
yield {
|
|
130
108
|
type: ResponseType.CONTEXT,
|
|
131
|
-
details
|
|
109
|
+
details,
|
|
132
110
|
};
|
|
133
111
|
}
|
|
134
112
|
|
|
135
113
|
override async enhanceQuery(
|
|
136
114
|
query: string, selectedFile: ConversationContext<Workspace.UISourceCode.UISourceCode>|null): Promise<string> {
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
'';
|
|
115
|
+
const promptDetails = selectedFile ? await selectedFile.getPromptDetails() : null;
|
|
116
|
+
const fileEnchantmentQuery = promptDetails ? `${promptDetails}\n\n# User request\n\n` : '';
|
|
140
117
|
return `${fileEnchantmentQuery}${query}`;
|
|
141
118
|
}
|
|
142
119
|
}
|
|
143
|
-
|
|
144
|
-
function createContextDetailsForFileAgent(selectedFile: ConversationContext<Workspace.UISourceCode.UISourceCode>):
|
|
145
|
-
[ContextDetail, ...ContextDetail[]] {
|
|
146
|
-
return [
|
|
147
|
-
{
|
|
148
|
-
title: 'Selected file',
|
|
149
|
-
text: new FileFormatter(selectedFile.getItem()).formatFile(),
|
|
150
|
-
},
|
|
151
|
-
];
|
|
152
|
-
}
|
|
@@ -10,7 +10,7 @@ Content:
|
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
"title": "Response",
|
|
13
|
-
"text": "Response headers:\ncontent-type: bar2\nx-forwarded-for: bar3\n\nResponse body:\n{\"request\":\"body\"}\n\nResponse status: 200
|
|
13
|
+
"text": "Response headers:\ncontent-type: bar2\nx-forwarded-for: bar3\n\nResponse body:\n{\"request\":\"body\"}\n\nResponse status: 200\nNetwork request status: pending\n"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"title": "Timing",
|
|
@@ -59,7 +59,7 @@ Content:
|
|
|
59
59
|
{
|
|
60
60
|
"parts": [
|
|
61
61
|
{
|
|
62
|
-
"text": "# Selected network request
|
|
62
|
+
"text": "# Selected network request\nRequest: https://www.example.com\n\nRequest headers:\ncontent-type: bar1\n\nResponse headers:\ncontent-type: bar2\nx-forwarded-for: bar3\n\nResponse body:\n{\"request\":\"body\"}\n\nResponse status: 200\nNetwork request status: pending\n\nRequest timing:\nQueued at (timestamp): 0 s\nStarted at (timestamp): 501 s\nQueueing (duration): 501 s\nConnection start (stalled) (duration): 800 ms\nRequest sent (duration): 100 ms\nDuration (duration): 501 s\n\nRequest initiator chain:\n- URL: <redacted cross-origin initiator URL>\n\t- URL: https://www.example.com\n\t\t- URL: https://www.example.com/1\n\t\t- URL: https://www.example.com/2\n\n# User request\n\ntest"
|
|
63
63
|
}
|
|
64
64
|
],
|
|
65
65
|
"role": 1
|