chrome-devtools-frontend 1.0.1611825 → 1.0.1613625
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/verification/SKILL.md +5 -1
- package/front_end/Images/src/flowsheet.svg +1 -0
- package/front_end/core/common/Color.ts +3 -2
- package/front_end/core/common/MapWithDefault.ts +2 -2
- package/front_end/core/common/Object.ts +9 -6
- package/front_end/core/platform/StringUtilities.ts +5 -0
- package/front_end/core/sdk/NetworkManager.ts +7 -0
- package/front_end/generated/InspectorBackendCommands.ts +2 -2
- package/front_end/generated/protocol.ts +12 -2
- package/front_end/models/ai_assistance/agents/README.md +77 -0
- package/front_end/models/greendev/Prototypes.ts +7 -4
- package/front_end/models/har/HARFormat.ts +30 -0
- package/front_end/models/har/Importer.ts +12 -1
- package/front_end/models/har/Log.ts +28 -0
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +6 -4
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +62 -22
- package/front_end/panels/ai_assistance/PatchWidget.ts +7 -23
- package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +3 -3
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +7 -0
- package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +13 -3
- package/front_end/panels/ai_assistance/components/ChatView.ts +4 -0
- package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +14 -7
- package/front_end/panels/ai_assistance/components/OptInChangeDialog.ts +179 -0
- package/front_end/panels/ai_assistance/components/WalkthroughView.ts +4 -3
- package/front_end/panels/ai_assistance/components/optInChangeDialog.css +95 -0
- package/front_end/panels/ai_assistance/components/walkthroughView.css +1 -1
- package/front_end/panels/application/CookieItemsView.ts +3 -2
- package/front_end/panels/changes/ChangesView.ts +0 -12
- package/front_end/panels/common/common.ts +0 -1
- package/front_end/panels/console/ConsolePrompt.ts +2 -2
- package/front_end/panels/elements/StylePropertyTreeElement.ts +2 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +6 -2
- package/front_end/panels/elements/elements-meta.ts +14 -0
- package/front_end/panels/emulation/DeviceModeToolbar.ts +13 -4
- package/front_end/panels/network/NetworkLogView.ts +58 -28
- package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +1 -1
- package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +9 -17
- package/front_end/panels/protocol_monitor/JSONEditor.ts +30 -4
- package/front_end/panels/recorder/RecorderController.ts +4 -4
- package/front_end/panels/recorder/models/RecordingPlayer.ts +1 -1
- package/front_end/panels/settings/AISettingsTab.ts +53 -6
- package/front_end/panels/settings/SettingsScreen.ts +2 -2
- package/front_end/services/puppeteer/PuppeteerConnection.ts +1 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/kit/icons/Icon.ts +1 -0
- package/front_end/ui/legacy/SplitWidget.ts +9 -6
- package/front_end/ui/legacy/TextPrompt.ts +1 -1
- package/front_end/ui/legacy/Treeoutline.ts +3 -2
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +4 -3
- package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +3 -3
- package/front_end/ui/legacy/components/source_frame/FontView.ts +101 -88
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +4 -4
- package/front_end/ui/visual_logging/KnownContextValues.ts +13 -0
- package/package.json +2 -2
- package/front_end/panels/common/CopyChangesToPrompt.ts +0 -233
|
@@ -25,9 +25,13 @@ description: MANDATORY: Activate this skill ANY TIME you need to build the proje
|
|
|
25
25
|
- `npm run lint` will execute ESLint and StyleLint. It will report any violations and automatically fix them where possible.
|
|
26
26
|
- To run the linter on a specific file or directory, you can run `npm run lint -- <PATH>` where `PATH` is a path to a file or directory. This will also automatically fix violations where possible.
|
|
27
27
|
|
|
28
|
+
## Presubmit
|
|
29
|
+
|
|
30
|
+
- `git cl presubmit -u` will check if the current change is ready for upload. It will also format and lint the change.
|
|
31
|
+
|
|
28
32
|
## Best practices
|
|
29
33
|
|
|
30
34
|
- Run tests often to verify your changes.
|
|
31
35
|
- Prefer using a fast build, if it exists, to keep the feedback loop shorter.
|
|
32
36
|
- Periodically compile with TypeScript to check for type errors.
|
|
33
|
-
- Run
|
|
37
|
+
- Run `git cl presubmit -u` at the end of your code changes.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 -960 960 960" width="20px" fill="currentColor"><path d="M168-456v192-432V-456Zm383.79 312q15.21 0 25.71-10.29t10.5-25.5q0-15.21-10.29-25.71t-25.5-10.5q-15.21 0-25.71 10.29t-10.5 25.5q0 15.21 10.29 25.71t25.5 10.5Zm240-360q15.21 0 25.71-10.29t10.5-25.5q0-15.21-10.29-25.71t-25.5-10.5q-15.21 0-25.71 10.29t-10.5 25.5q0 15.21 10.29 25.71t25.5 10.5ZM240-528h204v-72H240v72Zm0 168h204v-72H240v72Zm-72 168q-29.7 0-50.85-21.16Q96-234.32 96-264.04v-432.24Q96-726 117.15-747T168-768h624q29.7 0 50.85 21.15Q864-725.7 864-696H168v432h204v72H168Zm307.5 88.52Q444-134.96 444-179.92 444-215 464-243t52-39v-102h240v-54q-32-11-52-38.92t-20-63.05q0-45.03 31.5-76.53T792-648q45 0 76.5 31.48t31.5 76.44Q900-505 880-477t-52 39v126H588v30q32 11 52 38.92t20 63.05q0 45.03-31.5 76.53T552-72q-45 0-76.5-31.48Z"/></svg>
|
|
@@ -684,6 +684,7 @@ export interface Color {
|
|
|
684
684
|
|
|
685
685
|
const EPSILON = 0.01;
|
|
686
686
|
const WIDE_RANGE_EPSILON = 1; // For comparisons on channels with a wider range than [0,1]
|
|
687
|
+
const STRICT_EPSILON = 1e-4;
|
|
687
688
|
function equals(a: number[], b: number[], accuracy?: number): boolean;
|
|
688
689
|
function equals(a: number|null, b: number|null, accuracy?: number): boolean;
|
|
689
690
|
function equals(a: number|null|number[], b: number|null|number[], accuracy = EPSILON): boolean {
|
|
@@ -994,7 +995,7 @@ export class LCH implements Color {
|
|
|
994
995
|
// See "powerless" component definitions in
|
|
995
996
|
// https://www.w3.org/TR/css-color-4/#specifying-lab-lch
|
|
996
997
|
isHuePowerless(): boolean {
|
|
997
|
-
return equals(this.c, 0);
|
|
998
|
+
return equals(this.c, 0, STRICT_EPSILON);
|
|
998
999
|
}
|
|
999
1000
|
static fromSpec(spec: ColorParameterSpec, text: string): LCH|null {
|
|
1000
1001
|
const L = parsePercentage(spec[0], [0, 100]) ?? parseNumber(spec[0]);
|
|
@@ -1592,7 +1593,7 @@ export class HSL implements Color {
|
|
|
1592
1593
|
this.l = clamp(l, {min: 0, max: 1});
|
|
1593
1594
|
s = equals(this.l, 0) || equals(this.l, 1) ? 0 : s;
|
|
1594
1595
|
this.s = clamp(s, {min: 0, max: 1});
|
|
1595
|
-
h = equals(this.s, 0) ? 0 : h;
|
|
1596
|
+
h = equals(this.s, 0, STRICT_EPSILON) ? 0 : h;
|
|
1596
1597
|
this.h = normalizeHue(h * 360) / 360;
|
|
1597
1598
|
this.alpha = clamp(alpha ?? null, {min: 0, max: 1});
|
|
1598
1599
|
this.#authoredText = authoredText;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* TODO: Once the proposal is merged, just replace `MapWithDefault` with `Map` and remove it.
|
|
9
9
|
**/
|
|
10
10
|
export class MapWithDefault<K, V> extends Map<K, V> {
|
|
11
|
-
getOrInsert(key: K, defaultValue: V): V {
|
|
11
|
+
override getOrInsert(key: K, defaultValue: V): V {
|
|
12
12
|
if (!this.has(key)) {
|
|
13
13
|
this.set(key, defaultValue);
|
|
14
14
|
}
|
|
@@ -16,7 +16,7 @@ export class MapWithDefault<K, V> extends Map<K, V> {
|
|
|
16
16
|
return this.get(key) as V;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
getOrInsertComputed(key: K, callbackFunction: (key: K) => V): V {
|
|
19
|
+
override getOrInsertComputed(key: K, callbackFunction: (key: K) => V): V {
|
|
20
20
|
if (!this.has(key)) {
|
|
21
21
|
this.set(key, callbackFunction(key));
|
|
22
22
|
}
|
|
@@ -119,31 +119,34 @@ export class ObjectWrapper<Events> implements EventTarget<Events> {
|
|
|
119
119
|
export function eventMixin<Events, Base extends Platform.Constructor.Constructor<object>>(base: Base) {
|
|
120
120
|
console.assert(base !== HTMLElement);
|
|
121
121
|
return class EventHandling extends base implements EventTarget<Events> {
|
|
122
|
-
|
|
122
|
+
// Note that the weird name is due to TSC disallowing private/protected fields in
|
|
123
|
+
// anonmous exported classes. We use a `__` prefix to prevent clashes with `base`.
|
|
124
|
+
// eslint-disable-next-line @devtools/no-underscored-properties, @typescript-eslint/naming-convention
|
|
125
|
+
__events = new ObjectWrapper<Events>();
|
|
123
126
|
|
|
124
127
|
addEventListener<T extends keyof Events>(
|
|
125
128
|
eventType: T, listener: (arg0: EventTargetEvent<Events[T]>) => void,
|
|
126
129
|
thisObject?: Object): EventDescriptor<Events, T> {
|
|
127
|
-
return this
|
|
130
|
+
return this.__events.addEventListener(eventType, listener, thisObject);
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
once<T extends keyof Events>(eventType: T): Promise<Events[T]> {
|
|
131
|
-
return this
|
|
134
|
+
return this.__events.once(eventType);
|
|
132
135
|
}
|
|
133
136
|
|
|
134
137
|
removeEventListener<T extends keyof Events>(
|
|
135
138
|
eventType: T, listener: (arg0: EventTargetEvent<Events[T]>) => void, thisObject?: Object): void {
|
|
136
|
-
this
|
|
139
|
+
this.__events.removeEventListener(eventType, listener, thisObject);
|
|
137
140
|
}
|
|
138
141
|
|
|
139
142
|
hasEventListeners(eventType: keyof Events): boolean {
|
|
140
|
-
return this
|
|
143
|
+
return this.__events.hasEventListeners(eventType);
|
|
141
144
|
}
|
|
142
145
|
|
|
143
146
|
dispatchEventToListeners<T extends keyof Events>(
|
|
144
147
|
eventType: Platform.TypeScriptUtilities.NoUnion<T>,
|
|
145
148
|
...eventData: EventPayloadToRestParameters<Events, T>): void {
|
|
146
|
-
this
|
|
149
|
+
this.__events.dispatchEventToListeners(eventType, ...eventData);
|
|
147
150
|
}
|
|
148
151
|
};
|
|
149
152
|
}
|
|
@@ -276,6 +276,7 @@ export const removeURLFragment = (inputStr: string): string => {
|
|
|
276
276
|
};
|
|
277
277
|
|
|
278
278
|
const SPECIAL_REGEX_CHARACTERS = '^[]{}()\\.^$*+?|-,';
|
|
279
|
+
const SPECIAL_URL_PATTERN_CHARACTERS = '?+*(){}\\:';
|
|
279
280
|
|
|
280
281
|
export const regexSpecialCharacters = function(): string {
|
|
281
282
|
return SPECIAL_REGEX_CHARACTERS;
|
|
@@ -450,6 +451,10 @@ export const escapeForRegExp = (str: string): string => {
|
|
|
450
451
|
return escapeCharacters(str, SPECIAL_REGEX_CHARACTERS);
|
|
451
452
|
};
|
|
452
453
|
|
|
454
|
+
export const escapeForURLPattern = (text: string): string => {
|
|
455
|
+
return escapeCharacters(text, SPECIAL_URL_PATTERN_CHARACTERS);
|
|
456
|
+
};
|
|
457
|
+
|
|
453
458
|
export const naturalOrderComparator = (a: string, b: string): number => {
|
|
454
459
|
const chunk = /^\d+|^\D+/;
|
|
455
460
|
let chunkA, chunkB, numA, numB;
|
|
@@ -32,6 +32,10 @@ const UIStrings = {
|
|
|
32
32
|
* @description Explanation why no content is shown for WebSocket connection.
|
|
33
33
|
*/
|
|
34
34
|
noContentForWebSocket: 'Content for WebSockets is currently not supported',
|
|
35
|
+
/**
|
|
36
|
+
* @description Explanation why no content is shown for Server-Sent Events (SSE).
|
|
37
|
+
*/
|
|
38
|
+
noContentForSSE: 'Content for Server-Sent Events (SSE) is currently not supported',
|
|
35
39
|
/**
|
|
36
40
|
* @description Explanation why no content is shown for redirect response.
|
|
37
41
|
*/
|
|
@@ -215,6 +219,9 @@ export class NetworkManager extends SDKModel<EventTypes> {
|
|
|
215
219
|
return {error: i18nString(UIStrings.noContentForWebSocket)};
|
|
216
220
|
}
|
|
217
221
|
if (!request.finished) {
|
|
222
|
+
if (Boolean(request.eventSourceMessages()?.length)) {
|
|
223
|
+
return {error: i18nString(UIStrings.noContentForSSE)};
|
|
224
|
+
}
|
|
218
225
|
await request.once(NetworkRequestEvents.FINISHED_LOADING);
|
|
219
226
|
}
|
|
220
227
|
if (request.isRedirect()) {
|
|
@@ -867,7 +867,7 @@ inspectorBackend.registerCommand("Network.continueInterceptedRequest", [{"name":
|
|
|
867
867
|
inspectorBackend.registerCommand("Network.deleteCookies", [{"name": "name", "type": "string", "optional": false, "description": "Name of the cookies to remove.", "typeRef": null}, {"name": "url", "type": "string", "optional": true, "description": "If specified, deletes all the cookies with the given name where domain and path match provided URL.", "typeRef": null}, {"name": "domain", "type": "string", "optional": true, "description": "If specified, deletes only cookies with the exact domain.", "typeRef": null}, {"name": "path", "type": "string", "optional": true, "description": "If specified, deletes only cookies with the exact path.", "typeRef": null}, {"name": "partitionKey", "type": "object", "optional": true, "description": "If specified, deletes only cookies with the the given name and partitionKey where all partition key attributes match the cookie partition key attribute.", "typeRef": "Network.CookiePartitionKey"}], [], "Deletes browser cookies with matching name and url or domain/path/partitionKey pair.");
|
|
868
868
|
inspectorBackend.registerCommand("Network.disable", [], [], "Disables network tracking, prevents network events from being sent to the client.");
|
|
869
869
|
inspectorBackend.registerCommand("Network.emulateNetworkConditions", [{"name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null}, {"name": "latency", "type": "number", "optional": false, "description": "Minimum latency from request sent to response headers received (ms).", "typeRef": null}, {"name": "downloadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.", "typeRef": null}, {"name": "uploadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.", "typeRef": null}, {"name": "connectionType", "type": "string", "optional": true, "description": "Connection type if known.", "typeRef": "Network.ConnectionType"}, {"name": "packetLoss", "type": "number", "optional": true, "description": "WebRTC packet loss (percent, 0-100). 0 disables packet loss emulation, 100 drops all the packets.", "typeRef": null}, {"name": "packetQueueLength", "type": "number", "optional": true, "description": "WebRTC packet queue length (packet). 0 removes any queue length limitations.", "typeRef": null}, {"name": "packetReordering", "type": "boolean", "optional": true, "description": "WebRTC packetReordering feature.", "typeRef": null}], [], "Activates emulation of network conditions. This command is deprecated in favor of the emulateNetworkConditionsByRule and overrideNetworkState commands, which can be used together to the same effect.");
|
|
870
|
-
inspectorBackend.registerCommand("Network.emulateNetworkConditionsByRule", [{"name": "offline", "type": "boolean", "optional":
|
|
870
|
+
inspectorBackend.registerCommand("Network.emulateNetworkConditionsByRule", [{"name": "offline", "type": "boolean", "optional": true, "description": "True to emulate internet disconnection. Deprecated, use the offline property in matchedNetworkConditions or emulateOfflineServiceWorker instead.", "typeRef": null}, {"name": "emulateOfflineServiceWorker", "type": "boolean", "optional": true, "description": "True to emulate offline service worker.", "typeRef": null}, {"name": "matchedNetworkConditions", "type": "array", "optional": false, "description": "Configure conditions for matching requests. If multiple entries match a request, the first entry wins. Global conditions can be configured by leaving the urlPattern for the conditions empty. These global conditions are also applied for throttling of p2p connections.", "typeRef": "Network.NetworkConditions"}], ["ruleIds"], "Activates emulation of network conditions for individual requests using URL match patterns. Unlike the deprecated Network.emulateNetworkConditions this method does not affect `navigator` state. Use Network.overrideNetworkState to explicitly modify `navigator` behavior.");
|
|
871
871
|
inspectorBackend.registerCommand("Network.overrideNetworkState", [{"name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null}, {"name": "latency", "type": "number", "optional": false, "description": "Minimum latency from request sent to response headers received (ms).", "typeRef": null}, {"name": "downloadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.", "typeRef": null}, {"name": "uploadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.", "typeRef": null}, {"name": "connectionType", "type": "string", "optional": true, "description": "Connection type if known.", "typeRef": "Network.ConnectionType"}], [], "Override the state of navigator.onLine and navigator.connection.");
|
|
872
872
|
inspectorBackend.registerCommand("Network.enable", [{"name": "maxTotalBufferSize", "type": "number", "optional": true, "description": "Buffer size in bytes to use when preserving network payloads (XHRs, etc). This is the maximum number of bytes that will be collected by this DevTools session.", "typeRef": null}, {"name": "maxResourceBufferSize", "type": "number", "optional": true, "description": "Per-resource buffer size in bytes to use when preserving network payloads (XHRs, etc).", "typeRef": null}, {"name": "maxPostDataSize", "type": "number", "optional": true, "description": "Longest post body size (in bytes) that would be included in requestWillBeSent notification", "typeRef": null}, {"name": "reportDirectSocketTraffic", "type": "boolean", "optional": true, "description": "Whether DirectSocket chunk send/receive events should be reported.", "typeRef": null}, {"name": "enableDurableMessages", "type": "boolean", "optional": true, "description": "Enable storing response bodies outside of renderer, so that these survive a cross-process navigation. Requires maxTotalBufferSize to be set. Currently defaults to false. This field is being deprecated in favor of the dedicated configureDurableMessages command, due to the possibility of deadlocks when awaiting Network.enable before issuing Runtime.runIfWaitingForDebugger.", "typeRef": null}], [], "Enables network tracking, network events will now be delivered to the client.");
|
|
873
873
|
inspectorBackend.registerCommand("Network.configureDurableMessages", [{"name": "maxTotalBufferSize", "type": "number", "optional": true, "description": "Buffer size in bytes to use when preserving network payloads (XHRs, etc).", "typeRef": null}, {"name": "maxResourceBufferSize", "type": "number", "optional": true, "description": "Per-resource buffer size in bytes to use when preserving network payloads (XHRs, etc).", "typeRef": null}], [], "Configures storing response bodies outside of renderer, so that these survive a cross-process navigation. If maxTotalBufferSize is not set, durable messages are disabled.");
|
|
@@ -923,7 +923,7 @@ inspectorBackend.registerType("Network.SignedExchangeSignature", [{"name": "labe
|
|
|
923
923
|
inspectorBackend.registerType("Network.SignedExchangeHeader", [{"name": "requestUrl", "type": "string", "optional": false, "description": "Signed exchange request URL.", "typeRef": null}, {"name": "responseCode", "type": "number", "optional": false, "description": "Signed exchange response code.", "typeRef": null}, {"name": "responseHeaders", "type": "object", "optional": false, "description": "Signed exchange response headers.", "typeRef": "Network.Headers"}, {"name": "signatures", "type": "array", "optional": false, "description": "Signed exchange response signature.", "typeRef": "Network.SignedExchangeSignature"}, {"name": "headerIntegrity", "type": "string", "optional": false, "description": "Signed exchange header integrity hash in the form of `sha256-<base64-hash-value>`.", "typeRef": null}]);
|
|
924
924
|
inspectorBackend.registerType("Network.SignedExchangeError", [{"name": "message", "type": "string", "optional": false, "description": "Error message.", "typeRef": null}, {"name": "signatureIndex", "type": "number", "optional": true, "description": "The index of the signature which caused the error.", "typeRef": null}, {"name": "errorField", "type": "string", "optional": true, "description": "The field which caused the error.", "typeRef": "Network.SignedExchangeErrorField"}]);
|
|
925
925
|
inspectorBackend.registerType("Network.SignedExchangeInfo", [{"name": "outerResponse", "type": "object", "optional": false, "description": "The outer response of signed HTTP exchange which was received from network.", "typeRef": "Network.Response"}, {"name": "hasExtraInfo", "type": "boolean", "optional": false, "description": "Whether network response for the signed exchange was accompanied by extra headers.", "typeRef": null}, {"name": "header", "type": "object", "optional": true, "description": "Information about the signed exchange header.", "typeRef": "Network.SignedExchangeHeader"}, {"name": "securityDetails", "type": "object", "optional": true, "description": "Security details for the signed exchange header.", "typeRef": "Network.SecurityDetails"}, {"name": "errors", "type": "array", "optional": true, "description": "Errors occurred while handling the signed exchange.", "typeRef": "Network.SignedExchangeError"}]);
|
|
926
|
-
inspectorBackend.registerType("Network.NetworkConditions", [{"name": "urlPattern", "type": "string", "optional": false, "description": "Only matching requests will be affected by these conditions. Patterns use the URLPattern constructor string syntax (https://urlpattern.spec.whatwg.org/) and must be absolute. If the pattern is empty, all requests are matched (including p2p connections).", "typeRef": null}, {"name": "latency", "type": "number", "optional": false, "description": "Minimum latency from request sent to response headers received (ms).", "typeRef": null}, {"name": "downloadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.", "typeRef": null}, {"name": "uploadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.", "typeRef": null}, {"name": "connectionType", "type": "string", "optional": true, "description": "Connection type if known.", "typeRef": "Network.ConnectionType"}, {"name": "packetLoss", "type": "number", "optional": true, "description": "WebRTC packet loss (percent, 0-100). 0 disables packet loss emulation, 100 drops all the packets.", "typeRef": null}, {"name": "packetQueueLength", "type": "number", "optional": true, "description": "WebRTC packet queue length (packet). 0 removes any queue length limitations.", "typeRef": null}, {"name": "packetReordering", "type": "boolean", "optional": true, "description": "WebRTC packetReordering feature.", "typeRef": null}]);
|
|
926
|
+
inspectorBackend.registerType("Network.NetworkConditions", [{"name": "urlPattern", "type": "string", "optional": false, "description": "Only matching requests will be affected by these conditions. Patterns use the URLPattern constructor string syntax (https://urlpattern.spec.whatwg.org/) and must be absolute. If the pattern is empty, all requests are matched (including p2p connections).", "typeRef": null}, {"name": "latency", "type": "number", "optional": false, "description": "Minimum latency from request sent to response headers received (ms).", "typeRef": null}, {"name": "downloadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.", "typeRef": null}, {"name": "uploadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.", "typeRef": null}, {"name": "connectionType", "type": "string", "optional": true, "description": "Connection type if known.", "typeRef": "Network.ConnectionType"}, {"name": "packetLoss", "type": "number", "optional": true, "description": "WebRTC packet loss (percent, 0-100). 0 disables packet loss emulation, 100 drops all the packets.", "typeRef": null}, {"name": "packetQueueLength", "type": "number", "optional": true, "description": "WebRTC packet queue length (packet). 0 removes any queue length limitations.", "typeRef": null}, {"name": "packetReordering", "type": "boolean", "optional": true, "description": "WebRTC packetReordering feature.", "typeRef": null}, {"name": "offline", "type": "boolean", "optional": true, "description": "True to emulate internet disconnection.", "typeRef": null}]);
|
|
927
927
|
inspectorBackend.registerType("Network.BlockPattern", [{"name": "urlPattern", "type": "string", "optional": false, "description": "URL pattern to match. Patterns use the URLPattern constructor string syntax (https://urlpattern.spec.whatwg.org/) and must be absolute. Example: `*://*:*/*.css`.", "typeRef": null}, {"name": "block", "type": "boolean", "optional": false, "description": "Whether or not to block the pattern. If false, a matching request will not be blocked even if it matches a later `BlockPattern`.", "typeRef": null}]);
|
|
928
928
|
inspectorBackend.registerType("Network.DirectTCPSocketOptions", [{"name": "noDelay", "type": "boolean", "optional": false, "description": "TCP_NODELAY option", "typeRef": null}, {"name": "keepAliveDelay", "type": "number", "optional": true, "description": "Expected to be unsigned integer.", "typeRef": null}, {"name": "sendBufferSize", "type": "number", "optional": true, "description": "Expected to be unsigned integer.", "typeRef": null}, {"name": "receiveBufferSize", "type": "number", "optional": true, "description": "Expected to be unsigned integer.", "typeRef": null}, {"name": "dnsQueryType", "type": "string", "optional": true, "description": "", "typeRef": "Network.DirectSocketDnsQueryType"}]);
|
|
929
929
|
inspectorBackend.registerType("Network.DirectUDPSocketOptions", [{"name": "remoteAddr", "type": "string", "optional": true, "description": "", "typeRef": null}, {"name": "remotePort", "type": "number", "optional": true, "description": "Unsigned int 16.", "typeRef": null}, {"name": "localAddr", "type": "string", "optional": true, "description": "", "typeRef": null}, {"name": "localPort", "type": "number", "optional": true, "description": "Unsigned int 16.", "typeRef": null}, {"name": "dnsQueryType", "type": "string", "optional": true, "description": "", "typeRef": "Network.DirectSocketDnsQueryType"}, {"name": "sendBufferSize", "type": "number", "optional": true, "description": "Expected to be unsigned integer.", "typeRef": null}, {"name": "receiveBufferSize", "type": "number", "optional": true, "description": "Expected to be unsigned integer.", "typeRef": null}, {"name": "multicastLoopback", "type": "boolean", "optional": true, "description": "", "typeRef": null}, {"name": "multicastTimeToLive", "type": "number", "optional": true, "description": "Unsigned int 8.", "typeRef": null}, {"name": "multicastAllowAddressSharing", "type": "boolean", "optional": true, "description": "", "typeRef": null}]);
|
|
@@ -11376,6 +11376,10 @@ export namespace Network {
|
|
|
11376
11376
|
* WebRTC packetReordering feature.
|
|
11377
11377
|
*/
|
|
11378
11378
|
packetReordering?: boolean;
|
|
11379
|
+
/**
|
|
11380
|
+
* True to emulate internet disconnection.
|
|
11381
|
+
*/
|
|
11382
|
+
offline?: boolean;
|
|
11379
11383
|
}
|
|
11380
11384
|
|
|
11381
11385
|
export interface BlockPattern {
|
|
@@ -12154,9 +12158,15 @@ export namespace Network {
|
|
|
12154
12158
|
|
|
12155
12159
|
export interface EmulateNetworkConditionsByRuleRequest {
|
|
12156
12160
|
/**
|
|
12157
|
-
* True to emulate internet disconnection.
|
|
12161
|
+
* True to emulate internet disconnection. Deprecated, use the offline property in matchedNetworkConditions
|
|
12162
|
+
* or emulateOfflineServiceWorker instead.
|
|
12163
|
+
* @deprecated
|
|
12158
12164
|
*/
|
|
12159
|
-
offline
|
|
12165
|
+
offline?: boolean;
|
|
12166
|
+
/**
|
|
12167
|
+
* True to emulate offline service worker.
|
|
12168
|
+
*/
|
|
12169
|
+
emulateOfflineServiceWorker?: boolean;
|
|
12160
12170
|
/**
|
|
12161
12171
|
* Configure conditions for matching requests. If multiple entries match a request, the first entry wins. Global
|
|
12162
12172
|
* conditions can be configured by leaving the urlPattern for the conditions empty. These global conditions are
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# AI Agents
|
|
2
|
+
|
|
3
|
+
This directory contains the implementations of various AI agents used in the AI Assistance panel in Chrome DevTools.
|
|
4
|
+
|
|
5
|
+
## Performance Agent
|
|
6
|
+
|
|
7
|
+
The `PerformanceAgent` analyzes performance traces. This documentation details the specific data provided to the agent and the data it can retrieve via functions.
|
|
8
|
+
|
|
9
|
+
### Initial Data Provided to the Agent
|
|
10
|
+
|
|
11
|
+
When a conversation starts or the context changes, the agent is provided with a set of "facts" and query enhancements. This data forms the agent's base knowledge about the trace.
|
|
12
|
+
|
|
13
|
+
#### Trace Facts (Initial Context)
|
|
14
|
+
|
|
15
|
+
Facts are text-based data summaries injected into the conversation. The agent receives:
|
|
16
|
+
|
|
17
|
+
- **Data Schema Descriptions**: Text explaining the format of call frame and network data to help the agent interpret subsequent tool outputs.
|
|
18
|
+
- **Environment State**: Flags indicating if the trace is a fresh recording or loaded from an external file.
|
|
19
|
+
- **Trace Summary Data**: A text summary containing key performance metrics (LCP, INP, CLS) and basic trace metadata.
|
|
20
|
+
- **Critical Requests Data**: A text list of the most critical network requests identified in the trace.
|
|
21
|
+
- **Main Thread Activity Data**: A bottom-up aggregated summary of where time was spent on the main thread.
|
|
22
|
+
- **Longest Tasks Data**: A list of the longest tasks found on the main thread.
|
|
23
|
+
- **Third Party Activity Data**: A summary of time spent on third-party scripts.
|
|
24
|
+
|
|
25
|
+
#### Context Selection (Additional initial context)
|
|
26
|
+
|
|
27
|
+
The agent receives additional initial context based on the user's context selection. The context can be a Trace, an Insight, or a specific Event:
|
|
28
|
+
|
|
29
|
+
- **Trace Context**: No additional context is added beyond the base trace facts.
|
|
30
|
+
- **Insight Context**: The agent receives the name and key of the specific performance insight selected.
|
|
31
|
+
- **Event Context**: The agent receives the serialized details of the specific trace event selected.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Data Retrieval Functions (Tools)
|
|
35
|
+
|
|
36
|
+
The agent can request additional data by calling functions. Here is the data the agent receives from each function:
|
|
37
|
+
|
|
38
|
+
#### `getInsightDetails`
|
|
39
|
+
- **Arguments**: `insightSetId` (string), `insightName` (string)
|
|
40
|
+
- **Data Returned to Agent**: A detailed text representation of the specific insight (e.g., LCP breakdown components, render-blocking resource URLs).
|
|
41
|
+
|
|
42
|
+
#### `getEventByKey`
|
|
43
|
+
- **Arguments**: `eventKey` (string)
|
|
44
|
+
- **Data Returned to Agent**: The full JSON representation of the specific trace event.
|
|
45
|
+
|
|
46
|
+
#### `getMainThreadTrackSummary`
|
|
47
|
+
- **Arguments**: `min` (integer, optional), `max` (integer, optional)
|
|
48
|
+
- **Data Returned to Agent**: A comprehensive text summary of main thread activity *within the specified bounds*.
|
|
49
|
+
- **Note**: This differs from the initial "Main Thread Activity Data" fact as it is scoped to the provided time range and includes significantly more data: a **top-down tree**, a **bottom-up tree**, a **third-parties summary**, and a list of **related insights** for events in that range.
|
|
50
|
+
|
|
51
|
+
#### `getNetworkTrackSummary`
|
|
52
|
+
- **Arguments**: `min` (integer, optional), `max` (integer, optional)
|
|
53
|
+
- **Data Returned to Agent**: A text summary of network requests and activity within the bounds.
|
|
54
|
+
|
|
55
|
+
#### `getDetailedCallTree`
|
|
56
|
+
- **Arguments**: `eventKey` (string)
|
|
57
|
+
- **Data Returned to Agent**: A detailed call tree representation for the specified event.
|
|
58
|
+
|
|
59
|
+
#### `addElementAnnotation`
|
|
60
|
+
- **Arguments**: `elementId` (string), `annotationMessage` (string)
|
|
61
|
+
- **Data Returned to Agent**: Confirmation of success or an error message. (Note: This function also modifies the DevTools UI by adding a visual annotation).
|
|
62
|
+
|
|
63
|
+
#### `addNetworkRequestAnnotation`
|
|
64
|
+
- **Arguments**: `eventKey` (string), `annotationMessage` (string)
|
|
65
|
+
- **Data Returned to Agent**: Confirmation of success or an error message. (Note: This function also modifies the DevTools UI by adding a visual annotation).
|
|
66
|
+
|
|
67
|
+
#### `getFunctionCode`
|
|
68
|
+
- **Arguments**: `scriptUrl` (string), `line` (integer), `column` (integer)
|
|
69
|
+
- **Data Returned to Agent**: The source code lines for the function, annotated with performance cost per line if available.
|
|
70
|
+
|
|
71
|
+
#### `getResourceContent`
|
|
72
|
+
- **Arguments**: `url` (string)
|
|
73
|
+
- **Data Returned to Agent**: The full text content of the specified resource (e.g., script file).
|
|
74
|
+
|
|
75
|
+
#### `selectEventByKey`
|
|
76
|
+
- **Arguments**: `eventKey` (string)
|
|
77
|
+
- **Data Returned to Agent**: Confirmation of success or an error message. (Note: This function also modifies the DevTools UI by selecting the event in the flamechart).
|
|
@@ -9,7 +9,7 @@ let instance: Prototypes|null = null;
|
|
|
9
9
|
|
|
10
10
|
export interface GreenDevSettings {
|
|
11
11
|
aiAnnotations: Common.Settings.Setting<boolean>;
|
|
12
|
-
|
|
12
|
+
beyondStyling: Common.Settings.Setting<boolean>;
|
|
13
13
|
breakpointDebuggerAgent: Common.Settings.Setting<boolean>;
|
|
14
14
|
emulationCapabilities: Common.Settings.Setting<boolean>;
|
|
15
15
|
}
|
|
@@ -42,8 +42,11 @@ export class Prototypes {
|
|
|
42
42
|
false,
|
|
43
43
|
Common.Settings.SettingStorageType.LOCAL,
|
|
44
44
|
);
|
|
45
|
-
const
|
|
46
|
-
|
|
45
|
+
const beyondStyling = settings.createSetting(
|
|
46
|
+
'greendev-beyond-styling-enabled',
|
|
47
|
+
false,
|
|
48
|
+
Common.Settings.SettingStorageType.LOCAL,
|
|
49
|
+
);
|
|
47
50
|
const breakpointDebuggerAgent = settings.createSetting(
|
|
48
51
|
'greendev-breakpoint-debugger-agent-enabled',
|
|
49
52
|
false,
|
|
@@ -55,6 +58,6 @@ export class Prototypes {
|
|
|
55
58
|
Common.Settings.SettingStorageType.LOCAL,
|
|
56
59
|
);
|
|
57
60
|
|
|
58
|
-
return {aiAnnotations,
|
|
61
|
+
return {aiAnnotations, beyondStyling, breakpointDebuggerAgent, emulationCapabilities};
|
|
59
62
|
}
|
|
60
63
|
}
|
|
@@ -171,6 +171,7 @@ export class HAREntry extends HARBase {
|
|
|
171
171
|
this.custom.set('initiator', this.importInitiator(data['_initiator']));
|
|
172
172
|
this.custom.set('priority', HARBase.optionalString(data['_priority']));
|
|
173
173
|
this.custom.set('resourceType', HARBase.optionalString(data['_resourceType']));
|
|
174
|
+
this.custom.set('eventSourceMessages', this.#importEventSourceMessages(data['_eventSourceMessages']));
|
|
174
175
|
this.custom.set('webSocketMessages', this.importWebSocketMessages(data['_webSocketMessages']));
|
|
175
176
|
}
|
|
176
177
|
|
|
@@ -196,6 +197,21 @@ export class HAREntry extends HARBase {
|
|
|
196
197
|
}
|
|
197
198
|
return outputMessages;
|
|
198
199
|
}
|
|
200
|
+
|
|
201
|
+
#importEventSourceMessages(inputMessages: any): HAREventSourceMessage[]|undefined {
|
|
202
|
+
if (!Array.isArray(inputMessages)) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const outputMessages = [];
|
|
207
|
+
for (const message of inputMessages) {
|
|
208
|
+
if (typeof message !== 'object') {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
outputMessages.push(new HAREventSourceMessage(message));
|
|
212
|
+
}
|
|
213
|
+
return outputMessages;
|
|
214
|
+
}
|
|
199
215
|
}
|
|
200
216
|
|
|
201
217
|
class HARRequest extends HARBase {
|
|
@@ -480,3 +496,17 @@ class HARWebSocketMessage extends HARBase {
|
|
|
480
496
|
this.type = HARBase.optionalString(data['type']);
|
|
481
497
|
}
|
|
482
498
|
}
|
|
499
|
+
|
|
500
|
+
class HAREventSourceMessage extends HARBase {
|
|
501
|
+
time: number|undefined;
|
|
502
|
+
eventName: string|undefined;
|
|
503
|
+
eventId: string|undefined;
|
|
504
|
+
data: string|undefined;
|
|
505
|
+
constructor(data: any) {
|
|
506
|
+
super(data);
|
|
507
|
+
this.time = HARBase.optionalNumber(data['time']);
|
|
508
|
+
this.eventName = HARBase.optionalString(data['eventName']);
|
|
509
|
+
this.eventId = HARBase.optionalString(data['eventId']);
|
|
510
|
+
this.data = HARBase.optionalString(data['data']);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
@@ -137,7 +137,18 @@ export class Importer {
|
|
|
137
137
|
async () =>
|
|
138
138
|
new TextUtils.ContentData.ContentData(contentText ?? '', isBase64, mimeType ?? '', charset ?? undefined));
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
const importedEventSourceMessages = entry.customAsArray('eventSourceMessages');
|
|
141
|
+
|
|
142
|
+
if (importedEventSourceMessages) {
|
|
143
|
+
for (const message of importedEventSourceMessages) {
|
|
144
|
+
if (message.time === undefined || message.eventName === undefined || message.eventId === undefined) {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
// message.data may be undefined, if saved in a sanitized context
|
|
148
|
+
|
|
149
|
+
request.addEventSourceMessage(message.time, message.eventName, message.eventId, message.data);
|
|
150
|
+
}
|
|
151
|
+
} else if (request.mimeType === Platform.MimeType.MimeType.EVENTSTREAM && contentText) {
|
|
141
152
|
const issueTime = entry.startedDateTime.getTime() / 1000;
|
|
142
153
|
const onEvent = (eventName: string, data: string, eventId: string): void => {
|
|
143
154
|
request.addEventSourceMessage(issueTime, eventName, eventId, data);
|
|
@@ -176,6 +176,26 @@ export class Entry {
|
|
|
176
176
|
delete entry._webSocketMessages;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
const eventSourceMessages = harEntry.request.eventSourceMessages();
|
|
180
|
+
if (eventSourceMessages?.length) {
|
|
181
|
+
const messages = [];
|
|
182
|
+
for (const message of eventSourceMessages) {
|
|
183
|
+
const messageDTO: EventSourceMessageDTO = {
|
|
184
|
+
time: message.time,
|
|
185
|
+
eventName: message.eventName,
|
|
186
|
+
eventId: message.eventId,
|
|
187
|
+
};
|
|
188
|
+
if (!options.sanitize) {
|
|
189
|
+
// Omit the data when sanitizing, as it could contain sensitive information.
|
|
190
|
+
messageDTO.data = message.data;
|
|
191
|
+
}
|
|
192
|
+
messages.push(messageDTO);
|
|
193
|
+
}
|
|
194
|
+
entry._eventSourceMessages = messages;
|
|
195
|
+
} else {
|
|
196
|
+
delete entry._eventSourceMessages;
|
|
197
|
+
}
|
|
198
|
+
|
|
179
199
|
return entry;
|
|
180
200
|
}
|
|
181
201
|
|
|
@@ -490,6 +510,7 @@ export interface EntryDTO {
|
|
|
490
510
|
_priority: Protocol.Network.ResourcePriority|null;
|
|
491
511
|
_resourceType: string;
|
|
492
512
|
_webSocketMessages?: Object[];
|
|
513
|
+
_eventSourceMessages?: EventSourceMessageDTO[];
|
|
493
514
|
cache: Object;
|
|
494
515
|
connection?: string;
|
|
495
516
|
pageref?: string;
|
|
@@ -540,3 +561,10 @@ export interface LogDTO {
|
|
|
540
561
|
pages: Page[];
|
|
541
562
|
entries: EntryDTO[];
|
|
542
563
|
}
|
|
564
|
+
|
|
565
|
+
export interface EventSourceMessageDTO {
|
|
566
|
+
time: number;
|
|
567
|
+
eventName: string;
|
|
568
|
+
eventId: string;
|
|
569
|
+
data?: string;
|
|
570
|
+
}
|
|
@@ -17,13 +17,15 @@ export class HeapSnapshotWorkerProxy extends Common.ObjectWrapper.ObjectWrapper<
|
|
|
17
17
|
readonly previousCallbacks = new Set<number>();
|
|
18
18
|
readonly worker: PlatformApi.HostRuntime.Worker;
|
|
19
19
|
interval?: number;
|
|
20
|
+
readonly workerUrl?: string;
|
|
20
21
|
|
|
21
|
-
constructor(eventHandler: (arg0: string, arg1: string) => void) {
|
|
22
|
+
constructor(eventHandler: (arg0: string, arg1: string) => void, workerUrl?: string) {
|
|
22
23
|
super();
|
|
23
24
|
this.eventHandler = eventHandler;
|
|
25
|
+
this.workerUrl = workerUrl;
|
|
24
26
|
this.worker = Platform.HostRuntime.HOST_RUNTIME.createWorker(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
workerUrl ?? import.meta.resolve('../../entrypoints/heap_snapshot_worker/heap_snapshot_worker-entrypoint.js'),
|
|
28
|
+
);
|
|
27
29
|
this.worker.onmessage = this.messageReceived.bind(this);
|
|
28
30
|
}
|
|
29
31
|
|
|
@@ -236,7 +238,7 @@ export class HeapSnapshotLoaderProxy extends HeapSnapshotProxyObject implements
|
|
|
236
238
|
|
|
237
239
|
async close(): Promise<void> {
|
|
238
240
|
await this.callMethodPromise('close');
|
|
239
|
-
const secondWorker = new HeapSnapshotWorkerProxy(() => {});
|
|
241
|
+
const secondWorker = new HeapSnapshotWorkerProxy(() => {}, this.worker.workerUrl);
|
|
240
242
|
const channel = new MessageChannel();
|
|
241
243
|
await secondWorker.setupForSecondaryInit(channel.port2);
|
|
242
244
|
const snapshotProxy = await this.callFactoryMethodPromise('buildSnapshot', HeapSnapshotProxy, [channel.port1]);
|
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
import {DisabledWidget} from './components/DisabledWidget.js';
|
|
45
45
|
import {ExploreWidget} from './components/ExploreWidget.js';
|
|
46
46
|
import {MarkdownRendererWithCodeBlock} from './components/MarkdownRendererWithCodeBlock.js';
|
|
47
|
+
import {OptInChangeDialog} from './components/OptInChangeDialog.js';
|
|
47
48
|
import {PerformanceAgentMarkdownRenderer} from './components/PerformanceAgentMarkdownRenderer.js';
|
|
48
49
|
import {StylingAgentMarkdownRenderer} from './components/StylingAgentMarkdownRenderer.js';
|
|
49
50
|
import {
|
|
@@ -252,6 +253,16 @@ const UIStringsNotTranslate = {
|
|
|
252
253
|
*/
|
|
253
254
|
inputDisclaimerForAccessibilityEnterpriseNoLogging:
|
|
254
255
|
'Chat messages and the selected Lighthouse report are sent to Google. The content you submit and that is generated by this feature will not be used to improve Google’s AI models. This is an experimental AI feature and won’t always get it right.',
|
|
256
|
+
/**
|
|
257
|
+
* @description Disclaimer text right after the chat input when V2 is enabled.
|
|
258
|
+
*/
|
|
259
|
+
inputDisclaimerV2:
|
|
260
|
+
'Chat messages, data accessible for this site via DevTools panels and Web APIs, and items you select such as network requests, files, and performance traces are sent to Google and may be seen by human reviewers to improve this feature. This is an experimental AI feature and won’t always get it right.',
|
|
261
|
+
/**
|
|
262
|
+
* @description Disclaimer text right after the chat input when V2 is enabled and enterprise logging is off.
|
|
263
|
+
*/
|
|
264
|
+
inputDisclaimerEnterpriseNoLoggingV2:
|
|
265
|
+
'Chat messages, data accessible for this site via DevTools panels and Web APIs, and items you select such as network requests, files, and performance traces are sent to Google. The content submitted to and generated by this feature will not be used to improve Google’s AI models. This is an experimental AI feature and won’t always get it right.',
|
|
255
266
|
} as const;
|
|
256
267
|
|
|
257
268
|
const str_ = i18n.i18n.registerUIStrings('panels/ai_assistance/AiAssistancePanel.ts', UIStrings);
|
|
@@ -779,11 +790,32 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
779
790
|
return await this.#conversationSummaryAgent.summarizeConversation(markdown);
|
|
780
791
|
},
|
|
781
792
|
onTextSubmit: async (
|
|
782
|
-
|
|
783
793
|
text: string, imageInput?: Host.AidaClient.Part,
|
|
784
794
|
multimodalInputType?: AiAssistanceModel.AiAgent.MultimodalInputType) => {
|
|
785
|
-
|
|
786
|
-
|
|
795
|
+
const submit = (): void => {
|
|
796
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiAssistanceQuerySubmitted);
|
|
797
|
+
void this.#startConversation(text, imageInput, multimodalInputType);
|
|
798
|
+
};
|
|
799
|
+
|
|
800
|
+
const isAIV2Enabled = Root.Runtime.hostConfig.devToolsAiAssistanceV2?.enabled;
|
|
801
|
+
const seenSetting =
|
|
802
|
+
Common.Settings.Settings.instance().moduleSetting('ai-assistance-v2-opt-in-change-dialog-seen');
|
|
803
|
+
if (isAIV2Enabled && !seenSetting.get()) {
|
|
804
|
+
OptInChangeDialog.show({
|
|
805
|
+
onGotIt: () => {
|
|
806
|
+
seenSetting.set(true);
|
|
807
|
+
submit();
|
|
808
|
+
},
|
|
809
|
+
onManageSettings: () => {
|
|
810
|
+
seenSetting.set(true);
|
|
811
|
+
this.#viewOutput.chatView?.setInputValue(text);
|
|
812
|
+
void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
|
|
813
|
+
},
|
|
814
|
+
});
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
submit();
|
|
787
819
|
},
|
|
788
820
|
onInspectElementClick: this.#handleSelectElementClick.bind(this),
|
|
789
821
|
onFeedbackSubmit: this.#handleFeedbackSubmit.bind(this),
|
|
@@ -1396,46 +1428,54 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1396
1428
|
return i18nString(UIStrings.inputDisclaimerForEmptyState);
|
|
1397
1429
|
}
|
|
1398
1430
|
|
|
1399
|
-
const
|
|
1431
|
+
const loggingEnabled = Root.Runtime.hostConfig.aidaAvailability?.enterprisePolicyValue !==
|
|
1400
1432
|
Root.Runtime.GenAiEnterprisePolicyValue.ALLOW_WITHOUT_LOGGING;
|
|
1433
|
+
|
|
1434
|
+
if (Root.Runtime.hostConfig.devToolsAiAssistanceV2?.enabled) {
|
|
1435
|
+
if (loggingEnabled) {
|
|
1436
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerV2);
|
|
1437
|
+
}
|
|
1438
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerEnterpriseNoLoggingV2);
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1401
1441
|
switch (this.#conversation.type) {
|
|
1402
1442
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING:
|
|
1403
|
-
if (
|
|
1404
|
-
return lockedString(UIStringsNotTranslate.
|
|
1443
|
+
if (loggingEnabled) {
|
|
1444
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForStyling);
|
|
1405
1445
|
}
|
|
1406
|
-
return lockedString(UIStringsNotTranslate.
|
|
1446
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForStylingEnterpriseNoLogging);
|
|
1407
1447
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.FILE:
|
|
1408
|
-
if (
|
|
1409
|
-
return lockedString(UIStringsNotTranslate.
|
|
1448
|
+
if (loggingEnabled) {
|
|
1449
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForFile);
|
|
1410
1450
|
}
|
|
1411
|
-
return lockedString(UIStringsNotTranslate.
|
|
1451
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForFileEnterpriseNoLogging);
|
|
1412
1452
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.NETWORK:
|
|
1413
|
-
if (
|
|
1414
|
-
return lockedString(UIStringsNotTranslate.
|
|
1453
|
+
if (loggingEnabled) {
|
|
1454
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForNetwork);
|
|
1415
1455
|
}
|
|
1416
|
-
return lockedString(UIStringsNotTranslate.
|
|
1456
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForNetworkEnterpriseNoLogging);
|
|
1417
1457
|
|
|
1418
1458
|
// It is deliberate that both Performance agents use the same disclaimer
|
|
1419
1459
|
// text and this has been approved by Privacy.
|
|
1420
1460
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.PERFORMANCE:
|
|
1421
|
-
if (
|
|
1422
|
-
return lockedString(UIStringsNotTranslate.
|
|
1461
|
+
if (loggingEnabled) {
|
|
1462
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForPerformance);
|
|
1423
1463
|
}
|
|
1424
|
-
return lockedString(UIStringsNotTranslate.
|
|
1464
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForPerformanceEnterpriseNoLogging);
|
|
1425
1465
|
|
|
1426
1466
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.ACCESSIBILITY:
|
|
1427
|
-
if (
|
|
1428
|
-
return lockedString(UIStringsNotTranslate.
|
|
1467
|
+
if (loggingEnabled) {
|
|
1468
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForAccessibility);
|
|
1429
1469
|
}
|
|
1430
|
-
return lockedString(UIStringsNotTranslate.
|
|
1470
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForAccessibilityEnterpriseNoLogging);
|
|
1431
1471
|
|
|
1432
1472
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.BREAKPOINT:
|
|
1433
1473
|
|
|
1434
1474
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.NONE:
|
|
1435
|
-
if (
|
|
1436
|
-
return lockedString(UIStringsNotTranslate.
|
|
1475
|
+
if (loggingEnabled) {
|
|
1476
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForNoContext);
|
|
1437
1477
|
}
|
|
1438
|
-
return lockedString(UIStringsNotTranslate.
|
|
1478
|
+
return lockedString(UIStringsNotTranslate.inputDisclaimerForNoContextEnterpriseNoLogging);
|
|
1439
1479
|
}
|
|
1440
1480
|
}
|
|
1441
1481
|
|