chrome-devtools-frontend 1.0.1592129 → 1.0.1593518
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/front_end/Images/src/tab-move.svg +1 -0
- package/front_end/application_tokens.css +4 -4
- package/front_end/core/host/UserMetrics.ts +2 -1
- package/front_end/core/root/ExperimentNames.ts +1 -0
- package/front_end/entrypoints/main/MainImpl.ts +8 -0
- package/front_end/generated/InspectorBackendCommands.ts +3 -1
- package/front_end/generated/SupportedCSSProperties.js +2 -2
- package/front_end/generated/protocol-mapping.d.ts +13 -0
- package/front_end/generated/protocol-proxy-api.d.ts +12 -0
- package/front_end/generated/protocol.ts +75 -0
- package/front_end/models/ai_assistance/agents/AiAgent.ts +24 -1
- package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgent.ts +320 -26
- package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgentOverlay.ts +87 -0
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +8 -8
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +79 -48
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +16 -2
- package/front_end/models/computed_style/ComputedStyleModel.ts +40 -6
- package/front_end/models/javascript_metadata/NativeFunctions.js +6 -6
- package/front_end/panels/accessibility/AXBreadcrumbsPane.ts +5 -3
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +39 -7
- package/front_end/panels/ai_assistance/README.md +61 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +141 -27
- package/front_end/panels/ai_assistance/components/ChatView.ts +5 -1
- package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +55 -1
- package/front_end/panels/ai_assistance/components/WalkthroughView.ts +19 -7
- package/front_end/panels/ai_assistance/components/chatMessage.css +30 -0
- package/front_end/panels/ai_assistance/components/walkthroughView.css +12 -7
- package/front_end/panels/animation/AnimationGroupPreviewUI.ts +1 -1
- package/front_end/panels/application/CookieItemsView.ts +194 -134
- package/front_end/panels/application/DeviceBoundSessionsTreeElement.ts +1 -1
- package/front_end/panels/application/ServiceWorkerUpdateCycleView.ts +1 -0
- package/front_end/panels/application/StorageItemsToolbar.ts +25 -2
- package/front_end/panels/application/components/BackForwardCacheView.ts +4 -2
- package/front_end/panels/application/cookieItemsView.css +28 -26
- package/front_end/panels/autofill/AutofillView.ts +1 -1
- package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +161 -154
- package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +1 -0
- package/front_end/panels/browser_debugger/domBreakpointsSidebarPane.css +58 -36
- package/front_end/panels/console/ConsoleViewMessage.ts +2 -1
- package/front_end/panels/console/consoleView.css +7 -2
- package/front_end/panels/elements/ComputedStyleWidget.ts +16 -26
- package/front_end/panels/elements/ElementsPanel.ts +26 -3
- package/front_end/panels/elements/ElementsTreeElement.ts +1 -0
- package/front_end/panels/elements/LayoutPane.ts +8 -7
- package/front_end/panels/elements/StandaloneStylesContainer.ts +254 -0
- package/front_end/panels/elements/StylePropertyTreeElement.ts +33 -0
- package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +148 -1
- package/front_end/panels/elements/components/ComputedStyleTrace.ts +4 -0
- package/front_end/panels/elements/components/ElementsBreadcrumbs.ts +1 -1
- package/front_end/panels/elements/components/StylePropertyEditor.ts +2 -1
- package/front_end/panels/elements/components/computedStyleProperty.css +1 -1
- package/front_end/panels/elements/elements-meta.ts +3 -5
- package/front_end/panels/elements/elements.ts +2 -0
- package/front_end/panels/elements/stylePropertiesTreeOutline.css +6 -0
- package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +1 -1
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +1 -1
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplay.ts +1 -1
- package/front_end/panels/media/PlayerListView.ts +1 -1
- package/front_end/panels/network/NetworkLogViewColumns.ts +2 -1
- package/front_end/panels/network/components/RequestHeaderSection.ts +1 -1
- package/front_end/panels/protocol_monitor/JSONEditor.ts +1 -1
- package/front_end/panels/recorder/components/RecordingListView.ts +1 -1
- package/front_end/panels/recorder/components/StepEditor.ts +3 -3
- package/front_end/panels/settings/KeybindsSettingsTab.ts +2 -1
- package/front_end/panels/sources/components/HeadersView.ts +2 -2
- package/front_end/panels/timeline/components/BreadcrumbsUI.ts +1 -1
- package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +1 -1
- package/front_end/panels/timeline/components/metricCard.css +0 -4
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Navigation.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Navigation.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Navigation.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserContext.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserContext.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +6 -6
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Navigation.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Navigation.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Navigation.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserContext.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserContext.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/package.json +4 -4
- package/front_end/third_party/puppeteer/package/src/bidi/core/Navigation.ts +1 -0
- package/front_end/third_party/puppeteer/package/src/cdp/BrowserContext.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +1 -0
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/ui/components/suggestion_input/SuggestionInput.ts +7 -12
- package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +13 -2
- package/front_end/ui/components/tree_outline/TreeOutline.ts +6 -2
- package/front_end/ui/components/tree_outline/treeOutline.css +5 -0
- package/front_end/ui/legacy/ListControl.ts +5 -3
- package/front_end/ui/legacy/ListWidget.ts +1 -1
- package/front_end/ui/legacy/SoftContextMenu.ts +2 -1
- package/front_end/ui/legacy/Treeoutline.ts +1 -0
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +44 -24
- package/front_end/ui/legacy/components/data_grid/DataGrid.ts +4 -2
- package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +1 -1
- package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +31 -0
- package/front_end/ui/visual_logging/Debugging.ts +4 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import type * as Common from '../../../core/common/common.js';
|
|
6
6
|
import * as Host from '../../../core/host/host.js';
|
|
7
|
+
import * as i18n from '../../../core/i18n/i18n.js';
|
|
7
8
|
import type * as Platform from '../../../core/platform/platform.js';
|
|
8
9
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
9
10
|
import * as Bindings from '../../bindings/bindings.js';
|
|
@@ -20,9 +21,18 @@ import {
|
|
|
20
21
|
type ContextResponse,
|
|
21
22
|
ConversationContext,
|
|
22
23
|
type FunctionCallHandlerResult,
|
|
24
|
+
type FunctionHandlerOptions,
|
|
25
|
+
type MultimodalInput,
|
|
23
26
|
type RequestOptions,
|
|
27
|
+
type ResponseData,
|
|
24
28
|
ResponseType,
|
|
25
29
|
} from './AiAgent.js';
|
|
30
|
+
import {
|
|
31
|
+
injectOverlay,
|
|
32
|
+
removeOverlay,
|
|
33
|
+
} from './BreakpointDebuggerAgentOverlay.js';
|
|
34
|
+
|
|
35
|
+
const lockedString = i18n.i18n.lockedString;
|
|
26
36
|
|
|
27
37
|
// This is a temporary agent for a GreenDev prototype.
|
|
28
38
|
// The preamble is not on the server and you should not build on top of this.
|
|
@@ -39,20 +49,24 @@ You have two modes of operation that you can switch between and control:
|
|
|
39
49
|
**Workflow**:
|
|
40
50
|
1. **Hypothesize**: Read the code ('getFunctionSource', 'getPreviousLines', 'getNextLines') to understand the logic.
|
|
41
51
|
2. **Set Trap**: Identify the critical line where state corruption likely occurred or lines that can lead you to that place. Use 'setBreakpoint' on that line.
|
|
42
|
-
3. **Wait**: Call '
|
|
52
|
+
3. **Wait**: Call 'waitForUserActionToTriggerBreakpoint'. This will suspend your execution until the user triggers the breakpoint. You CANNOT proceed until this tool returns.
|
|
43
53
|
4. **Inspect**: Using 'getExecutionLocation' check exactly where you are paused.
|
|
44
54
|
5. **Analyze**: When paused (Runtime Mode), use 'getScopeVariables' and 'getCallStack' to verify your hypothesis. Check variables in multiple scopes and look up the call stack to see where bad data came from.
|
|
45
55
|
6. **Step**: Use 'stepInto' to investigate function calls on the current line. Use 'stepOut' to return to the caller. Use 'stepOver' to move to the next line.
|
|
46
56
|
7. **Trace Back**: If the current function isn't the root cause, use 'getCallStack' to find the caller, and repeat the analysis there.
|
|
47
57
|
8. **Root Cause**: Explain exactly how the runtime state contradicts the expected logic and point to the specific line of code that is the root cause.
|
|
58
|
+
9. **Apply Fix**: Use the 'testFixInConsole' tool to overwrite the problematic code in the current session.
|
|
59
|
+
10. **Verify**: The fix is applied but NOT verified. You MUST run the code again to verify the fix worked.
|
|
60
|
+
11. **Finish**: If the fix worked, you may output the solution and finish the execution.
|
|
48
61
|
|
|
49
62
|
**Rules**:
|
|
50
|
-
- **NEVER FINISH** execution until you have found the root cause
|
|
51
|
-
- **ACTION OVER TALK**: If you need the user to trigger a breakpoint, do NOT just ask them in text. You **MUST** call '
|
|
52
|
-
- **STATIC MODE**: If you are in STATIC MODE and need to see variables: 1. 'setBreakpoint', 2. '
|
|
53
|
-
- **ALREADY PAUSED?**: If 'setBreakpoint' warns you that you are already paused, **DO NOT** call '
|
|
63
|
+
- **NEVER FINISH** execution until you have found the root cause and verified the fix.
|
|
64
|
+
- **ACTION OVER TALK**: If you need the user to trigger a breakpoint, do NOT just ask them in text. You **MUST** call 'waitForUserActionToTriggerBreakpoint'. This tool will block and wait for the user to act.
|
|
65
|
+
- **STATIC MODE**: If you are in STATIC MODE and need to see variables: 1. 'setBreakpoint', 2. 'waitForUserActionToTriggerBreakpoint'. **DO NOT STOP** to ask the user. Investigate code and set breakpoints to find the root cause.
|
|
66
|
+
- **ALREADY PAUSED?**: If 'setBreakpoint' warns you that you are already paused, **DO NOT** call 'waitForUserActionToTriggerBreakpoint'. Start inspecting immediately. You can set more breakpoints while paused, but to call 'waitForUserActionToTriggerBreakpoint' again you MUST be in static state.
|
|
54
67
|
- **USE TOOLS EXCESSIVELY**: checking one thing is often not enough. Check everything you can thinks of.
|
|
55
|
-
- **CHECK LOCATION**: If you are not sure where you are, call 'getExecutionLocation' after '
|
|
68
|
+
- **CHECK LOCATION**: If you are not sure where you are, call 'getExecutionLocation' after 'waitForUserActionToTriggerBreakpoint' or any step command to confirm where you are.
|
|
69
|
+
- **INITIAL CONTEXT**: The breakpoint provided in the context is ALREADY SET. Do NOT set it again. Start by setting additional breakpoints if needed, or, if no additional breakpoints within the code you see make sense, call 'waitForUserActionToTriggerBreakpoint'.
|
|
56
70
|
|
|
57
71
|
**Execution Control when you are currently on a breakpoint**:
|
|
58
72
|
- **stepInto**: ESSENTIAL for entering function calls on the current line. Use this heavily when you suspect the issue is inside a called function.
|
|
@@ -60,6 +74,8 @@ You have two modes of operation that you can switch between and control:
|
|
|
60
74
|
- **stepOut**: Return to the caller. If you are currently on a breakpoint, 'stepOut' will move you to the caller and pause again. **It often makes sense to 'stepOut' after you have investigated a function with 'stepInto' and verified it is correct.**
|
|
61
75
|
- **stepInto, stepOver, stepOut**: After any step command, always call 'getScopeVariables' to see how the state evolved.
|
|
62
76
|
- **listBreakpoints**: Use this to see all active breakpoints. Do not try to set a breakpoint that is already active.
|
|
77
|
+
- **removeBreakpoint / removeAllBreakpoints**: Use this to remove breakpoints. This is especially useful when you want to speed up verifying a fix.
|
|
78
|
+
- **CLEANUP AFTER FIX**: After a fix is suggested and worked, you MUST remove all breakpoints and call 'resume' to resume the execution of the page.
|
|
63
79
|
`;
|
|
64
80
|
|
|
65
81
|
export class BreakpointContext extends ConversationContext<Workspace.UISourceCode.UILocation> {
|
|
@@ -108,6 +124,13 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
108
124
|
},
|
|
109
125
|
required: ['url', 'lineNumber'],
|
|
110
126
|
},
|
|
127
|
+
displayInfoFromArgs: (args: {url: string, lineNumber: number}) => {
|
|
128
|
+
const uiSourceCode = Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodeForURL(
|
|
129
|
+
args.url as Platform.DevToolsPath.UrlString);
|
|
130
|
+
return {
|
|
131
|
+
title: `Reading function source for ${uiSourceCode?.displayName()}:${args.lineNumber}`,
|
|
132
|
+
};
|
|
133
|
+
},
|
|
111
134
|
handler: async (args: {url: string, lineNumber: number}) => {
|
|
112
135
|
const result = await this.#getFunctionSource(args);
|
|
113
136
|
debugLog('getFunctionSource for ', JSON.stringify(args), '->', JSON.stringify(result));
|
|
@@ -137,6 +160,13 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
137
160
|
},
|
|
138
161
|
required: ['url', 'lineNumber', 'direction'],
|
|
139
162
|
},
|
|
163
|
+
displayInfoFromArgs: (args: {url: string, lineNumber: number, direction: 'before'|'after'}) => {
|
|
164
|
+
const uiSourceCode = Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodeForURL(
|
|
165
|
+
args.url as Platform.DevToolsPath.UrlString);
|
|
166
|
+
return {
|
|
167
|
+
title: `Reading code ${args.direction} ${uiSourceCode?.displayName()}:${args.lineNumber}`,
|
|
168
|
+
};
|
|
169
|
+
},
|
|
140
170
|
handler: async (args: {url: string, lineNumber: number, direction: 'before'|'after'}) => {
|
|
141
171
|
const result = await this.#getCodeLines(args);
|
|
142
172
|
debugLog('getCodeLines result', JSON.stringify(result));
|
|
@@ -151,6 +181,11 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
151
181
|
properties: {},
|
|
152
182
|
required: [],
|
|
153
183
|
},
|
|
184
|
+
displayInfoFromArgs: () => {
|
|
185
|
+
return {
|
|
186
|
+
title: 'Reading call stack',
|
|
187
|
+
};
|
|
188
|
+
},
|
|
154
189
|
handler: async () => {
|
|
155
190
|
const result = await this.#getCallStack();
|
|
156
191
|
debugLog('getCallStack result', JSON.stringify(result));
|
|
@@ -165,6 +200,11 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
165
200
|
properties: {},
|
|
166
201
|
required: [],
|
|
167
202
|
},
|
|
203
|
+
displayInfoFromArgs: () => {
|
|
204
|
+
return {
|
|
205
|
+
title: 'Reading scope variables',
|
|
206
|
+
};
|
|
207
|
+
},
|
|
168
208
|
handler: async () => {
|
|
169
209
|
const result = await this.#getScopeVariables();
|
|
170
210
|
debugLog('getScopeVariables result', JSON.stringify(result));
|
|
@@ -179,6 +219,11 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
179
219
|
properties: {},
|
|
180
220
|
required: [],
|
|
181
221
|
},
|
|
222
|
+
displayInfoFromArgs: () => {
|
|
223
|
+
return {
|
|
224
|
+
title: 'Listing breakpoints',
|
|
225
|
+
};
|
|
226
|
+
},
|
|
182
227
|
handler: async () => {
|
|
183
228
|
const result = await this.#listBreakpoints();
|
|
184
229
|
debugLog('listBreakpoints result', JSON.stringify(result));
|
|
@@ -202,6 +247,13 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
202
247
|
},
|
|
203
248
|
required: ['url', 'lineNumber'],
|
|
204
249
|
},
|
|
250
|
+
displayInfoFromArgs: (args: {url: string, lineNumber: number}) => {
|
|
251
|
+
const uiSourceCode = Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodeForURL(
|
|
252
|
+
args.url as Platform.DevToolsPath.UrlString);
|
|
253
|
+
return {
|
|
254
|
+
title: `Setting breakpoint at ${uiSourceCode?.displayName() ?? args.url}:${args.lineNumber}`,
|
|
255
|
+
};
|
|
256
|
+
},
|
|
205
257
|
handler: async (args: {url: string, lineNumber: number}) => {
|
|
206
258
|
debugLog('setBreakpoint requested', args);
|
|
207
259
|
const result = await this.#setBreakpoint(args);
|
|
@@ -209,18 +261,80 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
209
261
|
return result;
|
|
210
262
|
},
|
|
211
263
|
});
|
|
264
|
+
this.declareFunction('removeBreakpoint', {
|
|
265
|
+
description: 'Remove a breakpoint at a specific location.',
|
|
266
|
+
parameters: {
|
|
267
|
+
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
268
|
+
description: 'Location to remove the breakpoint from',
|
|
269
|
+
properties: {
|
|
270
|
+
url: {
|
|
271
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
272
|
+
description: 'The URL of the file',
|
|
273
|
+
},
|
|
274
|
+
lineNumber: {
|
|
275
|
+
type: Host.AidaClient.ParametersTypes.INTEGER,
|
|
276
|
+
description: 'The 1-based line number to remove the breakpoint from',
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
required: ['url', 'lineNumber'],
|
|
280
|
+
},
|
|
281
|
+
displayInfoFromArgs: (args: {url: string, lineNumber: number}) => {
|
|
282
|
+
const uiSourceCode = Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodeForURL(
|
|
283
|
+
args.url as Platform.DevToolsPath.UrlString);
|
|
284
|
+
return {
|
|
285
|
+
title: `Removing breakpoint at ${uiSourceCode?.displayName() ?? args.url}:${args.lineNumber}`,
|
|
286
|
+
};
|
|
287
|
+
},
|
|
288
|
+
handler: async (args: {url: string, lineNumber: number}) => {
|
|
289
|
+
debugLog('removeBreakpoint requested', args);
|
|
290
|
+
const result = await this.#removeBreakpoint(args);
|
|
291
|
+
debugLog('removeBreakpoint result', JSON.stringify(result));
|
|
292
|
+
return result;
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
this.declareFunction('removeAllBreakpoints', {
|
|
296
|
+
description: 'Remove all active breakpoints.',
|
|
297
|
+
parameters: {
|
|
298
|
+
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
299
|
+
description: 'No parameters required',
|
|
300
|
+
properties: {},
|
|
301
|
+
required: [],
|
|
302
|
+
},
|
|
303
|
+
displayInfoFromArgs: () => {
|
|
304
|
+
return {
|
|
305
|
+
title: 'Removing all breakpoints',
|
|
306
|
+
};
|
|
307
|
+
},
|
|
308
|
+
handler: async () => {
|
|
309
|
+
debugLog('removeAllBreakpoints requested');
|
|
310
|
+
const breakpointManager = Breakpoints.BreakpointManager.BreakpointManager.instance();
|
|
311
|
+
const allBreakpoints = breakpointManager.allBreakpointLocations();
|
|
312
|
+
for (const bp of allBreakpoints) {
|
|
313
|
+
await bp.breakpoint.remove(false);
|
|
314
|
+
}
|
|
315
|
+
return {result: {status: 'All breakpoints removed.'}};
|
|
316
|
+
},
|
|
317
|
+
});
|
|
212
318
|
this.declareFunction('resume', {
|
|
213
|
-
description: 'Resume execution
|
|
319
|
+
description: 'Resume execution. Always use this after applying a fix to resume the page execution.',
|
|
214
320
|
parameters: {
|
|
215
321
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
216
322
|
description: 'No parameters required',
|
|
217
323
|
properties: {},
|
|
218
324
|
required: [],
|
|
219
325
|
},
|
|
326
|
+
displayInfoFromArgs: () => {
|
|
327
|
+
return {
|
|
328
|
+
title: 'Resuming execution',
|
|
329
|
+
};
|
|
330
|
+
},
|
|
220
331
|
handler: async () => {
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
332
|
+
const targetManager = SDK.TargetManager.TargetManager.instance();
|
|
333
|
+
const debuggerModel = targetManager.models(SDK.DebuggerModel.DebuggerModel).find(m => m.isPaused());
|
|
334
|
+
if (debuggerModel) {
|
|
335
|
+
debuggerModel.resume();
|
|
336
|
+
}
|
|
337
|
+
return {result: {status: 'Execution resumed.'}};
|
|
224
338
|
},
|
|
225
339
|
});
|
|
226
340
|
this.declareFunction('stepOver', {
|
|
@@ -231,6 +345,11 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
231
345
|
properties: {},
|
|
232
346
|
required: [],
|
|
233
347
|
},
|
|
348
|
+
displayInfoFromArgs: () => {
|
|
349
|
+
return {
|
|
350
|
+
title: 'Stepping over',
|
|
351
|
+
};
|
|
352
|
+
},
|
|
234
353
|
handler: async () => {
|
|
235
354
|
const result = await this.#debuggerAction(model => model.stepOver());
|
|
236
355
|
debugLog('stepOver result', JSON.stringify(result));
|
|
@@ -246,6 +365,11 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
246
365
|
properties: {},
|
|
247
366
|
required: [],
|
|
248
367
|
},
|
|
368
|
+
displayInfoFromArgs: () => {
|
|
369
|
+
return {
|
|
370
|
+
title: 'Stepping into',
|
|
371
|
+
};
|
|
372
|
+
},
|
|
249
373
|
handler: async () => {
|
|
250
374
|
const result = await this.#debuggerAction(model => model.stepInto());
|
|
251
375
|
debugLog('stepInto result', JSON.stringify(result));
|
|
@@ -261,6 +385,11 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
261
385
|
properties: {},
|
|
262
386
|
required: [],
|
|
263
387
|
},
|
|
388
|
+
displayInfoFromArgs: () => {
|
|
389
|
+
return {
|
|
390
|
+
title: 'Stepping out',
|
|
391
|
+
};
|
|
392
|
+
},
|
|
264
393
|
handler: async () => {
|
|
265
394
|
const result = await this.#debuggerAction(model => model.stepOut());
|
|
266
395
|
debugLog('stepOut result', JSON.stringify(result));
|
|
@@ -298,12 +427,97 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
298
427
|
properties: {},
|
|
299
428
|
required: [],
|
|
300
429
|
},
|
|
430
|
+
displayInfoFromArgs: () => {
|
|
431
|
+
return {
|
|
432
|
+
title: 'Getting execution location',
|
|
433
|
+
};
|
|
434
|
+
},
|
|
301
435
|
handler: async () => {
|
|
302
436
|
const result = await this.#getExecutionLocation();
|
|
303
437
|
debugLog('getExecutionLocation ', JSON.stringify(result));
|
|
304
438
|
return result;
|
|
305
439
|
},
|
|
306
440
|
});
|
|
441
|
+
|
|
442
|
+
this.declareFunction('testFixInConsole', {
|
|
443
|
+
description:
|
|
444
|
+
'Tests a JavaScript code snippet in the current execution context to overwrite the problematic code or state. After running this, verify the fix worked.',
|
|
445
|
+
parameters: {
|
|
446
|
+
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
447
|
+
description: 'Provide the code to evaluate to test the fix',
|
|
448
|
+
properties: {
|
|
449
|
+
code: {
|
|
450
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
451
|
+
description: 'The JavaScript code to evaluate in the console to test the fix.',
|
|
452
|
+
},
|
|
453
|
+
explanation: {
|
|
454
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
455
|
+
description: 'Explanation for why this code fixes the issue.',
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
required: ['code', 'explanation'],
|
|
459
|
+
},
|
|
460
|
+
displayInfoFromArgs: (args: {code: string, explanation: string}) => {
|
|
461
|
+
return {
|
|
462
|
+
title: 'Testing a fix in console',
|
|
463
|
+
thought: args.explanation,
|
|
464
|
+
action: args.code,
|
|
465
|
+
};
|
|
466
|
+
},
|
|
467
|
+
handler: async (args: {code: string, explanation: string}, options?: FunctionHandlerOptions) => {
|
|
468
|
+
debugLog('testFixInConsole requested', args);
|
|
469
|
+
if (options?.approved === false) {
|
|
470
|
+
return {error: 'Fix rejected by the user.'};
|
|
471
|
+
}
|
|
472
|
+
if (!options?.approved) {
|
|
473
|
+
return {
|
|
474
|
+
requiresApproval: true,
|
|
475
|
+
description: lockedString('This code may modify page content. Continue?'),
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const targetManager = SDK.TargetManager.TargetManager.instance();
|
|
480
|
+
const debuggerModel = targetManager.models(SDK.DebuggerModel.DebuggerModel).find(m => m.isPaused());
|
|
481
|
+
|
|
482
|
+
if (!debuggerModel) {
|
|
483
|
+
return {error: 'Execution is not paused.'};
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
const details = debuggerModel.debuggerPausedDetails();
|
|
487
|
+
const callFrame = details?.callFrames[0];
|
|
488
|
+
if (!callFrame) {
|
|
489
|
+
return {error: 'No call frame available.'};
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
const result = await callFrame.evaluate({
|
|
493
|
+
expression: args.code,
|
|
494
|
+
objectGroup: 'console',
|
|
495
|
+
includeCommandLineAPI: true,
|
|
496
|
+
silent: false,
|
|
497
|
+
returnByValue: false,
|
|
498
|
+
generatePreview: true
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
if (!result) {
|
|
502
|
+
return {error: 'Failed to evaluate the fix.'};
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
if ('error' in result) {
|
|
506
|
+
return {error: 'Error applying fix: ' + (result as unknown as {error: string}).error};
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (result.exceptionDetails) {
|
|
510
|
+
return {error: 'Fix threw an exception: ' + result.exceptionDetails.text};
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
return {
|
|
514
|
+
result: {
|
|
515
|
+
status:
|
|
516
|
+
'Code evaluated successfully. Fix applied. PROCEED TO VERIFICATION: Call "resume" and ask the user to "run the code again" to verify.'
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
},
|
|
520
|
+
});
|
|
307
521
|
}
|
|
308
522
|
|
|
309
523
|
async #getFunctionSource(args: {url: string, lineNumber: number}):
|
|
@@ -407,7 +621,7 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
407
621
|
if (!debuggerModel) {
|
|
408
622
|
return {
|
|
409
623
|
error:
|
|
410
|
-
'Execution is not paused. I cannot access runtime variables or the call stack. I am currently in STATIC MODE. I must set a breakpoint and use
|
|
624
|
+
'Execution is not paused. I cannot access runtime variables or the call stack. I am currently in STATIC MODE. I must set a breakpoint and use waitForUserActionToTriggerBreakpoint to enter RUNTIME MODE.'
|
|
411
625
|
};
|
|
412
626
|
}
|
|
413
627
|
|
|
@@ -439,7 +653,7 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
439
653
|
if (!debuggerModel) {
|
|
440
654
|
return {
|
|
441
655
|
error:
|
|
442
|
-
'Execution is not paused. I cannot access runtime variables or the call stack. I am currently in STATIC MODE. I must set a breakpoint and use
|
|
656
|
+
'Execution is not paused. I cannot access runtime variables or the call stack. I am currently in STATIC MODE. I must set a breakpoint and use waitForUserActionToTriggerBreakpoint to enter RUNTIME MODE.'
|
|
443
657
|
};
|
|
444
658
|
}
|
|
445
659
|
|
|
@@ -566,7 +780,7 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
566
780
|
if (callFrame) {
|
|
567
781
|
const pausedLoc = `${callFrame.script.contentURL()}:${callFrame.location().lineNumber + 1}`;
|
|
568
782
|
warning = ` WARNING: You are already PAUSED at ${
|
|
569
|
-
pausedLoc}. \n1. If this is where you want to be, call 'getExecutionLocation' and inspect variables. \n2. If you want to wait for the NEW breakpoint, you MUST call '
|
|
783
|
+
pausedLoc}. \n1. If this is where you want to be, call 'getExecutionLocation' and inspect variables. \n2. If you want to wait for the NEW breakpoint, you MUST call 'waitForUserActionToTriggerBreakpoint' (which will resume execution).`;
|
|
570
784
|
}
|
|
571
785
|
}
|
|
572
786
|
|
|
@@ -575,8 +789,9 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
575
789
|
result: {
|
|
576
790
|
status: `Breakpoint requested at ${args.url}:${args.lineNumber}, but ACTUALLY resolved to line ${
|
|
577
791
|
actualLineNumber}.${
|
|
578
|
-
warning ?
|
|
579
|
-
|
|
792
|
+
warning ?
|
|
793
|
+
'\n' + warning :
|
|
794
|
+
' You must now call waitForUserActionToTriggerBreakpoint and ask the user to trigger the action.'}`
|
|
580
795
|
}
|
|
581
796
|
};
|
|
582
797
|
}
|
|
@@ -584,11 +799,33 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
584
799
|
return {
|
|
585
800
|
result: {
|
|
586
801
|
status: `Breakpoint set at ${args.url}:${args.lineNumber}.${
|
|
587
|
-
warning ?
|
|
802
|
+
warning ?
|
|
803
|
+
'\n' + warning :
|
|
804
|
+
' You must now call waitForUserActionToTriggerBreakpoint and ask the user to trigger the action.'}`
|
|
588
805
|
}
|
|
589
806
|
};
|
|
590
807
|
}
|
|
591
808
|
|
|
809
|
+
async #removeBreakpoint(args: {url: string, lineNumber: number}):
|
|
810
|
+
Promise<FunctionCallHandlerResult<{status: string}>> {
|
|
811
|
+
const uiSourceCode =
|
|
812
|
+
Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodeForURL(args.url as Platform.DevToolsPath.UrlString);
|
|
813
|
+
if (!uiSourceCode) {
|
|
814
|
+
return {error: `File not found: ${args.url}`};
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
const breakpointLocations =
|
|
818
|
+
Breakpoints.BreakpointManager.BreakpointManager.instance().breakpointLocationsForUISourceCode(uiSourceCode);
|
|
819
|
+
const breakpointLocation = breakpointLocations.find(bp => bp.uiLocation.lineNumber === args.lineNumber - 1);
|
|
820
|
+
|
|
821
|
+
if (!breakpointLocation) {
|
|
822
|
+
return {result: {status: `Breakpoint not found at ${args.url}:${args.lineNumber}.`}};
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
await breakpointLocation.breakpoint.remove(false);
|
|
826
|
+
return {result: {status: `Breakpoint removed at ${args.url}:${args.lineNumber}.`}};
|
|
827
|
+
}
|
|
828
|
+
|
|
592
829
|
async #debuggerAction(action: (model: SDK.DebuggerModel.DebuggerModel) => void):
|
|
593
830
|
Promise<FunctionCallHandlerResult<{status: string}>> {
|
|
594
831
|
const targetManager = SDK.TargetManager.TargetManager.instance();
|
|
@@ -598,8 +835,8 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
598
835
|
return {error: 'Execution is not paused. I cannot step or resume in STATIC MODE.'};
|
|
599
836
|
}
|
|
600
837
|
|
|
601
|
-
// Only resolve when next pause event is triggered
|
|
602
|
-
return await this.#waitForNextPause(() => action(debuggerModel));
|
|
838
|
+
// Only resolve when next pause event is triggered (with a 3 second timeout so the agent doesn't hang)
|
|
839
|
+
return await this.#waitForNextPause(() => action(debuggerModel), 3000);
|
|
603
840
|
}
|
|
604
841
|
|
|
605
842
|
async #waitForUserActionToTriggerBreakpoint(): Promise<FunctionCallHandlerResult<{status: string}>> {
|
|
@@ -610,14 +847,23 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
610
847
|
return {error: 'No debugger attached'};
|
|
611
848
|
}
|
|
612
849
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
850
|
+
// While waiting for the user to trigger the breakpoint, show an overlay on top of the page.
|
|
851
|
+
// This is to make it clear to the user that they need to trigger the
|
|
852
|
+
// breakpoint for the agent to continue the debugging process.
|
|
853
|
+
void injectOverlay();
|
|
854
|
+
|
|
855
|
+
try {
|
|
856
|
+
return await this.#waitForNextPause(() => {
|
|
857
|
+
// Resume all paused models before waiting for the next breakpoint
|
|
858
|
+
for (const model of debuggerModels) {
|
|
859
|
+
if (model.isPaused()) {
|
|
860
|
+
model.resume();
|
|
861
|
+
}
|
|
618
862
|
}
|
|
619
|
-
}
|
|
620
|
-
}
|
|
863
|
+
});
|
|
864
|
+
} finally {
|
|
865
|
+
void removeOverlay();
|
|
866
|
+
}
|
|
621
867
|
}
|
|
622
868
|
|
|
623
869
|
/**
|
|
@@ -626,14 +872,20 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
626
872
|
*
|
|
627
873
|
* @param triggerAction Optional action to execute (e.g. resume, step) that is expected to lead to a pause.
|
|
628
874
|
*/
|
|
629
|
-
async #waitForNextPause(triggerAction: () => void = () => {}):
|
|
875
|
+
async #waitForNextPause(triggerAction: () => void = () => {}, timeoutMs?: number):
|
|
876
|
+
Promise<FunctionCallHandlerResult<{status: string}>> {
|
|
630
877
|
const targetManager = SDK.TargetManager.TargetManager.instance();
|
|
631
878
|
|
|
632
879
|
return await new Promise(resolve => {
|
|
880
|
+
let timeoutId: ReturnType<typeof setTimeout>;
|
|
881
|
+
|
|
633
882
|
const listener =
|
|
634
883
|
async(event: Common.EventTarget.EventTargetEvent<SDK.DebuggerModel.DebuggerModel>): Promise<void> => {
|
|
635
884
|
targetManager.removeModelListener(
|
|
636
885
|
SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, listener);
|
|
886
|
+
if (timeoutId) {
|
|
887
|
+
clearTimeout(timeoutId);
|
|
888
|
+
}
|
|
637
889
|
const model = event.data;
|
|
638
890
|
const details = model.debuggerPausedDetails();
|
|
639
891
|
const callFrame = details?.callFrames[0];
|
|
@@ -655,6 +907,19 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
655
907
|
targetManager.addModelListener(
|
|
656
908
|
SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, listener);
|
|
657
909
|
|
|
910
|
+
if (timeoutMs !== undefined) {
|
|
911
|
+
timeoutId = setTimeout(() => {
|
|
912
|
+
targetManager.removeModelListener(
|
|
913
|
+
SDK.DebuggerModel.DebuggerModel, SDK.DebuggerModel.Events.DebuggerPaused, listener);
|
|
914
|
+
resolve({
|
|
915
|
+
result: {
|
|
916
|
+
status:
|
|
917
|
+
'Execution resumed but did not pause again. There is nothing to step into or the execution finished.'
|
|
918
|
+
}
|
|
919
|
+
});
|
|
920
|
+
}, timeoutMs);
|
|
921
|
+
}
|
|
922
|
+
|
|
658
923
|
// Execute the action that will eventually trigger the pause
|
|
659
924
|
triggerAction();
|
|
660
925
|
});
|
|
@@ -719,4 +984,33 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
719
984
|
get options(): RequestOptions {
|
|
720
985
|
return {temperature: 0, modelId: undefined};
|
|
721
986
|
}
|
|
987
|
+
|
|
988
|
+
override async *
|
|
989
|
+
run(
|
|
990
|
+
initialQuery: string,
|
|
991
|
+
options: {
|
|
992
|
+
selected: ConversationContext<Workspace.UISourceCode.UILocation>|null,
|
|
993
|
+
signal?: AbortSignal,
|
|
994
|
+
},
|
|
995
|
+
multimodalInput?: MultimodalInput,
|
|
996
|
+
): AsyncGenerator<ResponseData, void, void> {
|
|
997
|
+
try {
|
|
998
|
+
yield* super.run(initialQuery, options, multimodalInput);
|
|
999
|
+
} finally {
|
|
1000
|
+
// When the agent is done, remove all breakpoints and exit paused state.
|
|
1001
|
+
const breakpointManager = Breakpoints.BreakpointManager.BreakpointManager.instance();
|
|
1002
|
+
const allBreakpoints = breakpointManager.allBreakpointLocations();
|
|
1003
|
+
for (const bp of allBreakpoints) {
|
|
1004
|
+
await bp.breakpoint.remove(false);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
const targetManager = SDK.TargetManager.TargetManager.instance();
|
|
1008
|
+
const debuggerModels = targetManager.models(SDK.DebuggerModel.DebuggerModel);
|
|
1009
|
+
for (const model of debuggerModels) {
|
|
1010
|
+
if (model.isPaused()) {
|
|
1011
|
+
model.resume();
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
722
1016
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Copyright 2026 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* This file contains the overlay script that is injected into the page when the
|
|
7
|
+
* BreakpointDebuggerAgent is waiting for a user action.
|
|
8
|
+
*
|
|
9
|
+
* This is a temporary solution for the prototype. In the long term, we should
|
|
10
|
+
* use a proper overlay or a different mechanism to communicate with the user,
|
|
11
|
+
* rather than injecting a script into the page. This approach is fine for the
|
|
12
|
+
* prototype but should be replaced before production.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import * as SDK from '../../../core/sdk/sdk.js';
|
|
16
|
+
|
|
17
|
+
export async function injectOverlay(): Promise<void> {
|
|
18
|
+
const targetManager = SDK.TargetManager.TargetManager.instance();
|
|
19
|
+
const primaryTarget = targetManager.primaryPageTarget();
|
|
20
|
+
|
|
21
|
+
await primaryTarget?.runtimeAgent().invoke_evaluate({
|
|
22
|
+
expression: WAIT_FOR_USER_ACTION_OVERLAY_SCRIPT,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function removeOverlay(): Promise<void> {
|
|
27
|
+
const targetManager = SDK.TargetManager.TargetManager.instance();
|
|
28
|
+
const primaryTarget = targetManager.primaryPageTarget();
|
|
29
|
+
|
|
30
|
+
await primaryTarget?.runtimeAgent().invoke_evaluate({
|
|
31
|
+
expression: REMOVE_OVERLAY_SCRIPT,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const WAIT_FOR_USER_ACTION_OVERLAY_SCRIPT = `
|
|
36
|
+
(function() {
|
|
37
|
+
const devtoolsOverlayId = 'devtools-waiting-overlay';
|
|
38
|
+
let overlay = document.getElementById(devtoolsOverlayId);
|
|
39
|
+
if (!overlay) {
|
|
40
|
+
overlay = document.createElement('div');
|
|
41
|
+
overlay.id = devtoolsOverlayId;
|
|
42
|
+
overlay.style.position = 'fixed';
|
|
43
|
+
overlay.style.top = '0';
|
|
44
|
+
overlay.style.left = '0';
|
|
45
|
+
overlay.style.width = '100vw';
|
|
46
|
+
overlay.style.height = '100vh';
|
|
47
|
+
overlay.style.pointerEvents = 'none';
|
|
48
|
+
overlay.style.zIndex = '2147483647';
|
|
49
|
+
overlay.style.boxSizing = 'border-box';
|
|
50
|
+
overlay.style.border = '10px solid red';
|
|
51
|
+
overlay.style.animation = 'devtools-fade 1.5s infinite alternate';
|
|
52
|
+
const text = document.createElement('div');
|
|
53
|
+
text.innerText = 'Trigger the breakpoint again';
|
|
54
|
+
text.style.position = 'absolute';
|
|
55
|
+
text.style.top = '10px';
|
|
56
|
+
text.style.left = '50%';
|
|
57
|
+
text.style.transform = 'translateX(-50%)';
|
|
58
|
+
text.style.backgroundColor = 'red';
|
|
59
|
+
text.style.color = 'white';
|
|
60
|
+
text.style.padding = '10px 20px';
|
|
61
|
+
text.style.borderRadius = '5px';
|
|
62
|
+
text.style.fontFamily = 'system-ui, sans-serif';
|
|
63
|
+
text.style.fontSize = '16px';
|
|
64
|
+
text.style.fontWeight = 'bold';
|
|
65
|
+
text.style.boxShadow = '0 4px 6px rgba(0,0,0,0.1)';
|
|
66
|
+
overlay.appendChild(text);
|
|
67
|
+
|
|
68
|
+
const style = document.createElement('style');
|
|
69
|
+
style.id = devtoolsOverlayId + '-style';
|
|
70
|
+
style.innerText = '@keyframes devtools-fade { from { opacity: 0.5; } to { opacity: 1; } }';
|
|
71
|
+
// Head might not exist immediately on a completely blank page, fallback to documentElement
|
|
72
|
+
(document.head || document.documentElement).appendChild(style);
|
|
73
|
+
|
|
74
|
+
document.documentElement.appendChild(overlay);
|
|
75
|
+
}
|
|
76
|
+
})();
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
const REMOVE_OVERLAY_SCRIPT = `
|
|
80
|
+
(function() {
|
|
81
|
+
const devtoolsOverlayId = 'devtools-waiting-overlay';
|
|
82
|
+
const overlay = document.getElementById(devtoolsOverlayId);
|
|
83
|
+
if (overlay) overlay.remove();
|
|
84
|
+
const style = document.getElementById(devtoolsOverlayId + '-style');
|
|
85
|
+
if (style) style.remove();
|
|
86
|
+
})();
|
|
87
|
+
`;
|
|
@@ -48,12 +48,12 @@ Content:
|
|
|
48
48
|
"description": "",
|
|
49
49
|
"nullable": true,
|
|
50
50
|
"required": [
|
|
51
|
-
"
|
|
51
|
+
"id"
|
|
52
52
|
],
|
|
53
53
|
"properties": {
|
|
54
|
-
"
|
|
54
|
+
"id": {
|
|
55
55
|
"type": 1,
|
|
56
|
-
"description": "The
|
|
56
|
+
"description": "The id of the network request",
|
|
57
57
|
"nullable": false
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -72,18 +72,18 @@ Content:
|
|
|
72
72
|
},
|
|
73
73
|
{
|
|
74
74
|
"name": "selectSourceFile",
|
|
75
|
-
"description": "Selects a source file. Use this when asked about files on the page. Use listSourceFiles
|
|
75
|
+
"description": "Selects a source file. Use this when asked about files on the page. Use listSourceFiles to find the file ID.",
|
|
76
76
|
"parameters": {
|
|
77
77
|
"type": 6,
|
|
78
78
|
"description": "",
|
|
79
79
|
"nullable": true,
|
|
80
80
|
"required": [
|
|
81
|
-
"
|
|
81
|
+
"id"
|
|
82
82
|
],
|
|
83
83
|
"properties": {
|
|
84
|
-
"
|
|
85
|
-
"type":
|
|
86
|
-
"description": "The
|
|
84
|
+
"id": {
|
|
85
|
+
"type": 3,
|
|
86
|
+
"description": "The id (URL) of the file you want to select.",
|
|
87
87
|
"nullable": false
|
|
88
88
|
}
|
|
89
89
|
}
|