chrome-devtools-frontend 1.0.1559913 → 1.0.1561528
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/core/host/InspectorFrontendHostStub.ts +0 -3
- package/front_end/core/platform/ArrayUtilities.ts +13 -0
- package/front_end/core/root/Runtime.ts +0 -5
- package/front_end/core/sdk/DOMModel.ts +8 -0
- package/front_end/core/sdk/NetworkManager.ts +4 -0
- package/front_end/core/sdk/NetworkRequest.ts +9 -0
- package/front_end/core/sdk/OverlayModel.ts +20 -9
- package/front_end/entrypoints/main/MainImpl.ts +2 -1
- package/front_end/generated/InspectorBackendCommands.ts +4 -2
- package/front_end/generated/protocol-mapping.d.ts +7 -0
- package/front_end/generated/protocol-proxy-api.d.ts +5 -0
- package/front_end/generated/protocol.ts +24 -0
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +23 -22
- package/front_end/models/badges/UserBadges.ts +48 -16
- package/front_end/models/greendev/Prototypes.ts +6 -1
- package/front_end/models/trace/extras/TraceTree.ts +1 -1
- package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +8 -3
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +11 -142
- package/front_end/panels/ai_assistance/PatchWidget.ts +90 -72
- package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
- package/front_end/panels/ai_assistance/components/ChatInput.ts +701 -0
- package/front_end/panels/ai_assistance/components/ChatView.ts +71 -1268
- package/front_end/panels/ai_assistance/components/UserActionRow.ts +514 -31
- package/front_end/panels/ai_assistance/components/chatInput.css +387 -0
- package/front_end/panels/ai_assistance/components/chatView.css +38 -599
- package/front_end/panels/ai_assistance/components/userActionRow.css +230 -0
- package/front_end/panels/autofill/AutofillView.ts +2 -2
- package/front_end/panels/changes/ChangesView.ts +15 -1
- package/front_end/panels/changes/changesView.css +6 -0
- package/front_end/panels/common/BadgeNotification.ts +44 -58
- package/front_end/panels/common/CopyChangesToPrompt.ts +233 -0
- package/front_end/panels/common/common.ts +1 -0
- package/front_end/panels/elements/ElementsTreeElement.ts +183 -359
- package/front_end/panels/elements/ElementsTreeOutline.ts +0 -6
- package/front_end/panels/elements/ShortcutTreeElement.ts +57 -50
- package/front_end/panels/elements/StylePropertiesSection.ts +1 -3
- package/front_end/panels/elements/components/AdornerManager.ts +5 -149
- package/front_end/panels/issues/HiddenIssuesRow.ts +1 -2
- package/front_end/panels/issues/IssueKindView.ts +2 -4
- package/front_end/panels/issues/IssueView.ts +2 -4
- package/front_end/panels/network/NetworkDataGridNode.ts +65 -1
- package/front_end/panels/network/NetworkLogView.ts +2 -4
- package/front_end/panels/network/NetworkLogViewColumns.ts +9 -0
- package/front_end/panels/screencast/ScreencastApp.ts +1 -0
- package/front_end/panels/settings/SettingsScreen.ts +3 -2
- package/front_end/panels/timeline/CompatibilityTracksAppender.ts +14 -1
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -4
- package/front_end/panels/timeline/TimelineController.ts +185 -3
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +52 -25
- package/front_end/panels/timeline/TimelineFlameChartView.ts +1 -0
- package/front_end/panels/timeline/TimelinePanel.ts +17 -104
- package/front_end/panels/timeline/TimelineTreeView.ts +1 -0
- package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +2 -2
- package/front_end/panels/timeline/components/insights/Table.ts +3 -3
- package/front_end/panels/whats_new/ReleaseNoteText.ts +15 -9
- package/front_end/panels/whats_new/resources/WNDT.md +6 -6
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/codemirror.next/rebuild.sh +1 -1
- package/front_end/third_party/lit/rebuild.sh +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +2 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.js +9 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.d.ts +3 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.js +9 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.d.ts +3 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.js +10 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js +8 -4
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.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/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.d.ts +10 -1
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +13 -7
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +2 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.js +9 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.d.ts +3 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.js +9 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.d.ts +3 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.js +10 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js +8 -4
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.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/lib/types.d.ts +10 -1
- package/front_end/third_party/puppeteer/package/package.json +3 -3
- package/front_end/third_party/puppeteer/package/src/api/Page.ts +2 -3
- package/front_end/third_party/puppeteer/package/src/bidi/HTTPRequest.ts +13 -0
- package/front_end/third_party/puppeteer/package/src/bidi/HTTPResponse.ts +10 -0
- package/front_end/third_party/puppeteer/package/src/bidi/core/Request.ts +15 -0
- package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +9 -4
- package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
- 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/adorners/Adorner.ts +8 -68
- package/front_end/ui/legacy/TabbedPane.ts +1 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
- package/package.json +2 -1
|
@@ -118,4 +118,234 @@
|
|
|
118
118
|
padding: 0 var(--sys-size-4);
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
|
+
|
|
122
|
+
.chat-message {
|
|
123
|
+
user-select: text;
|
|
124
|
+
cursor: initial;
|
|
125
|
+
display: flex;
|
|
126
|
+
flex-direction: column;
|
|
127
|
+
gap: var(--sys-size-5);
|
|
128
|
+
width: 100%;
|
|
129
|
+
padding: var(--sys-size-7) var(--sys-size-5);
|
|
130
|
+
font-size: 12px;
|
|
131
|
+
word-break: normal;
|
|
132
|
+
overflow-wrap: anywhere;
|
|
133
|
+
border-bottom: var(--sys-size-1) solid var(--sys-color-divider);
|
|
134
|
+
|
|
135
|
+
&.is-last-message {
|
|
136
|
+
border-bottom: 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.message-info {
|
|
140
|
+
display: flex;
|
|
141
|
+
align-items: center;
|
|
142
|
+
height: var(--sys-size-11);
|
|
143
|
+
gap: var(--sys-size-4);
|
|
144
|
+
font: var(--sys-typescale-body4-bold);
|
|
145
|
+
|
|
146
|
+
img {
|
|
147
|
+
border: 0;
|
|
148
|
+
border-radius: var(--sys-shape-corner-full);
|
|
149
|
+
display: block;
|
|
150
|
+
height: var(--sys-size-9);
|
|
151
|
+
width: var(--sys-size-9);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
h2 {
|
|
155
|
+
font: var(--sys-typescale-body4-bold);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.actions {
|
|
160
|
+
display: flex;
|
|
161
|
+
flex-direction: column;
|
|
162
|
+
gap: var(--sys-size-8);
|
|
163
|
+
max-width: 100%;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.aborted {
|
|
167
|
+
color: var(--sys-color-on-surface-subtle);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.image-link {
|
|
171
|
+
width: fit-content;
|
|
172
|
+
border-radius: var(--sys-shape-corner-small);
|
|
173
|
+
outline-offset: var(--sys-size-2);
|
|
174
|
+
|
|
175
|
+
img {
|
|
176
|
+
max-height: var(--sys-size-20);
|
|
177
|
+
max-width: 100%;
|
|
178
|
+
border-radius: var(--sys-shape-corner-small);
|
|
179
|
+
border: 1px solid var(--sys-color-neutral-outline);
|
|
180
|
+
width: fit-content;
|
|
181
|
+
vertical-align: bottom;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.unavailable-image {
|
|
186
|
+
margin: var(--sys-size-4) 0;
|
|
187
|
+
display: inline-flex;
|
|
188
|
+
justify-content: center;
|
|
189
|
+
align-items: center;
|
|
190
|
+
height: var(--sys-size-17);
|
|
191
|
+
width: var(--sys-size-18);
|
|
192
|
+
background-color: var(--sys-color-surface3);
|
|
193
|
+
border-radius: var(--sys-shape-corner-small);
|
|
194
|
+
border: 1px solid var(--sys-color-neutral-outline);
|
|
195
|
+
|
|
196
|
+
devtools-icon {
|
|
197
|
+
color: var(--sys-color-state-disabled);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.indicator {
|
|
203
|
+
color: var(--sys-color-green-bright);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.summary {
|
|
207
|
+
display: grid;
|
|
208
|
+
grid-template-columns: auto 1fr auto;
|
|
209
|
+
padding: var(--sys-size-3);
|
|
210
|
+
line-height: var(--sys-size-9);
|
|
211
|
+
cursor: default;
|
|
212
|
+
gap: var(--sys-size-3);
|
|
213
|
+
justify-content: center;
|
|
214
|
+
align-items: center;
|
|
215
|
+
|
|
216
|
+
.title {
|
|
217
|
+
text-overflow: ellipsis;
|
|
218
|
+
white-space: nowrap;
|
|
219
|
+
overflow: hidden;
|
|
220
|
+
font: var(--sys-typescale-body4-regular);
|
|
221
|
+
|
|
222
|
+
.paused {
|
|
223
|
+
font: var(--sys-typescale-body4-bold);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.step-code {
|
|
229
|
+
display: flex;
|
|
230
|
+
flex-direction: column;
|
|
231
|
+
gap: var(--sys-size-2);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.js-code-output {
|
|
235
|
+
devtools-code-block {
|
|
236
|
+
--code-block-max-code-height: 50px;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.context-details {
|
|
241
|
+
devtools-code-block {
|
|
242
|
+
--code-block-max-code-height: 80px;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.step {
|
|
247
|
+
width: fit-content;
|
|
248
|
+
background-color: var(--sys-color-surface3);
|
|
249
|
+
border-radius: var(--sys-size-6);
|
|
250
|
+
position: relative;
|
|
251
|
+
|
|
252
|
+
&.empty {
|
|
253
|
+
pointer-events: none;
|
|
254
|
+
|
|
255
|
+
.arrow {
|
|
256
|
+
display: none;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
&:not(&[open]):hover::after {
|
|
261
|
+
content: '';
|
|
262
|
+
height: 100%;
|
|
263
|
+
width: 100%;
|
|
264
|
+
border-radius: inherit;
|
|
265
|
+
position: absolute;
|
|
266
|
+
top: 0;
|
|
267
|
+
left: 0;
|
|
268
|
+
pointer-events: none;
|
|
269
|
+
background-color: var(--sys-color-state-hover-on-subtle);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
&.paused {
|
|
273
|
+
.indicator {
|
|
274
|
+
color: var(--sys-color-on-surface-subtle);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
&.canceled {
|
|
279
|
+
.summary {
|
|
280
|
+
color: var(--sys-color-state-disabled);
|
|
281
|
+
text-decoration: line-through;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.indicator {
|
|
285
|
+
color: var(--sys-color-state-disabled);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
devtools-markdown-view {
|
|
290
|
+
--code-background-color: var(--sys-color-surface1);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
devtools-icon {
|
|
294
|
+
vertical-align: bottom;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
devtools-spinner {
|
|
298
|
+
width: var(--sys-size-9);
|
|
299
|
+
height: var(--sys-size-9);
|
|
300
|
+
padding: var(--sys-size-2);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
&[open] {
|
|
304
|
+
width: auto;
|
|
305
|
+
|
|
306
|
+
.summary .title {
|
|
307
|
+
white-space: normal;
|
|
308
|
+
overflow: unset;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.summary .arrow {
|
|
312
|
+
transform: rotate(180deg);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
summary::marker {
|
|
317
|
+
content: '';
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
summary {
|
|
321
|
+
border-radius: var(--sys-size-6);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.step-details {
|
|
325
|
+
padding: 0 var(--sys-size-5) var(--sys-size-4) var(--sys-size-12);
|
|
326
|
+
display: flex;
|
|
327
|
+
flex-direction: column;
|
|
328
|
+
gap: var(--sys-size-6);
|
|
329
|
+
|
|
330
|
+
devtools-code-block {
|
|
331
|
+
--code-block-background-color: var(--sys-color-surface1);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.error-step {
|
|
337
|
+
color: var(--sys-color-error);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.side-effect-confirmation {
|
|
341
|
+
display: flex;
|
|
342
|
+
flex-direction: column;
|
|
343
|
+
gap: var(--sys-size-5);
|
|
344
|
+
padding-bottom: var(--sys-size-4);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.side-effect-buttons-container {
|
|
348
|
+
display: flex;
|
|
349
|
+
gap: var(--sys-size-4);
|
|
350
|
+
}
|
|
121
351
|
}
|
|
@@ -198,11 +198,11 @@ const DEFAULT_VIEW: View = (input: ViewInput, _output: ViewOutput, target: HTMLE
|
|
|
198
198
|
<td>
|
|
199
199
|
${field.autofillType}
|
|
200
200
|
${field.fillingStrategy === FillingStrategy.AutocompleteAttribute ?
|
|
201
|
-
html`<devtools-adorner title=${i18nString(UIStrings.autocompleteAttribute)}
|
|
201
|
+
html`<devtools-adorner .name=${field.fillingStrategy} title=${i18nString(UIStrings.autocompleteAttribute)}>
|
|
202
202
|
<span>${i18nString(UIStrings.attr)}</span>
|
|
203
203
|
</devtools-adorner>` :
|
|
204
204
|
field.fillingStrategy === FillingStrategy.AutofillInferred ?
|
|
205
|
-
html`<devtools-adorner title=${i18nString(UIStrings.inferredByHeuristics)}
|
|
205
|
+
html`<devtools-adorner .name=${field.fillingStrategy} title=${i18nString(UIStrings.inferredByHeuristics)}>
|
|
206
206
|
<span>${i18nString(UIStrings.heur)}</span>
|
|
207
207
|
</devtools-adorner>` :
|
|
208
208
|
Lit.nothing}
|
|
@@ -6,11 +6,13 @@ import '../../ui/legacy/legacy.js';
|
|
|
6
6
|
|
|
7
7
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
8
8
|
import type * as Platform from '../../core/platform/platform.js';
|
|
9
|
+
import * as GreenDev from '../../models/greendev/greendev.js';
|
|
9
10
|
import type * as Workspace from '../../models/workspace/workspace.js';
|
|
10
11
|
import * as WorkspaceDiff from '../../models/workspace_diff/workspace_diff.js';
|
|
11
12
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
12
13
|
import * as Lit from '../../ui/lit/lit.js';
|
|
13
14
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
15
|
+
import * as PanelsCommon from '../common/common.js';
|
|
14
16
|
|
|
15
17
|
import {ChangesSidebar, Events} from './ChangesSidebar.js';
|
|
16
18
|
import changesViewStyles from './changesView.css.js';
|
|
@@ -27,6 +29,7 @@ const UIStrings = {
|
|
|
27
29
|
* @description Text in Changes View of the Changes tab to explain the Changes panel.
|
|
28
30
|
*/
|
|
29
31
|
changesViewDescription: 'On this page you can track code changes made within DevTools.',
|
|
32
|
+
|
|
30
33
|
} as const;
|
|
31
34
|
const str_ = i18n.i18n.registerUIStrings('panels/changes/ChangesView.ts', UIStrings);
|
|
32
35
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
@@ -37,11 +40,14 @@ interface ViewInput {
|
|
|
37
40
|
workspaceDiff: WorkspaceDiff.WorkspaceDiff.WorkspaceDiffImpl;
|
|
38
41
|
}
|
|
39
42
|
type View = (input: ViewInput, output: object, target: HTMLElement) => void;
|
|
40
|
-
export const DEFAULT_VIEW: View = (input,
|
|
43
|
+
export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
41
44
|
const onSidebar = (sidebar: ChangesSidebar): void => {
|
|
42
45
|
sidebar.addEventListener(
|
|
43
46
|
Events.SELECTED_UI_SOURCE_CODE_CHANGED, () => input.onSelect(sidebar.selectedUISourceCode()));
|
|
44
47
|
};
|
|
48
|
+
|
|
49
|
+
const hasCopyToPrompt = GreenDev.Prototypes.instance().isEnabled('copyToGemini');
|
|
50
|
+
|
|
45
51
|
render(
|
|
46
52
|
// clang-format off
|
|
47
53
|
html`
|
|
@@ -62,6 +68,14 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
62
68
|
workspaceDiff: input.workspaceDiff
|
|
63
69
|
})}></devtools-widget>
|
|
64
70
|
</div>
|
|
71
|
+
${hasCopyToPrompt ? html`
|
|
72
|
+
<devtools-widget class="copy-to-prompt"
|
|
73
|
+
.widgetConfig=${UI.Widget.widgetConfig(PanelsCommon.CopyChangesToPrompt, {
|
|
74
|
+
workspaceDiff: input.workspaceDiff,
|
|
75
|
+
patchAgentCSSChange: null,
|
|
76
|
+
})}
|
|
77
|
+
></devtools-widget>
|
|
78
|
+
` : Lit.nothing}
|
|
65
79
|
</div>
|
|
66
80
|
<devtools-widget
|
|
67
81
|
slot="sidebar"
|
|
@@ -40,3 +40,9 @@
|
|
|
40
40
|
[hidden] {
|
|
41
41
|
display: none !important; /* stylelint-disable-line declaration-no-important */
|
|
42
42
|
}
|
|
43
|
+
|
|
44
|
+
.copy-to-prompt {
|
|
45
|
+
margin: var(--sys-size-4);
|
|
46
|
+
/* Got to override the default flex properties for widgets */
|
|
47
|
+
flex-grow: 0 !important; /* stylelint-disable-line declaration-no-important */
|
|
48
|
+
}
|
|
@@ -50,9 +50,9 @@ const UIStrings = {
|
|
|
50
50
|
starterBadgeAwardMessageNoGdpProfile:
|
|
51
51
|
'You earned the {PH1} badge for the {PH2}! Create a profile to claim your badge.',
|
|
52
52
|
/**
|
|
53
|
-
* @description Action title for
|
|
53
|
+
* @description Action title for dismissing the badge notification.
|
|
54
54
|
*/
|
|
55
|
-
|
|
55
|
+
noThanks: 'No thanks',
|
|
56
56
|
/**
|
|
57
57
|
* @description Action title for enabling the "Receive badges" setting
|
|
58
58
|
*/
|
|
@@ -157,11 +157,17 @@ export class BadgeNotification extends UI.Widget.Widget {
|
|
|
157
157
|
this.markAsRoot();
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
async present(badge: Badges.Badge): Promise<void> {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
160
|
+
async present(badge: Badges.Badge, reason: Badges.BadgeTriggerReason): Promise<void> {
|
|
161
|
+
switch (reason) {
|
|
162
|
+
case Badges.BadgeTriggerReason.AWARD:
|
|
163
|
+
this.#presentActivityBasedBadge(badge);
|
|
164
|
+
return;
|
|
165
|
+
case Badges.BadgeTriggerReason.STARTER_BADGE_SETTINGS_NUDGE:
|
|
166
|
+
this.#presentStarterBadgeSettingsNudge(badge);
|
|
167
|
+
return;
|
|
168
|
+
case Badges.BadgeTriggerReason.STARTER_BADGE_PROFILE_NUDGE:
|
|
169
|
+
this.#presentStarterBadgeProfileNudge(badge);
|
|
170
|
+
return;
|
|
165
171
|
}
|
|
166
172
|
}
|
|
167
173
|
|
|
@@ -191,70 +197,50 @@ export class BadgeNotification extends UI.Widget.Widget {
|
|
|
191
197
|
this.#autoCloseTimeout = window.setTimeout(this.#onAutoClose, AUTO_CLOSE_TIME_IN_MS);
|
|
192
198
|
}
|
|
193
199
|
|
|
194
|
-
|
|
195
|
-
const getProfileResponse = await Host.GdpClient.GdpClient.instance().getProfile();
|
|
196
|
-
// The `getProfile` call failed and returned a `null`.
|
|
197
|
-
// For that case, we don't show anything.
|
|
198
|
-
if (!getProfileResponse) {
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const hasGdpProfile = Boolean(getProfileResponse.profile);
|
|
203
|
-
const receiveBadgesSettingEnabled = Badges.UserBadges.instance().isReceiveBadgesSettingEnabled();
|
|
200
|
+
#presentStarterBadgeSettingsNudge(badge: Badges.Badge): void {
|
|
204
201
|
const googleDeveloperProgramLink = UI.XLink.XLink.create(
|
|
205
202
|
'https://developers.google.com/program', lockedString('Google Developer Program'), 'badge-link', undefined,
|
|
206
203
|
'program-link');
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (hasGdpProfile && !receiveBadgesSettingEnabled) {
|
|
218
|
-
this.#show({
|
|
219
|
-
message: i18nFormatString(
|
|
220
|
-
UIStrings.starterBadgeAwardMessageSettingDisabled, {PH1: badge.title, PH2: googleDeveloperProgramLink}),
|
|
221
|
-
jslogContext: badge.jslogContext,
|
|
222
|
-
actions: [
|
|
223
|
-
{
|
|
224
|
-
label: i18nString(UIStrings.remindMeLater),
|
|
225
|
-
jslogContext: 'remind-me-later',
|
|
226
|
-
onClick: () => {
|
|
227
|
-
this.detach();
|
|
228
|
-
Badges.UserBadges.instance().snoozeStarterBadge();
|
|
229
|
-
},
|
|
204
|
+
this.#show({
|
|
205
|
+
message: i18nFormatString(
|
|
206
|
+
UIStrings.starterBadgeAwardMessageSettingDisabled, {PH1: badge.title, PH2: googleDeveloperProgramLink}),
|
|
207
|
+
jslogContext: badge.jslogContext,
|
|
208
|
+
actions: [
|
|
209
|
+
{
|
|
210
|
+
label: i18nString(UIStrings.noThanks),
|
|
211
|
+
jslogContext: 'no-thanks',
|
|
212
|
+
onClick: () => {
|
|
213
|
+
this.#onDismissClick();
|
|
230
214
|
},
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
label: i18nString(UIStrings.receiveBadges),
|
|
218
|
+
jslogContext: 'receive-badges',
|
|
219
|
+
onClick: () => {
|
|
220
|
+
this.detach();
|
|
221
|
+
revealBadgeSettings();
|
|
238
222
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
223
|
+
}
|
|
224
|
+
],
|
|
225
|
+
imageUri: badge.imageUri,
|
|
226
|
+
isStarterBadge: true,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
245
229
|
|
|
246
|
-
|
|
230
|
+
#presentStarterBadgeProfileNudge(badge: Badges.Badge): void {
|
|
231
|
+
const googleDeveloperProgramLink = UI.XLink.XLink.create(
|
|
232
|
+
'https://developers.google.com/program', lockedString('Google Developer Program'), 'badge-link', undefined,
|
|
233
|
+
'program-link');
|
|
247
234
|
this.#show({
|
|
248
235
|
message: i18nFormatString(
|
|
249
236
|
UIStrings.starterBadgeAwardMessageNoGdpProfile, {PH1: badge.title, PH2: googleDeveloperProgramLink}),
|
|
250
237
|
jslogContext: badge.jslogContext,
|
|
251
238
|
actions: [
|
|
252
239
|
{
|
|
253
|
-
label: i18nString(UIStrings.
|
|
254
|
-
jslogContext: '
|
|
240
|
+
label: i18nString(UIStrings.noThanks),
|
|
241
|
+
jslogContext: 'no-thanks',
|
|
255
242
|
onClick: () => {
|
|
256
|
-
this
|
|
257
|
-
Badges.UserBadges.instance().snoozeStarterBadge();
|
|
243
|
+
this.#onDismissClick();
|
|
258
244
|
},
|
|
259
245
|
},
|
|
260
246
|
{
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
// Copyright 2025 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
|
+
import * as Host from '../../core/host/host.js';
|
|
6
|
+
import * as i18n from '../../core/i18n/i18n.js';
|
|
7
|
+
import * as GreenDev from '../../models/greendev/greendev.js';
|
|
8
|
+
import type * as Workspace from '../../models/workspace/workspace.js';
|
|
9
|
+
import * as WorkspaceDiff from '../../models/workspace_diff/workspace_diff.js';
|
|
10
|
+
import * as Diff from '../../third_party/diff/diff.js';
|
|
11
|
+
import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
12
|
+
import * as Snackbars from '../../ui/components/snackbars/snackbars.js';
|
|
13
|
+
import * as UI from '../../ui/legacy/legacy.js';
|
|
14
|
+
import * as Lit from '../../ui/lit/lit.js';
|
|
15
|
+
|
|
16
|
+
const {render, html} = Lit;
|
|
17
|
+
|
|
18
|
+
const UIStrings = {
|
|
19
|
+
/**
|
|
20
|
+
* @description The message shown in a toast when the response is copied to the clipboard.
|
|
21
|
+
*/
|
|
22
|
+
responseCopiedToClipboard: 'Response copied to clipboard',
|
|
23
|
+
} as const;
|
|
24
|
+
|
|
25
|
+
const str_ = i18n.i18n.registerUIStrings('panels/common/CopyChangesToPrompt.ts', UIStrings);
|
|
26
|
+
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
27
|
+
|
|
28
|
+
interface CopyChangesDiff {
|
|
29
|
+
diff: Diff.Diff.DiffArray|undefined;
|
|
30
|
+
uiSourceCode: Workspace.UISourceCode.UISourceCode;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface GeminiChangesViewInput {
|
|
34
|
+
/**
|
|
35
|
+
* These are the set of diffs tracked by the Changes Panel.
|
|
36
|
+
*/
|
|
37
|
+
diffs: CopyChangesDiff[];
|
|
38
|
+
/**
|
|
39
|
+
* Supplied by the Patch Agent if it has made any changes on behalf of the
|
|
40
|
+
* user.
|
|
41
|
+
*/
|
|
42
|
+
patchAgentCSSChange: string|null;
|
|
43
|
+
onCopyToClipboard: (text: string) => void;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type GeminiChangesView = (input: GeminiChangesViewInput, output: object, target: HTMLElement) => void;
|
|
47
|
+
|
|
48
|
+
export class CopyChangesToPrompt extends UI.Widget.Widget {
|
|
49
|
+
#workspaceDiff: WorkspaceDiff.WorkspaceDiff.WorkspaceDiffImpl;
|
|
50
|
+
readonly #view: GeminiChangesView;
|
|
51
|
+
#patchAgentCSSChange: string|null = null;
|
|
52
|
+
|
|
53
|
+
constructor(target?: HTMLElement, view = GEMINI_CHANGES_VIEW) {
|
|
54
|
+
super(target);
|
|
55
|
+
this.#view = view;
|
|
56
|
+
this.#workspaceDiff = WorkspaceDiff.WorkspaceDiff.workspaceDiff();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
get patchAgentCSSChange(): string|null {
|
|
60
|
+
return this.#patchAgentCSSChange;
|
|
61
|
+
}
|
|
62
|
+
set patchAgentCSSChange(code: string) {
|
|
63
|
+
this.#patchAgentCSSChange = code;
|
|
64
|
+
this.requestUpdate();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
override wasShown(): void {
|
|
68
|
+
super.wasShown();
|
|
69
|
+
this.#workspaceDiff.addEventListener(
|
|
70
|
+
WorkspaceDiff.WorkspaceDiff.Events.MODIFIED_STATUS_CHANGED, this.#onDiffChange, this);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
override willHide(): void {
|
|
74
|
+
super.willHide();
|
|
75
|
+
this.#workspaceDiff.removeEventListener(
|
|
76
|
+
WorkspaceDiff.WorkspaceDiff.Events.MODIFIED_STATUS_CHANGED, this.#onDiffChange, this);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#getModifiledFiles(): Workspace.UISourceCode.UISourceCode[] {
|
|
80
|
+
return this.#workspaceDiff.modifiedUISourceCodes().filter(modified => {
|
|
81
|
+
return !modified.url().startsWith('inspector://');
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
#onDiffChange(): void {
|
|
86
|
+
// TODO: track this and unsubscribe to files?
|
|
87
|
+
for (const file of this.#getModifiledFiles()) {
|
|
88
|
+
this.#workspaceDiff.subscribeToDiffChange(file, this.requestUpdate, this);
|
|
89
|
+
}
|
|
90
|
+
this.requestUpdate();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
set workspaceDiff(diff: WorkspaceDiff.WorkspaceDiff.WorkspaceDiffImpl) {
|
|
94
|
+
this.#workspaceDiff = diff;
|
|
95
|
+
this.requestUpdate();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
override async performUpdate(): Promise<void> {
|
|
99
|
+
if (!GreenDev.Prototypes.instance().isEnabled('copyToGemini')) {
|
|
100
|
+
// We expect code that renders this component to only do so based on this flag, but this is a double-check.
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const diffs = await Promise.all(this.#getModifiledFiles().map(async modifiedUISourceCode => {
|
|
105
|
+
const diffResponse = await this.#workspaceDiff?.requestDiff(modifiedUISourceCode);
|
|
106
|
+
return {diff: diffResponse?.diff ?? [], uiSourceCode: modifiedUISourceCode};
|
|
107
|
+
}));
|
|
108
|
+
this.#view(
|
|
109
|
+
{
|
|
110
|
+
diffs,
|
|
111
|
+
patchAgentCSSChange: this.#patchAgentCSSChange,
|
|
112
|
+
onCopyToClipboard: (text: string) => {
|
|
113
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(text);
|
|
114
|
+
Snackbars.Snackbar.Snackbar.show({
|
|
115
|
+
message: i18nString(UIStrings.responseCopiedToClipboard),
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
{}, this.contentElement);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const GEMINI_CHANGES_VIEW: GeminiChangesView = (input, _output, target) => {
|
|
123
|
+
const hasDiffs = input.diffs.some(d => {
|
|
124
|
+
return d.diff !== undefined && d.diff.length > 0;
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
if (!hasDiffs && !input.patchAgentCSSChange) {
|
|
128
|
+
render(Lit.nothing, target);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const promptForChangesPanel = hasDiffs ? buildGeminiCommand(input.diffs) : '';
|
|
133
|
+
const promptForPatchAgentCSS = input.patchAgentCSSChange ? buildPatchAgentCSSPrompt(input.patchAgentCSSChange) : '';
|
|
134
|
+
|
|
135
|
+
const finalPrompt = [PREAMBLE, promptForChangesPanel, promptForPatchAgentCSS].filter(x => x.length > 0).join(`\n`);
|
|
136
|
+
|
|
137
|
+
function copyClick(): void {
|
|
138
|
+
input.onCopyToClipboard(finalPrompt);
|
|
139
|
+
}
|
|
140
|
+
// clang-format off
|
|
141
|
+
render(html`<devtools-button
|
|
142
|
+
.iconName=${'copy'}
|
|
143
|
+
.variant=${Buttons.Button.Variant.OUTLINED}
|
|
144
|
+
@click=${copyClick}>Copy prompt to clipboard</devtools-button>
|
|
145
|
+
`, target);
|
|
146
|
+
// clang-format on
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
function buildPatchAgentCSSPrompt(code: string): string {
|
|
150
|
+
// clang-format off
|
|
151
|
+
return `The DevTools CSS Patching Agent has also made some CSS changes on behalf of the user. These changes are listed below. Think carefully about how best to apply these changes.
|
|
152
|
+
|
|
153
|
+
**DevTools Patch Agent changes**
|
|
154
|
+
\`\`\`
|
|
155
|
+
${code}
|
|
156
|
+
\`\`\``;
|
|
157
|
+
// clang-format on
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function buildGeminiCommand(diffs: readonly CopyChangesDiff[]): string {
|
|
161
|
+
// clang-format off
|
|
162
|
+
const output = `Below this line are a list of files and the diff for each of them. Consider this diff and apply it to the codebase but remembering that the changes in DevTools may not be the most accurate fixes and you should not necessarily apply them directly as DevTools works with the deployed code and not the source code.
|
|
163
|
+
|
|
164
|
+
Within the diffs you will often see lines of code commented out. If the diff contains a new line that was some code being wrapped in comments, treat that as if the intent is to delete the code.
|
|
165
|
+
|
|
166
|
+
How to read a diff:
|
|
167
|
+
* If a line starts with \`-\` , DevTools removed it.
|
|
168
|
+
* If a line starts with \`+\` , DevTools added it.
|
|
169
|
+
* If a line starts with neither a \`+\` or \`-\` , DevTools did not change the line and you can safely ignore it.
|
|
170
|
+
|
|
171
|
+
${diffs.map(diff => {
|
|
172
|
+
if (!diff.diff || diff.diff.length === 0) {
|
|
173
|
+
return '';
|
|
174
|
+
}
|
|
175
|
+
return `Filename: ${diff.uiSourceCode.fullDisplayName()}
|
|
176
|
+
|
|
177
|
+
Diff:
|
|
178
|
+
${formatDiffForLLM(diff.diff)}`;
|
|
179
|
+
}).filter(x => x.length).join('\n')}`;
|
|
180
|
+
// clang-format on
|
|
181
|
+
return output;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function formatDiffForLLM(diffArray: Diff.Diff.DiffArray): string {
|
|
185
|
+
let formattedDiff = '';
|
|
186
|
+
for (const diffItem of diffArray) {
|
|
187
|
+
const operation = diffItem[0];
|
|
188
|
+
const lines = diffItem[1];
|
|
189
|
+
|
|
190
|
+
for (const line of lines) {
|
|
191
|
+
if (operation === Diff.Diff.Operation.Equal) {
|
|
192
|
+
formattedDiff += ' ' + line + '\n';
|
|
193
|
+
} else if (operation === Diff.Diff.Operation.Insert) {
|
|
194
|
+
formattedDiff += '+ ' + line + '\n';
|
|
195
|
+
} else if (operation === Diff.Diff.Operation.Delete) {
|
|
196
|
+
formattedDiff += '- ' + line + '\n';
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return formattedDiff;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const PREAMBLE =
|
|
204
|
+
`You are receiving a set of runtime changes (CSS, HTML, and JS) captured via Browser DevTools. Your goal is to persist these changes into the local source code by identifying the original source-of-truth.
|
|
205
|
+
|
|
206
|
+
Because DevTools reflects the "Flattened Result" of complex build logic, you must follow this "Source-Aware" strategy:
|
|
207
|
+
|
|
208
|
+
1. **Structural Mapping (HTML/DOM):**
|
|
209
|
+
- If a DOM element was added/removed, identify the source template (JSX, Vue, Svelte, HTML) responsible.
|
|
210
|
+
- **Logic Check:** Determine if the change should be a static element or if it requires a new conditional (\`if/else\`) or loop (\`map\`) based on existing component patterns.
|
|
211
|
+
|
|
212
|
+
2. **Style Mapping (CSS/Attributes):**
|
|
213
|
+
- Map raw styles to the project's specific styling architecture (Tailwind, SCSS, Styled-Components).
|
|
214
|
+
- Replace hard-coded values with existing Design Tokens or Theme Variables (\`var(--color-primary)\`, etc.) found in the codebase.
|
|
215
|
+
- CSS changes may not be applied to CSS files directly. Consider that CSS could be applied via JavaScript, especially if the codebase is using a component based frontend framework or web components.
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
3. **Behavioral Mapping (JS/Event Listeners):**
|
|
219
|
+
- If logic or event handlers were modified, locate the corresponding functions or hooks in the source.
|
|
220
|
+
- Ensure new logic follows the project's state management patterns (e.g., React \`useState\`, Redux, or standard ES6+ modules).
|
|
221
|
+
|
|
222
|
+
4. **Safety & Ambiguity Protocol:**
|
|
223
|
+
- **Third-Party Code:** If a change targets a DOM element or style generated by an external library (e.g., a UI kit's internal wrapper), do not modify the library's source. Instead, find the appropriate override mechanism in the codebase.
|
|
224
|
+
- **Uncertainty:** If a DevTools change cannot be mapped to the source with 100% confidence (e.g., minified selectors or ambiguous origin), stop and report the conflict rather than guessing.
|
|
225
|
+
|
|
226
|
+
5. **Agentic Execution Workflow:**
|
|
227
|
+
- **Discovery:** Use your tools (\`grep\`, \`find\`, etc.) to locate unique strings or class names from the DevTools log.
|
|
228
|
+
- **Analysis:** Determine if the target is a reusable component or a specific page instance.
|
|
229
|
+
- **Implementation:** Execute file edits using the project's idiomatic syntax and formatting standards.
|
|
230
|
+
|
|
231
|
+
**INSTRUCTION:**
|
|
232
|
+
Begin by searching for the relevant source files. Explain your mapping logic before performing the edits.
|
|
233
|
+
`;
|
|
@@ -108,3 +108,4 @@ export * as ExtensionView from './ExtensionView.js';
|
|
|
108
108
|
export * as PersistenceUtils from './PersistenceUtils.js';
|
|
109
109
|
export * as DOMLinkifier from './DOMLinkifier.js';
|
|
110
110
|
export * as ExtensionIframe from './ExtensionView.js';
|
|
111
|
+
export {CopyChangesToPrompt} from './CopyChangesToPrompt.js';
|