chrome-devtools-frontend 1.0.1642845 → 1.0.1643099
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/SECURITY.md +1 -0
- package/front_end/core/host/UserMetrics.ts +2 -1
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/core/sdk/CSSMatchedStyles.ts +55 -26
- package/front_end/core/sdk/CSSRule.ts +1 -0
- package/front_end/core/sdk/DebuggerModel.ts +5 -0
- package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +4 -3
- package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +4 -3
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +4 -5
- package/front_end/generated/InspectorBackendCommands.ts +1 -1
- package/front_end/generated/protocol.ts +7 -0
- package/front_end/models/ai_assistance/AiAgent2.ts +100 -18
- package/front_end/models/ai_assistance/AiConversation.ts +18 -14
- package/front_end/models/ai_assistance/AiUtils.ts +71 -0
- package/front_end/models/ai_assistance/ChangeManager.ts +2 -5
- package/front_end/models/ai_assistance/{agents/ConversationSummaryAgent.ts → ConversationSummary.ts} +29 -66
- package/front_end/models/ai_assistance/ExtensionScope.ts +1 -4
- package/front_end/models/ai_assistance/{agents/PerformanceAnnotationsAgent.ts → PerformanceAnnotations.ts} +47 -89
- package/front_end/models/ai_assistance/README.md +8 -0
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +65 -40
- package/front_end/models/ai_assistance/agents/AiAgent.ts +37 -6
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +11 -0
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +55 -5
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +2 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +119 -78
- package/front_end/models/ai_assistance/agents/StorageAgent.ts +47 -38
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +0 -25
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +46 -326
- package/front_end/models/ai_assistance/ai_assistance.ts +14 -4
- package/front_end/models/ai_assistance/contexts/DOMNodeContext.snapshot.txt +51 -0
- package/front_end/models/ai_assistance/contexts/DOMNodeContext.ts +200 -0
- package/front_end/models/ai_assistance/skills/styling.md +44 -2
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +140 -0
- package/front_end/models/ai_assistance/tools/GetStyles.ts +141 -0
- package/front_end/models/ai_assistance/tools/Tool.ts +64 -0
- package/front_end/models/ai_assistance/tools/ToolRegistry.ts +36 -0
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +5 -7
- package/front_end/models/lighthouse/LighthouseReporterTypes.ts +5 -0
- package/front_end/models/live-metrics/LiveMetrics.ts +24 -13
- package/front_end/models/stack_trace/DetailedErrorStackParser.ts +2 -2
- package/front_end/models/stack_trace/StackTrace.ts +4 -1
- package/front_end/models/stack_trace/StackTraceImpl.ts +9 -2
- package/front_end/models/stack_trace/StackTraceModel.ts +17 -4
- package/front_end/models/stack_trace/Trie.ts +1 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +25 -22
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +16 -0
- package/front_end/panels/ai_assistance/components/ChatInput.ts +2 -2
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +96 -4
- package/front_end/panels/ai_assistance/components/chatMessage.css +6 -0
- package/front_end/panels/application/DOMStorageItemsView.ts +4 -0
- package/front_end/panels/application/KeyValueStorageItemsView.ts +39 -7
- package/front_end/panels/application/components/AdsView.ts +219 -0
- package/front_end/panels/application/components/adsView.css +54 -0
- package/front_end/panels/application/components/components.ts +2 -0
- package/front_end/panels/common/ExtensionServer.ts +26 -15
- package/front_end/panels/console/SymbolizedErrorWidget.ts +73 -22
- package/front_end/panels/elements/StandaloneStylesContainer.ts +1 -1
- package/front_end/panels/elements/StylePropertiesSection.ts +8 -0
- package/front_end/panels/elements/StylePropertyHighlighter.ts +4 -2
- package/front_end/panels/elements/StylePropertyTreeElement.ts +6 -5
- package/front_end/panels/elements/StylesContainer.ts +1 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +4 -4
- package/front_end/panels/layer_viewer/PaintProfilerView.ts +106 -132
- package/front_end/panels/lighthouse/LighthousePanel.ts +4 -3
- package/front_end/panels/network/NetworkLogView.ts +8 -1
- package/front_end/panels/network/networkLogView.css +0 -15
- package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +5 -4
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/lighthouse/README.chromium +2 -2
- package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1607 -5733
- package/front_end/third_party/lighthouse/locales/ar-XB.json +290 -65
- package/front_end/third_party/lighthouse/locales/ar.json +290 -65
- package/front_end/third_party/lighthouse/locales/bg.json +290 -65
- package/front_end/third_party/lighthouse/locales/ca.json +295 -70
- package/front_end/third_party/lighthouse/locales/cs.json +290 -65
- package/front_end/third_party/lighthouse/locales/da.json +294 -69
- package/front_end/third_party/lighthouse/locales/de.json +295 -70
- package/front_end/third_party/lighthouse/locales/el.json +290 -65
- package/front_end/third_party/lighthouse/locales/en-GB.json +290 -65
- package/front_end/third_party/lighthouse/locales/en-US.json +79 -67
- package/front_end/third_party/lighthouse/locales/en-XA.json +253 -64
- package/front_end/third_party/lighthouse/locales/en-XL.json +79 -67
- package/front_end/third_party/lighthouse/locales/es-419.json +290 -65
- package/front_end/third_party/lighthouse/locales/es.json +298 -73
- package/front_end/third_party/lighthouse/locales/fi.json +290 -65
- package/front_end/third_party/lighthouse/locales/fil.json +290 -65
- package/front_end/third_party/lighthouse/locales/fr.json +294 -69
- package/front_end/third_party/lighthouse/locales/he.json +293 -68
- package/front_end/third_party/lighthouse/locales/hi.json +291 -66
- package/front_end/third_party/lighthouse/locales/hr.json +290 -65
- package/front_end/third_party/lighthouse/locales/hu.json +290 -65
- package/front_end/third_party/lighthouse/locales/id.json +290 -65
- package/front_end/third_party/lighthouse/locales/it.json +294 -69
- package/front_end/third_party/lighthouse/locales/ja.json +290 -65
- package/front_end/third_party/lighthouse/locales/ko.json +290 -65
- package/front_end/third_party/lighthouse/locales/lt.json +290 -65
- package/front_end/third_party/lighthouse/locales/lv.json +290 -65
- package/front_end/third_party/lighthouse/locales/nl.json +290 -65
- package/front_end/third_party/lighthouse/locales/no.json +290 -65
- package/front_end/third_party/lighthouse/locales/pl.json +290 -65
- package/front_end/third_party/lighthouse/locales/pt-PT.json +291 -66
- package/front_end/third_party/lighthouse/locales/pt.json +290 -65
- package/front_end/third_party/lighthouse/locales/ro.json +290 -65
- package/front_end/third_party/lighthouse/locales/ru.json +301 -76
- package/front_end/third_party/lighthouse/locales/sk.json +291 -66
- package/front_end/third_party/lighthouse/locales/sl.json +290 -65
- package/front_end/third_party/lighthouse/locales/sr-Latn.json +290 -65
- package/front_end/third_party/lighthouse/locales/sr.json +290 -65
- package/front_end/third_party/lighthouse/locales/sv.json +297 -72
- package/front_end/third_party/lighthouse/locales/ta.json +291 -66
- package/front_end/third_party/lighthouse/locales/te.json +293 -68
- package/front_end/third_party/lighthouse/locales/th.json +291 -66
- package/front_end/third_party/lighthouse/locales/tr.json +290 -65
- package/front_end/third_party/lighthouse/locales/uk.json +290 -65
- package/front_end/third_party/lighthouse/locales/vi.json +291 -66
- package/front_end/third_party/lighthouse/locales/zh-HK.json +292 -67
- package/front_end/third_party/lighthouse/locales/zh-TW.json +291 -66
- package/front_end/third_party/lighthouse/locales/zh.json +291 -66
- package/front_end/third_party/lighthouse/report/bundle.d.ts +6 -6
- package/front_end/third_party/lighthouse/report/bundle.js +4 -7
- package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +2 -2
- package/front_end/ui/legacy/Widget.ts +32 -8
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +36 -3
- package/front_end/ui/legacy/components/data_grid/dataGridAiButton.css +20 -0
- package/front_end/ui/legacy/components/utils/Linkifier.ts +19 -4
- package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
- package/mcp/mcp.ts +1 -0
- package/package.json +1 -1
package/SECURITY.md
CHANGED
|
@@ -22,6 +22,7 @@ Chrome DevTools is a privileged web app running in a sandboxed renderer process,
|
|
|
22
22
|
* **Legitimate Data Exposure:** Displaying local user data, cookies, tokens, or auth headers within UI panels.
|
|
23
23
|
* **Local Data Persistence:** Saving user-initiated traces, heaps, profiles, or logs to disk.
|
|
24
24
|
* **Correctness & Availability:** Stale, misleading, or missing UI information (classified as functional bugs).
|
|
25
|
+
* **Denial of Service:** Chrome extensions or debug targets that disrupt DevTools' availability, e.g. through performance degradation.
|
|
25
26
|
* **Disabled-by-default Experimental Features:** Experimental features or capabilities that are disabled by default, e.g. requiring a command-line flag to be activated, or a specific runtime setting within DevTools to be manually turned on.
|
|
26
27
|
|
|
27
28
|
## Specific Severity Classification Rules (S1–S4)
|
|
@@ -496,7 +496,8 @@ export enum Action {
|
|
|
496
496
|
AiCodeGenerationRequestTriggeredFromSources = 205,
|
|
497
497
|
AiCodeCompletionFreCompletedFromConsole = 206,
|
|
498
498
|
AiCodeCompletionFreCompletedFromSources = 207,
|
|
499
|
-
|
|
499
|
+
AiAssistanceOpenedFromStoragePanelFloatingButton = 208,
|
|
500
|
+
MAX_VALUE = 209,
|
|
500
501
|
/* eslint-enable @typescript-eslint/naming-convention */
|
|
501
502
|
}
|
|
502
503
|
|
|
@@ -339,6 +339,10 @@ export class TargetBase {
|
|
|
339
339
|
return this.getAgent('Autofill');
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
+
adsAgent(): ProtocolProxyApi.AdsApi {
|
|
343
|
+
return this.getAgent('Ads');
|
|
344
|
+
}
|
|
345
|
+
|
|
342
346
|
browserAgent(): ProtocolProxyApi.BrowserApi {
|
|
343
347
|
return this.getAgent('Browser');
|
|
344
348
|
}
|
|
@@ -196,6 +196,36 @@ function queryMatches(style: CSSStyleDeclaration): boolean {
|
|
|
196
196
|
return true;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
function treeScopeDistance(node: DOMNode, property: CSSProperty): number {
|
|
200
|
+
if (!property.ownerStyle.parentRule && property.ownerStyle.type !== Type.Inline) {
|
|
201
|
+
return -1;
|
|
202
|
+
}
|
|
203
|
+
const root = node.getTreeRoot();
|
|
204
|
+
const nodeId = property.ownerStyle.parentRule?.treeScope ?? root?.backendNodeId();
|
|
205
|
+
if (nodeId === undefined) {
|
|
206
|
+
return -1;
|
|
207
|
+
}
|
|
208
|
+
return distanceToTreeScope(node, nodeId);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Distance from node to parent that is the tree scope. Returns -1 if tree scope is not found.
|
|
213
|
+
*
|
|
214
|
+
* @param node The child node to start from.
|
|
215
|
+
* @param treeScope The tree scope node ID.
|
|
216
|
+
* @returns The distance to the tree scope node, or -1 if not found.
|
|
217
|
+
*/
|
|
218
|
+
export function distanceToTreeScope(node: DOMNode, treeScope: Protocol.DOM.BackendNodeId): number {
|
|
219
|
+
let distance = 0;
|
|
220
|
+
for (let ancestor: DOMNode|null = node; ancestor; ancestor = ancestor.parentNode) {
|
|
221
|
+
if (ancestor.backendNodeId() === treeScope) {
|
|
222
|
+
return distance;
|
|
223
|
+
}
|
|
224
|
+
distance++;
|
|
225
|
+
}
|
|
226
|
+
return -1;
|
|
227
|
+
}
|
|
228
|
+
|
|
199
229
|
export interface CSSMatchedStylesPayload {
|
|
200
230
|
cssModel: CSSModel;
|
|
201
231
|
node: DOMNode;
|
|
@@ -307,7 +337,7 @@ export class CSSMatchedStyles {
|
|
|
307
337
|
#customHighlightPseudoDOMCascades?: Map<string, DOMInheritanceCascade>;
|
|
308
338
|
#functionRules: CSSFunctionRule[];
|
|
309
339
|
#atRules: CSSAtRule[];
|
|
310
|
-
#functionRuleMap = new Map<string, CSSFunctionRule>();
|
|
340
|
+
#functionRuleMap = new Map<string, CSSFunctionRule[]>();
|
|
311
341
|
#environmentVariables: Record<string, string> = {};
|
|
312
342
|
|
|
313
343
|
static async create(payload: CSSMatchedStylesPayload): Promise<CSSMatchedStyles> {
|
|
@@ -381,7 +411,9 @@ export class CSSMatchedStyles {
|
|
|
381
411
|
}
|
|
382
412
|
|
|
383
413
|
for (const rule of this.#functionRules) {
|
|
384
|
-
this.#functionRuleMap.
|
|
414
|
+
const rules = this.#functionRuleMap.get(rule.functionName().text) ?? [];
|
|
415
|
+
rules.push(rule);
|
|
416
|
+
this.#functionRuleMap.set(rule.functionName().text, rules);
|
|
385
417
|
}
|
|
386
418
|
}
|
|
387
419
|
|
|
@@ -790,9 +822,25 @@ export class CSSMatchedStyles {
|
|
|
790
822
|
return this.#registeredPropertyMap.get(name);
|
|
791
823
|
}
|
|
792
824
|
|
|
793
|
-
getRegisteredFunction(name: string):
|
|
794
|
-
|
|
795
|
-
|
|
825
|
+
getRegisteredFunction(name: string, sourceProperty: CSSProperty):
|
|
826
|
+
{treeScopeDistance: number, registeredFunction?: string} {
|
|
827
|
+
const minTreeScopeDistance = treeScopeDistance(this.#node, sourceProperty);
|
|
828
|
+
const functionRules = this.#functionRuleMap.get(name) ?? [];
|
|
829
|
+
let result: {treeScopeDistance: number, registeredFunction?: string} = {treeScopeDistance: -1};
|
|
830
|
+
for (const functionRule of functionRules) {
|
|
831
|
+
if (!functionRule.treeScope) {
|
|
832
|
+
continue;
|
|
833
|
+
}
|
|
834
|
+
const distance = distanceToTreeScope(this.#node, functionRule.treeScope);
|
|
835
|
+
if (distance === -1 || distance < minTreeScopeDistance) {
|
|
836
|
+
continue;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
if (result.treeScopeDistance === -1 || distance < result.treeScopeDistance) {
|
|
840
|
+
result = {registeredFunction: functionRule.nameWithParameters(), treeScopeDistance: distance};
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
return result;
|
|
796
844
|
}
|
|
797
845
|
|
|
798
846
|
functionRules(): CSSFunctionRule[] {
|
|
@@ -1045,26 +1093,6 @@ class NodeCascade {
|
|
|
1045
1093
|
}
|
|
1046
1094
|
}
|
|
1047
1095
|
|
|
1048
|
-
#treeScopeDistance(property: CSSProperty): number {
|
|
1049
|
-
if (!property.ownerStyle.parentRule && property.ownerStyle.type !== Type.Inline) {
|
|
1050
|
-
return -1;
|
|
1051
|
-
}
|
|
1052
|
-
const root = this.#node.getTreeRoot();
|
|
1053
|
-
const nodeId = property.ownerStyle.parentRule?.treeScope ?? root?.backendNodeId();
|
|
1054
|
-
if (nodeId === undefined) {
|
|
1055
|
-
return -1;
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
let distance = 0;
|
|
1059
|
-
for (let ancestor: DOMNode|null = this.#node; ancestor; ancestor = ancestor.parentNode) {
|
|
1060
|
-
if (ancestor.backendNodeId() === nodeId) {
|
|
1061
|
-
return distance;
|
|
1062
|
-
}
|
|
1063
|
-
distance++;
|
|
1064
|
-
}
|
|
1065
|
-
return -1;
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
1096
|
#needsCascadeContextStep(): boolean {
|
|
1069
1097
|
if (!this.#node.isInShadowTree()) {
|
|
1070
1098
|
return false;
|
|
@@ -1084,7 +1112,8 @@ class NodeCascade {
|
|
|
1084
1112
|
const activeProperty = this.activeProperties.get(canonicalName);
|
|
1085
1113
|
if (activeProperty?.important && !propertyWithHigherSpecificity.important ||
|
|
1086
1114
|
activeProperty && this.#needsCascadeContextStep() &&
|
|
1087
|
-
this.#
|
|
1115
|
+
treeScopeDistance(this.#node, activeProperty) >
|
|
1116
|
+
treeScopeDistance(this.#node, propertyWithHigherSpecificity)) {
|
|
1088
1117
|
this.propertiesState.set(propertyWithHigherSpecificity, PropertyState.OVERLOADED);
|
|
1089
1118
|
return;
|
|
1090
1119
|
}
|
|
@@ -418,6 +418,7 @@ export class CSSFunctionRule extends CSSRule {
|
|
|
418
418
|
styleSheetId: payload.styleSheetId
|
|
419
419
|
},
|
|
420
420
|
header: styleSheetHeaderForRule(cssModel, payload),
|
|
421
|
+
originTreeScopeNodeId: payload.originTreeScopeNodeId
|
|
421
422
|
});
|
|
422
423
|
this.#name = new CSSValue(payload.name);
|
|
423
424
|
this.#parameters = payload.parameters.map(({name}) => name);
|
|
@@ -535,6 +535,11 @@ export class DebuggerModel extends SDKModel<EventTypes> {
|
|
|
535
535
|
return this.#scripts.get(scriptId) || null;
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
+
isWasm(scriptId: string): boolean {
|
|
539
|
+
const script = this.scriptForId(scriptId);
|
|
540
|
+
return script ? script.isWasm() : false;
|
|
541
|
+
}
|
|
542
|
+
|
|
538
543
|
/**
|
|
539
544
|
* Returns all `Script` objects with the same provided `sourceURL`. The
|
|
540
545
|
* resulting array is sorted by time with the newest `Script` in the front.
|
|
@@ -41,7 +41,7 @@ class GreenDevFloaty {
|
|
|
41
41
|
#playButton!: HTMLButtonElement;
|
|
42
42
|
#node?: SDK.DOMModel.DOMNode;
|
|
43
43
|
#agent?: AiAssistance.GreenDevAgent.GreenDevAgent|AiAssistance.StylingAgent.StylingAgent;
|
|
44
|
-
#nodeContext?: AiAssistance.
|
|
44
|
+
#nodeContext?: AiAssistance.DOMNodeContext.DOMNodeContext;
|
|
45
45
|
#backendNodeId?: Protocol.DOM.BackendNodeId;
|
|
46
46
|
#syncChannel: BroadcastChannel;
|
|
47
47
|
#isFloatyWindow: boolean;
|
|
@@ -341,7 +341,7 @@ class GreenDevFloaty {
|
|
|
341
341
|
});
|
|
342
342
|
} else {
|
|
343
343
|
this.#agent = new AiAssistance.StylingAgent.StylingAgent({aidaClient});
|
|
344
|
-
this.#nodeContext = new AiAssistance.
|
|
344
|
+
this.#nodeContext = new AiAssistance.DOMNodeContext.DOMNodeContext(this.#node);
|
|
345
345
|
}
|
|
346
346
|
}
|
|
347
347
|
|
|
@@ -428,7 +428,8 @@ class GreenDevFloaty {
|
|
|
428
428
|
'Could not get the backendNodeId for the selected element.';
|
|
429
429
|
|
|
430
430
|
// --- Get some context information about the selected node ---
|
|
431
|
-
const
|
|
431
|
+
const domNodeContext = new AiAssistance.DOMNodeContext.DOMNodeContext(this.#node);
|
|
432
|
+
const elementContext = await domNodeContext.describe();
|
|
432
433
|
|
|
433
434
|
// Now construct the full context.
|
|
434
435
|
const context = `# Page URL
|
|
@@ -20,7 +20,8 @@ import * as AiAssistance from '../../models/ai_assistance/ai_assistance.js';
|
|
|
20
20
|
|
|
21
21
|
const {AidaClient} = Host.AidaClient;
|
|
22
22
|
const {ResponseType} = AiAssistance.AiAgent;
|
|
23
|
-
const {
|
|
23
|
+
const {DOMNodeContext} = AiAssistance.DOMNodeContext;
|
|
24
|
+
const {StylingAgent} = AiAssistance.StylingAgent;
|
|
24
25
|
|
|
25
26
|
class GreenDevFloaty {
|
|
26
27
|
#chatContainer: HTMLDivElement;
|
|
@@ -28,7 +29,7 @@ class GreenDevFloaty {
|
|
|
28
29
|
#playButton: HTMLButtonElement;
|
|
29
30
|
#node?: SDK.DOMModel.DOMNode;
|
|
30
31
|
#agent?: StylingAgent;
|
|
31
|
-
#nodeContext?:
|
|
32
|
+
#nodeContext?: DOMNodeContext;
|
|
32
33
|
#backendNodeId?: Protocol.DOM.BackendNodeId;
|
|
33
34
|
// Switching this to false can help while investigating tool conflicts.
|
|
34
35
|
#highlightNodeOnWindowFocus = false;
|
|
@@ -170,7 +171,7 @@ class GreenDevFloaty {
|
|
|
170
171
|
if (!this.#agent) {
|
|
171
172
|
const aidaClient = new AidaClient();
|
|
172
173
|
this.#agent = new StylingAgent({aidaClient});
|
|
173
|
-
this.#nodeContext = new
|
|
174
|
+
this.#nodeContext = new DOMNodeContext(this.#node);
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
this.#addMessage(query, true);
|
|
@@ -876,7 +876,7 @@ export abstract class HeapSnapshot {
|
|
|
876
876
|
readonly #progress: HeapSnapshotProgress;
|
|
877
877
|
readonly #noDistance = -5;
|
|
878
878
|
rootNodeIndexInternal = 0;
|
|
879
|
-
#snapshotDiffs: Record<
|
|
879
|
+
#snapshotDiffs: Record<number, Record<string, HeapSnapshotModel.HeapSnapshotModel.Diff>> = {};
|
|
880
880
|
#aggregatesForDiff?: {
|
|
881
881
|
interfaceDefinitions: string,
|
|
882
882
|
aggregates: Record<string, HeapSnapshotModel.HeapSnapshotModel.AggregateForDiff>,
|
|
@@ -2688,9 +2688,8 @@ export abstract class HeapSnapshot {
|
|
|
2688
2688
|
throw new Error('Not implemented');
|
|
2689
2689
|
}
|
|
2690
2690
|
|
|
2691
|
-
calculateSnapshotDiff(
|
|
2692
|
-
|
|
2693
|
-
baseSnapshotAggregates: Record<string, HeapSnapshotModel.HeapSnapshotModel.AggregateForDiff>):
|
|
2691
|
+
calculateSnapshotDiff(baseSnapshotId: number,
|
|
2692
|
+
baseSnapshotAggregates: Record<string, HeapSnapshotModel.HeapSnapshotModel.AggregateForDiff>):
|
|
2694
2693
|
Record<string, HeapSnapshotModel.HeapSnapshotModel.Diff> {
|
|
2695
2694
|
let snapshotDiff: Record<string, HeapSnapshotModel.HeapSnapshotModel.Diff> = this.#snapshotDiffs[baseSnapshotId];
|
|
2696
2695
|
if (snapshotDiff) {
|
|
@@ -2976,7 +2975,7 @@ export abstract class HeapSnapshot {
|
|
|
2976
2975
|
return {paths, limitsReached};
|
|
2977
2976
|
}
|
|
2978
2977
|
|
|
2979
|
-
createAddedNodesProvider(baseSnapshotId:
|
|
2978
|
+
createAddedNodesProvider(baseSnapshotId: number, classKey: string): HeapSnapshotNodesProvider {
|
|
2980
2979
|
const snapshotDiff = this.#snapshotDiffs[baseSnapshotId];
|
|
2981
2980
|
const diffForClass = snapshotDiff[classKey];
|
|
2982
2981
|
return new HeapSnapshotNodesProvider(this, diffForClass.addedIndexes);
|
|
@@ -435,7 +435,7 @@ inspectorBackend.registerCommand("DOM.getFrameOwner", [{"name": "frameId", "type
|
|
|
435
435
|
inspectorBackend.registerCommand("DOM.getContainerForNode", [{"name": "nodeId", "type": "number", "optional": false, "description": "", "typeRef": "DOM.NodeId"}, {"name": "containerName", "type": "string", "optional": true, "description": "", "typeRef": null}, {"name": "physicalAxes", "type": "string", "optional": true, "description": "", "typeRef": "DOM.PhysicalAxes"}, {"name": "logicalAxes", "type": "string", "optional": true, "description": "", "typeRef": "DOM.LogicalAxes"}, {"name": "queriesScrollState", "type": "boolean", "optional": true, "description": "", "typeRef": null}, {"name": "queriesAnchored", "type": "boolean", "optional": true, "description": "", "typeRef": null}], ["nodeId"], "Returns the query container of the given node based on container query conditions: containerName, physical and logical axes, and whether it queries scroll-state or anchored elements. If no axes are provided and queriesScrollState is false, the style container is returned, which is the direct parent or the closest element with a matching container-name.");
|
|
436
436
|
inspectorBackend.registerCommand("DOM.getQueryingDescendantsForContainer", [{"name": "nodeId", "type": "number", "optional": false, "description": "Id of the container node to find querying descendants from.", "typeRef": "DOM.NodeId"}], ["nodeIds"], "Returns the descendants of a container query container that have container queries against this container.");
|
|
437
437
|
inspectorBackend.registerCommand("DOM.getAnchorElement", [{"name": "nodeId", "type": "number", "optional": false, "description": "Id of the positioned element from which to find the anchor.", "typeRef": "DOM.NodeId"}, {"name": "anchorSpecifier", "type": "string", "optional": true, "description": "An optional anchor specifier, as defined in https://www.w3.org/TR/css-anchor-position-1/#anchor-specifier. If not provided, it will return the implicit anchor element for the given positioned element.", "typeRef": null}], ["nodeId"], "Returns the target anchor element of the given anchor query according to https://www.w3.org/TR/css-anchor-position-1/#target.");
|
|
438
|
-
inspectorBackend.registerCommand("DOM.forceShowPopover", [{"name": "nodeId", "type": "number", "optional": false, "description": "Id of the popover HTMLElement", "typeRef": "DOM.NodeId"}, {"name": "enable", "type": "boolean", "optional": false, "description": "If true, opens the popover and keeps it open. If false, closes the popover if it was previously force-opened.", "typeRef": null}], ["nodeIds"], "When enabling, this API force-opens the popover identified by nodeId and keeps it open until disabled.");
|
|
438
|
+
inspectorBackend.registerCommand("DOM.forceShowPopover", [{"name": "nodeId", "type": "number", "optional": false, "description": "Id of the popover HTMLElement", "typeRef": "DOM.NodeId"}, {"name": "enable", "type": "boolean", "optional": false, "description": "If true, opens the popover and keeps it open. If false, closes the popover if it was previously force-opened.", "typeRef": null}, {"name": "invokerNodeId", "type": "number", "optional": true, "description": "Optional ID of the element invoking this popover, used to establish the implicit anchor. If not provided, it will fall back to the first invoker in the document, preferring elements with a popovertarget attribute over those with a commandfor attribute. Note that if there are multiple invokers, this is just an estimate.", "typeRef": "DOM.BackendNodeId"}], ["nodeIds"], "When enabling, this API force-opens the popover identified by nodeId and keeps it open until disabled.");
|
|
439
439
|
inspectorBackend.registerType("DOM.BackendNode", [{"name": "nodeType", "type": "number", "optional": false, "description": "`Node`'s nodeType.", "typeRef": null}, {"name": "nodeName", "type": "string", "optional": false, "description": "`Node`'s nodeName.", "typeRef": null}, {"name": "backendNodeId", "type": "number", "optional": false, "description": "", "typeRef": "DOM.BackendNodeId"}]);
|
|
440
440
|
inspectorBackend.registerType("DOM.Node", [{"name": "nodeId", "type": "number", "optional": false, "description": "Node identifier that is passed into the rest of the DOM messages as the `nodeId`. Backend will only push node with given `id` once. It is aware of all requested nodes and will only fire DOM events for nodes known to the client.", "typeRef": "DOM.NodeId"}, {"name": "parentId", "type": "number", "optional": true, "description": "The id of the parent node if any.", "typeRef": "DOM.NodeId"}, {"name": "backendNodeId", "type": "number", "optional": false, "description": "The BackendNodeId for this node.", "typeRef": "DOM.BackendNodeId"}, {"name": "nodeType", "type": "number", "optional": false, "description": "`Node`'s nodeType.", "typeRef": null}, {"name": "nodeName", "type": "string", "optional": false, "description": "`Node`'s nodeName.", "typeRef": null}, {"name": "localName", "type": "string", "optional": false, "description": "`Node`'s localName.", "typeRef": null}, {"name": "nodeValue", "type": "string", "optional": false, "description": "`Node`'s nodeValue.", "typeRef": null}, {"name": "childNodeCount", "type": "number", "optional": true, "description": "Child count for `Container` nodes.", "typeRef": null}, {"name": "children", "type": "array", "optional": true, "description": "Child nodes of this node when requested with children.", "typeRef": "DOM.Node"}, {"name": "attributes", "type": "array", "optional": true, "description": "Attributes of the `Element` node in the form of flat array `[name1, value1, name2, value2]`.", "typeRef": "string"}, {"name": "documentURL", "type": "string", "optional": true, "description": "Document URL that `Document` or `FrameOwner` node points to.", "typeRef": null}, {"name": "baseURL", "type": "string", "optional": true, "description": "Base URL that `Document` or `FrameOwner` node uses for URL completion.", "typeRef": null}, {"name": "publicId", "type": "string", "optional": true, "description": "`DocumentType`'s publicId.", "typeRef": null}, {"name": "systemId", "type": "string", "optional": true, "description": "`DocumentType`'s systemId.", "typeRef": null}, {"name": "internalSubset", "type": "string", "optional": true, "description": "`DocumentType`'s internalSubset.", "typeRef": null}, {"name": "xmlVersion", "type": "string", "optional": true, "description": "`Document`'s XML version in case of XML documents.", "typeRef": null}, {"name": "name", "type": "string", "optional": true, "description": "`Attr`'s name.", "typeRef": null}, {"name": "value", "type": "string", "optional": true, "description": "`Attr`'s value.", "typeRef": null}, {"name": "pseudoType", "type": "string", "optional": true, "description": "Pseudo element type for this node.", "typeRef": "DOM.PseudoType"}, {"name": "pseudoIdentifier", "type": "string", "optional": true, "description": "Pseudo element identifier for this node. Only present if there is a valid pseudoType.", "typeRef": null}, {"name": "shadowRootType", "type": "string", "optional": true, "description": "Shadow root type.", "typeRef": "DOM.ShadowRootType"}, {"name": "frameId", "type": "string", "optional": true, "description": "Frame ID for frame owner elements.", "typeRef": "Page.FrameId"}, {"name": "contentDocument", "type": "object", "optional": true, "description": "Content document for frame owner elements.", "typeRef": "DOM.Node"}, {"name": "shadowRoots", "type": "array", "optional": true, "description": "Shadow root list for given element host.", "typeRef": "DOM.Node"}, {"name": "templateContent", "type": "object", "optional": true, "description": "Content document fragment for template elements.", "typeRef": "DOM.Node"}, {"name": "pseudoElements", "type": "array", "optional": true, "description": "Pseudo elements associated with this node.", "typeRef": "DOM.Node"}, {"name": "importedDocument", "type": "object", "optional": true, "description": "Deprecated, as the HTML Imports API has been removed (crbug.com/937746). This property used to return the imported document for the HTMLImport links. The property is always undefined now.", "typeRef": "DOM.Node"}, {"name": "distributedNodes", "type": "array", "optional": true, "description": "Distributed nodes for given insertion point.", "typeRef": "DOM.BackendNode"}, {"name": "isSVG", "type": "boolean", "optional": true, "description": "Whether the node is SVG.", "typeRef": null}, {"name": "compatibilityMode", "type": "string", "optional": true, "description": "", "typeRef": "DOM.CompatibilityMode"}, {"name": "assignedSlot", "type": "object", "optional": true, "description": "", "typeRef": "DOM.BackendNode"}, {"name": "isScrollable", "type": "boolean", "optional": true, "description": "", "typeRef": null}, {"name": "affectedByStartingStyles", "type": "boolean", "optional": true, "description": "", "typeRef": null}, {"name": "adoptedStyleSheets", "type": "array", "optional": true, "description": "", "typeRef": "DOM.StyleSheetId"}, {"name": "adProvenance", "type": "object", "optional": true, "description": "", "typeRef": "Network.AdProvenance"}]);
|
|
441
441
|
inspectorBackend.registerType("DOM.DetachedElementInfo", [{"name": "treeNode", "type": "object", "optional": false, "description": "", "typeRef": "DOM.Node"}, {"name": "retainedNodeIds", "type": "array", "optional": false, "description": "", "typeRef": "DOM.NodeId"}]);
|
|
@@ -5849,6 +5849,13 @@ export namespace DOM {
|
|
|
5849
5849
|
* popover if it was previously force-opened.
|
|
5850
5850
|
*/
|
|
5851
5851
|
enable: boolean;
|
|
5852
|
+
/**
|
|
5853
|
+
* Optional ID of the element invoking this popover, used to establish the implicit anchor.
|
|
5854
|
+
* If not provided, it will fall back to the first invoker in the document, preferring
|
|
5855
|
+
* elements with a popovertarget attribute over those with a commandfor attribute. Note that
|
|
5856
|
+
* if there are multiple invokers, this is just an estimate.
|
|
5857
|
+
*/
|
|
5858
|
+
invokerNodeId?: BackendNodeId;
|
|
5852
5859
|
}
|
|
5853
5860
|
|
|
5854
5861
|
export interface ForceShowPopoverResponse extends ProtocolResponseWithError {
|
|
@@ -5,16 +5,26 @@
|
|
|
5
5
|
import * as Host from '../../core/host/host.js';
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
-
type AgentOptions,
|
|
9
8
|
AiAgent,
|
|
10
9
|
type ContextResponse,
|
|
11
10
|
type ConversationContext,
|
|
11
|
+
type MultimodalInputType,
|
|
12
12
|
type RequestOptions,
|
|
13
13
|
ResponseType
|
|
14
14
|
} from './agents/AiAgent.js';
|
|
15
|
+
import {type ExecuteJsAgentOptions, executeJsCode} from './agents/ExecuteJavascript.js';
|
|
16
|
+
import {ChangeManager} from './ChangeManager.js';
|
|
17
|
+
import {DOMNodeContext} from './contexts/DOMNodeContext.js';
|
|
15
18
|
import {debugLog} from './debug.js';
|
|
19
|
+
import {ExtensionScope} from './ExtensionScope.js';
|
|
16
20
|
import type {Skill, SkillName} from './skills/Skill.js';
|
|
17
21
|
import {SKILLS} from './skills/SkillRegistry.js';
|
|
22
|
+
import type {Tool} from './tools/Tool.js';
|
|
23
|
+
import {ToolRegistry} from './tools/ToolRegistry.js';
|
|
24
|
+
|
|
25
|
+
const SKILL_DISPLAY_NAMES: Record<SkillName, string> = {
|
|
26
|
+
styling: 'CSS and styling',
|
|
27
|
+
};
|
|
18
28
|
|
|
19
29
|
export class AiAgent2 extends AiAgent<unknown> {
|
|
20
30
|
// TODO: The static preamble is a placeholder and will eventually live server-side.
|
|
@@ -23,15 +33,20 @@ export class AiAgent2 extends AiAgent<unknown> {
|
|
|
23
33
|
readonly userTier = 'TESTERS';
|
|
24
34
|
|
|
25
35
|
#skillsInjected = false;
|
|
36
|
+
#changes = new ChangeManager();
|
|
37
|
+
#execJs: typeof executeJsCode;
|
|
26
38
|
|
|
27
39
|
get options(): RequestOptions {
|
|
28
40
|
return {};
|
|
29
41
|
}
|
|
30
42
|
|
|
31
43
|
readonly #activeSkills = new Set<SkillName>();
|
|
44
|
+
readonly #declaredTools = new Set<string>();
|
|
32
45
|
|
|
33
|
-
constructor(opts:
|
|
46
|
+
constructor(opts: ExecuteJsAgentOptions) {
|
|
34
47
|
super(opts);
|
|
48
|
+
this.#execJs = opts.execJs ?? executeJsCode;
|
|
49
|
+
this.#declaredTools.add('learnSkills');
|
|
35
50
|
const skillsList = Object.keys(SKILLS).join(', ');
|
|
36
51
|
this.declareFunction<{skills: SkillName[]}>('learnSkills', {
|
|
37
52
|
description: `Load skills to help with the task. Available skills: ${skillsList}.`,
|
|
@@ -51,8 +66,12 @@ export class AiAgent2 extends AiAgent<unknown> {
|
|
|
51
66
|
required: ['skills'],
|
|
52
67
|
},
|
|
53
68
|
displayInfoFromArgs: args => {
|
|
69
|
+
const isSingular = args.skills.length === 1;
|
|
70
|
+
const prefix = isSingular ? 'Learning skill' : 'Learning skills';
|
|
71
|
+
const names = args.skills.map(name => SKILL_DISPLAY_NAMES[name] ?? name).join(', ');
|
|
54
72
|
return {
|
|
55
|
-
title:
|
|
73
|
+
title: `${prefix}: ${names}`,
|
|
74
|
+
action: `learnSkills(${args.skills.map(name => `'${name}'`).join(', ')})`,
|
|
56
75
|
};
|
|
57
76
|
},
|
|
58
77
|
handler: async args => {
|
|
@@ -62,33 +81,58 @@ export class AiAgent2 extends AiAgent<unknown> {
|
|
|
62
81
|
});
|
|
63
82
|
}
|
|
64
83
|
|
|
65
|
-
override async enhanceQuery(
|
|
84
|
+
override async enhanceQuery(
|
|
85
|
+
query: string,
|
|
86
|
+
selected: ConversationContext<unknown>|null = null,
|
|
87
|
+
// TODO: support multimodal input in AiAgent2.
|
|
88
|
+
_multimodalInputType?: MultimodalInputType,
|
|
89
|
+
): Promise<string> {
|
|
90
|
+
let enhancedQuery = query;
|
|
91
|
+
if (selected) {
|
|
92
|
+
const promptDetails = await selected.getPromptDetails();
|
|
93
|
+
if (promptDetails) {
|
|
94
|
+
enhancedQuery = `${promptDetails}
|
|
95
|
+
|
|
96
|
+
# User request
|
|
97
|
+
|
|
98
|
+
QUERY: ${query}`;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
66
102
|
if (this.#skillsInjected) {
|
|
67
|
-
return
|
|
103
|
+
return enhancedQuery;
|
|
68
104
|
}
|
|
69
105
|
this.#skillsInjected = true;
|
|
70
|
-
const skillsManifest =
|
|
106
|
+
const skillsManifest =
|
|
107
|
+
Object.entries(this.getSkills()).map(([name, skill]) => `- ${name}: ${skill.description}`).join('\n');
|
|
71
108
|
return `Available skills:
|
|
72
109
|
${skillsManifest}
|
|
73
110
|
|
|
74
111
|
You must call \`learnSkills\` to load a skill before you can use it.
|
|
75
112
|
|
|
76
|
-
User query: ${
|
|
113
|
+
User query: ${enhancedQuery}`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
override async *
|
|
117
|
+
handleContextDetails(selected: ConversationContext<unknown>|null): AsyncGenerator<ContextResponse, void, void> {
|
|
118
|
+
if (selected) {
|
|
119
|
+
const details = await selected.getUserFacingDetails();
|
|
120
|
+
if (details) {
|
|
121
|
+
yield {
|
|
122
|
+
type: ResponseType.CONTEXT,
|
|
123
|
+
details,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
77
127
|
}
|
|
78
128
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
yield {
|
|
82
|
-
type: ResponseType.CONTEXT,
|
|
83
|
-
details: [{
|
|
84
|
-
title: 'Status',
|
|
85
|
-
text: 'Minimal agent initialized.',
|
|
86
|
-
}],
|
|
87
|
-
};
|
|
129
|
+
getSkills(): Record<SkillName, Skill> {
|
|
130
|
+
return SKILLS;
|
|
88
131
|
}
|
|
89
132
|
|
|
90
133
|
async learnSkill(names: SkillName[]): Promise<string> {
|
|
91
134
|
let response = '';
|
|
135
|
+
const skills = this.getSkills();
|
|
92
136
|
for (const name of names) {
|
|
93
137
|
debugLog(`AiAgent2: Attempting to load skill ${name}`);
|
|
94
138
|
if (this.#activeSkills.has(name)) {
|
|
@@ -97,19 +141,57 @@ User query: ${query}`;
|
|
|
97
141
|
continue;
|
|
98
142
|
}
|
|
99
143
|
|
|
100
|
-
const skillObj: Skill =
|
|
144
|
+
const skillObj: Skill = skills[name];
|
|
101
145
|
if (skillObj) {
|
|
102
146
|
this.#activeSkills.add(name);
|
|
103
147
|
debugLog(`AiAgent2: Skill ${name} loaded successfully`);
|
|
104
148
|
response += `Skill ${name} loaded. Instructions:\n${skillObj.instructions}\n`;
|
|
149
|
+
for (const toolName of skillObj.allowedTools) {
|
|
150
|
+
const tool = ToolRegistry.get(toolName);
|
|
151
|
+
if (tool) {
|
|
152
|
+
this.#declareTool(tool);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
105
155
|
} else {
|
|
106
156
|
debugLog(`AiAgent2: Failed to load skill ${name}`);
|
|
107
|
-
response += `Failed to load skill ${name}. Valid skills are: ${Object.keys(
|
|
157
|
+
response += `Failed to load skill ${name}. Valid skills are: ${Object.keys(skills).join(', ')}.\n`;
|
|
108
158
|
}
|
|
109
159
|
}
|
|
110
160
|
return response.trim();
|
|
111
161
|
}
|
|
112
162
|
|
|
163
|
+
#createExtensionScope(changes: ChangeManager): {install(): Promise<void>, uninstall(): Promise<void>} {
|
|
164
|
+
const selectedNode = this.context && this.context instanceof DOMNodeContext ? this.context.getItem() : null;
|
|
165
|
+
return new ExtensionScope(changes, this.sessionId, selectedNode);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Declares a tool to be available to the agent model, verifying first that
|
|
170
|
+
* it hasn't already been declared to prevent duplicate declaration errors.
|
|
171
|
+
*/
|
|
172
|
+
#declareTool(tool: Tool): void {
|
|
173
|
+
if (this.#declaredTools.has(tool.name)) {
|
|
174
|
+
debugLog(`AiAgent2: Tool ${tool.name} is already declared`);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
this.#declaredTools.add(tool.name);
|
|
178
|
+
this.declareFunction(tool.name, {
|
|
179
|
+
description: tool.description,
|
|
180
|
+
parameters: tool.parameters,
|
|
181
|
+
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
|
+
},
|
|
190
|
+
options,
|
|
191
|
+
),
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
113
195
|
get activeSkills(): Set<SkillName> {
|
|
114
196
|
return this.#activeSkills;
|
|
115
197
|
}
|
|
@@ -29,10 +29,11 @@ import {FileAgent, FileContext} from './agents/FileAgent.js';
|
|
|
29
29
|
import {NetworkAgent, RequestContext} from './agents/NetworkAgent.js';
|
|
30
30
|
import {PerformanceAgent, PerformanceTraceContext} from './agents/PerformanceAgent.js';
|
|
31
31
|
import {StorageAgent, StorageContext} from './agents/StorageAgent.js';
|
|
32
|
-
import {
|
|
32
|
+
import {StylingAgent} from './agents/StylingAgent.js';
|
|
33
33
|
import {AiAgent2} from './AiAgent2.js';
|
|
34
34
|
import {AiHistoryStorage, ConversationType, type SerializedConversation} from './AiHistoryStorage.js';
|
|
35
35
|
import type {ChangeManager} from './ChangeManager.js';
|
|
36
|
+
import {DOMNodeContext} from './contexts/DOMNodeContext.js';
|
|
36
37
|
|
|
37
38
|
export const NOT_FOUND_IMAGE_DATA = '';
|
|
38
39
|
export const CONTEXT_TITLE = 'Analyzing data';
|
|
@@ -182,7 +183,7 @@ export class AiConversation {
|
|
|
182
183
|
if (isAiAssistanceContextSelectionAgentEnabled()) {
|
|
183
184
|
if (updateContext instanceof FileContext) {
|
|
184
185
|
this.#updateAgent(ConversationType.FILE);
|
|
185
|
-
} else if (updateContext instanceof
|
|
186
|
+
} else if (updateContext instanceof DOMNodeContext) {
|
|
186
187
|
this.#updateAgent(ConversationType.STYLING);
|
|
187
188
|
} else if (updateContext instanceof RequestContext) {
|
|
188
189
|
this.#updateAgent(ConversationType.NETWORK);
|
|
@@ -327,24 +328,27 @@ export class AiConversation {
|
|
|
327
328
|
};
|
|
328
329
|
}
|
|
329
330
|
|
|
331
|
+
#filterHistoryForNewAgent(): Host.AidaClient.Content[] {
|
|
332
|
+
return this.#agent?.history
|
|
333
|
+
.map(content => {
|
|
334
|
+
return {
|
|
335
|
+
...content,
|
|
336
|
+
parts: content.parts.filter(part => !('functionCall' in part) && !('functionResponse' in part)),
|
|
337
|
+
};
|
|
338
|
+
})
|
|
339
|
+
.filter(content => content.parts.length > 0) ??
|
|
340
|
+
[];
|
|
341
|
+
}
|
|
342
|
+
|
|
330
343
|
#updateAgent(type: ConversationType): void {
|
|
331
344
|
if (this.#type === type) {
|
|
332
345
|
return;
|
|
333
346
|
}
|
|
334
347
|
|
|
335
|
-
this.#type
|
|
348
|
+
const isTransitioningFromStorage = this.#type === ConversationType.STORAGE && type !== ConversationType.STORAGE;
|
|
349
|
+
const history = isTransitioningFromStorage ? [] : this.#filterHistoryForNewAgent();
|
|
336
350
|
|
|
337
|
-
|
|
338
|
-
// as the LLM tries to call the existing ones.
|
|
339
|
-
const history =
|
|
340
|
-
this.#agent?.history
|
|
341
|
-
.map(content => {
|
|
342
|
-
return {
|
|
343
|
-
...content,
|
|
344
|
-
parts: content.parts.filter(part => !('functionCall' in part) && !('functionResponse' in part)),
|
|
345
|
-
};
|
|
346
|
-
})
|
|
347
|
-
.filter(content => content.parts.length > 0);
|
|
351
|
+
this.#type = type;
|
|
348
352
|
|
|
349
353
|
const options = {
|
|
350
354
|
aidaClient: this.#aidaClient,
|
|
@@ -8,6 +8,8 @@ import * as i18n from '../../core/i18n/i18n.js';
|
|
|
8
8
|
import type * as Platform from '../../core/platform/platform.js';
|
|
9
9
|
import * as Root from '../../core/root/root.js';
|
|
10
10
|
|
|
11
|
+
import {debugLog} from './debug.js';
|
|
12
|
+
|
|
11
13
|
const UIStrings = {
|
|
12
14
|
/**
|
|
13
15
|
* @description Message shown to the user if the age check is not successful.
|
|
@@ -71,3 +73,72 @@ export function isSameOrigin(url1: Platform.DevToolsPath.UrlString, url2: Platfo
|
|
|
71
73
|
const origin2 = Common.ParsedURL.ParsedURL.extractOrigin(url2);
|
|
72
74
|
return origin1 !== '' && origin1 === origin2;
|
|
73
75
|
}
|
|
76
|
+
|
|
77
|
+
export interface OneShotPromptRequest {
|
|
78
|
+
aidaClient: Host.AidaClient.AidaClient;
|
|
79
|
+
preamble: string;
|
|
80
|
+
query: string;
|
|
81
|
+
clientFeature: Host.AidaClient.ClientFeature;
|
|
82
|
+
temperature?: number;
|
|
83
|
+
modelId?: string;
|
|
84
|
+
userTier?: string;
|
|
85
|
+
serverSideLoggingEnabled?: boolean;
|
|
86
|
+
signal?: AbortSignal;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export async function runOneShotPrompt({
|
|
90
|
+
aidaClient,
|
|
91
|
+
preamble,
|
|
92
|
+
query,
|
|
93
|
+
clientFeature,
|
|
94
|
+
temperature,
|
|
95
|
+
modelId,
|
|
96
|
+
userTier,
|
|
97
|
+
serverSideLoggingEnabled,
|
|
98
|
+
signal,
|
|
99
|
+
}: OneShotPromptRequest): Promise<string> {
|
|
100
|
+
const chromeVersion = Root.Runtime.getChromeVersion();
|
|
101
|
+
if (!chromeVersion) {
|
|
102
|
+
throw new Error('Cannot determine Chrome version');
|
|
103
|
+
}
|
|
104
|
+
const disallowLogging = !serverSideLoggingEnabled;
|
|
105
|
+
const sessionId = crypto.randomUUID();
|
|
106
|
+
|
|
107
|
+
const userTierEnum = Host.AidaClient.convertToUserTierEnum(userTier);
|
|
108
|
+
const finalPreamble = userTierEnum === Host.AidaClient.UserTier.TESTERS ? preamble : undefined;
|
|
109
|
+
|
|
110
|
+
const request: Host.AidaClient.DoConversationRequest = {
|
|
111
|
+
client: Host.AidaClient.CLIENT_NAME,
|
|
112
|
+
current_message: {
|
|
113
|
+
parts: [{text: query}],
|
|
114
|
+
role: Host.AidaClient.Role.USER,
|
|
115
|
+
},
|
|
116
|
+
preamble: finalPreamble,
|
|
117
|
+
options: {
|
|
118
|
+
temperature: typeof temperature === 'number' && temperature >= 0 ? temperature : undefined,
|
|
119
|
+
model_id: modelId || undefined,
|
|
120
|
+
},
|
|
121
|
+
metadata: {
|
|
122
|
+
disable_user_content_logging: disallowLogging,
|
|
123
|
+
string_session_id: sessionId,
|
|
124
|
+
user_tier: userTierEnum,
|
|
125
|
+
client_version: chromeVersion,
|
|
126
|
+
},
|
|
127
|
+
functionality_type: Host.AidaClient.FunctionalityType.CHAT,
|
|
128
|
+
client_feature: clientFeature,
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
let textResponse = '';
|
|
132
|
+
try {
|
|
133
|
+
for await (const response of aidaClient.doConversation(request, {signal})) {
|
|
134
|
+
if (response.explanation) {
|
|
135
|
+
textResponse = response.explanation;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
} catch (err) {
|
|
139
|
+
debugLog('Error calling AIDA for one-shot prompt', err);
|
|
140
|
+
throw err;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return textResponse;
|
|
144
|
+
}
|