@checkly/playwright-core 1.51.15 → 1.51.17-beta.0

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.
Files changed (57) hide show
  1. package/lib/checkly/secretsFilter.js +9 -2
  2. package/lib/generated/clockSource.js +2 -1
  3. package/lib/generated/consoleApiSource.js +2 -1
  4. package/lib/generated/injectedScriptSource.js +2 -1
  5. package/lib/generated/pollingRecorderSource.js +2 -1
  6. package/lib/generated/utilityScriptSource.js +2 -1
  7. package/lib/generated/webSocketMockSource.js +2 -1
  8. package/lib/vite/recorder/assets/codeMirrorModule-DrMbgOIo.js +16684 -0
  9. package/lib/vite/recorder/assets/codeMirrorModule-DuST8d_k.css +344 -0
  10. package/lib/vite/recorder/assets/index-5NM3V7eb.css +2524 -0
  11. package/lib/vite/recorder/assets/index-CT-scFHn.js +16848 -0
  12. package/lib/vite/recorder/index.html +2 -2
  13. package/lib/vite/traceViewer/assets/codeMirrorModule-CB-2okZ8.js +16684 -0
  14. package/lib/vite/traceViewer/assets/defaultSettingsView-CBiB4avC.js +217 -0
  15. package/lib/vite/traceViewer/assets/inspectorTab-CwgfffWb.js +25143 -0
  16. package/lib/vite/traceViewer/assets/workbench-CWZselvp.js +2470 -0
  17. package/lib/vite/traceViewer/assets/xtermModule-Es_gt_u7.js +5994 -0
  18. package/lib/vite/traceViewer/codeMirrorModule.DuST8d_k.css +344 -0
  19. package/lib/vite/traceViewer/defaultSettingsView.Dp3b_92q.css +41 -0
  20. package/lib/vite/traceViewer/embedded.BeldSa2G.css +68 -0
  21. package/lib/vite/traceViewer/embedded.gzudoghF.js +106 -0
  22. package/lib/vite/traceViewer/embedded.html +6 -6
  23. package/lib/vite/traceViewer/index.DilotR1h.js +314 -0
  24. package/lib/vite/traceViewer/index.QewjJ85u.css +131 -0
  25. package/lib/vite/traceViewer/index.html +8 -8
  26. package/lib/vite/traceViewer/inspectorTab.DnGm18kV.css +3178 -0
  27. package/lib/vite/traceViewer/recorder.DLgqV9db.css +15 -0
  28. package/lib/vite/traceViewer/recorder.DVrkq3Um.js +551 -0
  29. package/lib/vite/traceViewer/recorder.html +4 -4
  30. package/lib/vite/traceViewer/uiMode.C9_OcpPU.js +1756 -0
  31. package/lib/vite/traceViewer/uiMode.c5ORgcrX.css +1424 -0
  32. package/lib/vite/traceViewer/uiMode.html +8 -8
  33. package/lib/vite/traceViewer/workbench.xUZSA8PY.css +787 -0
  34. package/lib/vite/traceViewer/xtermModule.EsaqrrTX.css +209 -0
  35. package/package.json +1 -1
  36. package/lib/vite/recorder/assets/codeMirrorModule-B9YMkrwa.js +0 -24
  37. package/lib/vite/recorder/assets/codeMirrorModule-C3UTv-Ge.css +0 -1
  38. package/lib/vite/recorder/assets/index-ELPgmkwA.js +0 -184
  39. package/lib/vite/recorder/assets/index-eHBmevrY.css +0 -1
  40. package/lib/vite/traceViewer/assets/codeMirrorModule-gU1OOCQO.js +0 -24
  41. package/lib/vite/traceViewer/assets/defaultSettingsView-B5n_FjMx.js +0 -1
  42. package/lib/vite/traceViewer/assets/inspectorTab-6Tru8Mn_.js +0 -235
  43. package/lib/vite/traceViewer/assets/workbench-B_Nj4NA2.js +0 -25
  44. package/lib/vite/traceViewer/assets/xtermModule-BoAIEibi.js +0 -9
  45. package/lib/vite/traceViewer/codeMirrorModule.C3UTv-Ge.css +0 -1
  46. package/lib/vite/traceViewer/defaultSettingsView.CO3FR0CX.css +0 -1
  47. package/lib/vite/traceViewer/embedded.DpNPH6mk.js +0 -2
  48. package/lib/vite/traceViewer/embedded.mLhjB5IF.css +0 -1
  49. package/lib/vite/traceViewer/index.CFOW-Ezb.css +0 -1
  50. package/lib/vite/traceViewer/index.CuE3SYGw.js +0 -2
  51. package/lib/vite/traceViewer/inspectorTab.CXDulcFG.css +0 -1
  52. package/lib/vite/traceViewer/recorder.BD-uZJs7.js +0 -2
  53. package/lib/vite/traceViewer/recorder.tn0RQdqM.css +0 -0
  54. package/lib/vite/traceViewer/uiMode.BatfzHMG.css +0 -1
  55. package/lib/vite/traceViewer/uiMode.DHrNgddz.js +0 -5
  56. package/lib/vite/traceViewer/workbench.B9vIAzH9.css +0 -1
  57. package/lib/vite/traceViewer/xtermModule.Beg8tuEN.css +0 -32
@@ -0,0 +1,2470 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { r as reactExports, j as jsxRuntimeExports, f as clsx, k as scrollIntoViewIfNeeded, l as buildActionTree, n as stats, m as msToString, T as ToolbarButton, o as asLocator, P as PlaceholderPanel, C as CopyToClipboard, L as ListView, p as ansi2html, q as useCookies, u as useMeasure, v as ResizeView, w as kWebLinkRe, x as useFlash, y as lineHeight, z as CodeMirrorWrapper, A as useAsyncMemo, B as CopyToClipboardTextButton, D as upperBound, G as GlassPane, h as useSetting, E as useConsoleTabModel, F as useNetworkTabModel, S as SplitView, H as TabbedPane, I as SnapshotTabsView, J as InspectorTab, K as ConsoleTab, N as NetworkTab, O as SourceTab } from "./inspectorTab-CwgfffWb.js";
5
+ const scrollPositions = /* @__PURE__ */ new Map();
6
+ function TreeView({
7
+ name,
8
+ rootItem,
9
+ render,
10
+ title,
11
+ icon,
12
+ isError,
13
+ isVisible,
14
+ selectedItem,
15
+ onAccepted,
16
+ onSelected,
17
+ onHighlighted,
18
+ treeState,
19
+ setTreeState,
20
+ noItemsMessage,
21
+ dataTestId,
22
+ autoExpandDepth
23
+ }) {
24
+ const treeItems = reactExports.useMemo(() => {
25
+ return indexTree(rootItem, selectedItem, treeState.expandedItems, autoExpandDepth || 0, isVisible);
26
+ }, [rootItem, selectedItem, treeState, autoExpandDepth, isVisible]);
27
+ const itemListRef = reactExports.useRef(null);
28
+ const [highlightedItem, setHighlightedItem] = reactExports.useState();
29
+ const [isKeyboardNavigation, setIsKeyboardNavigation] = reactExports.useState(false);
30
+ reactExports.useEffect(() => {
31
+ onHighlighted == null ? void 0 : onHighlighted(highlightedItem);
32
+ }, [onHighlighted, highlightedItem]);
33
+ reactExports.useEffect(() => {
34
+ const treeElem = itemListRef.current;
35
+ if (!treeElem)
36
+ return;
37
+ const saveScrollPosition = () => {
38
+ scrollPositions.set(name, treeElem.scrollTop);
39
+ };
40
+ treeElem.addEventListener("scroll", saveScrollPosition, { passive: true });
41
+ return () => treeElem.removeEventListener("scroll", saveScrollPosition);
42
+ }, [name]);
43
+ reactExports.useEffect(() => {
44
+ if (itemListRef.current)
45
+ itemListRef.current.scrollTop = scrollPositions.get(name) || 0;
46
+ }, [name]);
47
+ const toggleExpanded = reactExports.useCallback((item) => {
48
+ const { expanded } = treeItems.get(item);
49
+ if (expanded) {
50
+ for (let i2 = selectedItem; i2; i2 = i2.parent) {
51
+ if (i2 === item) {
52
+ onSelected == null ? void 0 : onSelected(item);
53
+ break;
54
+ }
55
+ }
56
+ treeState.expandedItems.set(item.id, false);
57
+ } else {
58
+ treeState.expandedItems.set(item.id, true);
59
+ }
60
+ setTreeState({ ...treeState });
61
+ }, [treeItems, selectedItem, onSelected, treeState, setTreeState]);
62
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: clsx(`tree-view vbox`, name + "-tree-view"), role: "tree", "data-testid": dataTestId || name + "-tree", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
63
+ "div",
64
+ {
65
+ className: clsx("tree-view-content"),
66
+ tabIndex: 0,
67
+ onKeyDown: (event) => {
68
+ if (selectedItem && event.key === "Enter") {
69
+ onAccepted == null ? void 0 : onAccepted(selectedItem);
70
+ return;
71
+ }
72
+ if (event.key !== "ArrowDown" && event.key !== "ArrowUp" && event.key !== "ArrowLeft" && event.key !== "ArrowRight")
73
+ return;
74
+ event.stopPropagation();
75
+ event.preventDefault();
76
+ if (selectedItem && event.key === "ArrowLeft") {
77
+ const { expanded, parent } = treeItems.get(selectedItem);
78
+ if (expanded) {
79
+ treeState.expandedItems.set(selectedItem.id, false);
80
+ setTreeState({ ...treeState });
81
+ } else if (parent) {
82
+ onSelected == null ? void 0 : onSelected(parent);
83
+ }
84
+ return;
85
+ }
86
+ if (selectedItem && event.key === "ArrowRight") {
87
+ if (selectedItem.children.length) {
88
+ treeState.expandedItems.set(selectedItem.id, true);
89
+ setTreeState({ ...treeState });
90
+ }
91
+ return;
92
+ }
93
+ let newSelectedItem = selectedItem;
94
+ if (event.key === "ArrowDown") {
95
+ if (selectedItem) {
96
+ const itemData = treeItems.get(selectedItem);
97
+ newSelectedItem = itemData.next;
98
+ } else if (treeItems.size) {
99
+ const itemList = [...treeItems.keys()];
100
+ newSelectedItem = itemList[0];
101
+ }
102
+ }
103
+ if (event.key === "ArrowUp") {
104
+ if (selectedItem) {
105
+ const itemData = treeItems.get(selectedItem);
106
+ newSelectedItem = itemData.prev;
107
+ } else if (treeItems.size) {
108
+ const itemList = [...treeItems.keys()];
109
+ newSelectedItem = itemList[itemList.length - 1];
110
+ }
111
+ }
112
+ onHighlighted == null ? void 0 : onHighlighted(void 0);
113
+ if (newSelectedItem) {
114
+ setIsKeyboardNavigation(true);
115
+ onSelected == null ? void 0 : onSelected(newSelectedItem);
116
+ }
117
+ setHighlightedItem(void 0);
118
+ },
119
+ ref: itemListRef,
120
+ children: [
121
+ noItemsMessage && treeItems.size === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "tree-view-empty", children: noItemsMessage }),
122
+ rootItem.children.map((child) => {
123
+ const itemData = treeItems.get(child);
124
+ return itemData && /* @__PURE__ */ jsxRuntimeExports.jsx(
125
+ TreeItemHeader,
126
+ {
127
+ item: child,
128
+ treeItems,
129
+ selectedItem,
130
+ onSelected,
131
+ onAccepted,
132
+ isError,
133
+ toggleExpanded,
134
+ highlightedItem,
135
+ setHighlightedItem,
136
+ render,
137
+ icon,
138
+ title,
139
+ isKeyboardNavigation,
140
+ setIsKeyboardNavigation
141
+ },
142
+ child.id
143
+ );
144
+ })
145
+ ]
146
+ }
147
+ ) });
148
+ }
149
+ function TreeItemHeader({
150
+ item,
151
+ treeItems,
152
+ selectedItem,
153
+ onSelected,
154
+ highlightedItem,
155
+ setHighlightedItem,
156
+ isError,
157
+ onAccepted,
158
+ toggleExpanded,
159
+ render,
160
+ title,
161
+ icon,
162
+ isKeyboardNavigation,
163
+ setIsKeyboardNavigation
164
+ }) {
165
+ const groupId = reactExports.useId();
166
+ const itemRef = reactExports.useRef(null);
167
+ reactExports.useEffect(() => {
168
+ if (selectedItem === item && isKeyboardNavigation && itemRef.current) {
169
+ scrollIntoViewIfNeeded(itemRef.current);
170
+ setIsKeyboardNavigation(false);
171
+ }
172
+ }, [item, selectedItem, isKeyboardNavigation, setIsKeyboardNavigation]);
173
+ const itemData = treeItems.get(item);
174
+ const indentation = itemData.depth;
175
+ const expanded = itemData.expanded;
176
+ let expandIcon = "codicon-blank";
177
+ if (typeof expanded === "boolean")
178
+ expandIcon = expanded ? "codicon-chevron-down" : "codicon-chevron-right";
179
+ const rendered = render(item);
180
+ const children = expanded && item.children.length ? item.children : [];
181
+ const titled = title == null ? void 0 : title(item);
182
+ const iconed = (icon == null ? void 0 : icon(item)) || "codicon-blank";
183
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: itemRef, role: "treeitem", "aria-selected": item === selectedItem, "aria-expanded": expanded, "aria-controls": groupId, title: titled, className: "vbox", style: { flex: "none" }, children: [
184
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
185
+ "div",
186
+ {
187
+ onDoubleClick: () => onAccepted == null ? void 0 : onAccepted(item),
188
+ className: clsx(
189
+ "tree-view-entry",
190
+ selectedItem === item && "selected",
191
+ highlightedItem === item && "highlighted",
192
+ (isError == null ? void 0 : isError(item)) && "error"
193
+ ),
194
+ onClick: () => onSelected == null ? void 0 : onSelected(item),
195
+ onMouseEnter: () => setHighlightedItem(item),
196
+ onMouseLeave: () => setHighlightedItem(void 0),
197
+ children: [
198
+ indentation ? new Array(indentation).fill(0).map((_2, i2) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "tree-view-indent" }, "indent-" + i2)) : void 0,
199
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
200
+ "div",
201
+ {
202
+ "aria-hidden": "true",
203
+ className: "codicon " + expandIcon,
204
+ style: { minWidth: 16, marginRight: 4 },
205
+ onDoubleClick: (e) => {
206
+ e.preventDefault();
207
+ e.stopPropagation();
208
+ },
209
+ onClick: (e) => {
210
+ e.stopPropagation();
211
+ e.preventDefault();
212
+ toggleExpanded(item);
213
+ }
214
+ }
215
+ ),
216
+ icon && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "codicon " + iconed, style: { minWidth: 16, marginRight: 4 }, "aria-label": "[" + iconed.replace("codicon", "icon") + "]" }),
217
+ typeof rendered === "string" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { textOverflow: "ellipsis", overflow: "hidden" }, children: rendered }) : rendered
218
+ ]
219
+ }
220
+ ),
221
+ !!children.length && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { id: groupId, role: "group", children: children.map((child) => {
222
+ const itemData2 = treeItems.get(child);
223
+ return itemData2 && /* @__PURE__ */ jsxRuntimeExports.jsx(
224
+ TreeItemHeader,
225
+ {
226
+ item: child,
227
+ treeItems,
228
+ selectedItem,
229
+ onSelected,
230
+ onAccepted,
231
+ isError,
232
+ toggleExpanded,
233
+ highlightedItem,
234
+ setHighlightedItem,
235
+ render,
236
+ title,
237
+ icon,
238
+ isKeyboardNavigation,
239
+ setIsKeyboardNavigation
240
+ },
241
+ child.id
242
+ );
243
+ }) })
244
+ ] });
245
+ }
246
+ function indexTree(rootItem, selectedItem, expandedItems, autoExpandDepth, isVisible = () => true) {
247
+ if (!isVisible(rootItem))
248
+ return /* @__PURE__ */ new Map();
249
+ const result = /* @__PURE__ */ new Map();
250
+ const temporaryExpanded = /* @__PURE__ */ new Set();
251
+ for (let item = selectedItem == null ? void 0 : selectedItem.parent; item; item = item.parent)
252
+ temporaryExpanded.add(item.id);
253
+ let lastItem = null;
254
+ const appendChildren = (parent, depth) => {
255
+ for (const item of parent.children) {
256
+ if (!isVisible(item))
257
+ continue;
258
+ const expandState = temporaryExpanded.has(item.id) || expandedItems.get(item.id);
259
+ const autoExpandMatches = autoExpandDepth > depth && result.size < 25 && expandState !== false;
260
+ const expanded = item.children.length ? expandState ?? autoExpandMatches : void 0;
261
+ const itemData = {
262
+ depth,
263
+ expanded,
264
+ parent: rootItem === parent ? null : parent,
265
+ next: null,
266
+ prev: lastItem
267
+ };
268
+ if (lastItem)
269
+ result.get(lastItem).next = item;
270
+ lastItem = item;
271
+ result.set(item, itemData);
272
+ if (expanded)
273
+ appendChildren(item, depth + 1);
274
+ }
275
+ };
276
+ appendChildren(rootItem, 0);
277
+ return result;
278
+ }
279
+ function testStatusIcon(status) {
280
+ if (status === "scheduled")
281
+ return "codicon-clock";
282
+ if (status === "running")
283
+ return "codicon-loading";
284
+ if (status === "failed")
285
+ return "codicon-error";
286
+ if (status === "passed")
287
+ return "codicon-check";
288
+ if (status === "skipped")
289
+ return "codicon-circle-slash";
290
+ return "codicon-circle-outline";
291
+ }
292
+ function testStatusText(status) {
293
+ if (status === "scheduled")
294
+ return "Pending";
295
+ if (status === "running")
296
+ return "Running";
297
+ if (status === "failed")
298
+ return "Failed";
299
+ if (status === "passed")
300
+ return "Passed";
301
+ if (status === "skipped")
302
+ return "Skipped";
303
+ return "Did not run";
304
+ }
305
+ const ActionTreeView = TreeView;
306
+ const ActionList = ({
307
+ actions,
308
+ selectedAction,
309
+ selectedTime,
310
+ setSelectedTime,
311
+ sdkLanguage,
312
+ onSelected,
313
+ onHighlighted,
314
+ revealConsole,
315
+ revealAttachment,
316
+ isLive
317
+ }) => {
318
+ const [treeState, setTreeState] = reactExports.useState({ expandedItems: /* @__PURE__ */ new Map() });
319
+ const { rootItem, itemMap } = reactExports.useMemo(() => buildActionTree(actions), [actions]);
320
+ const { selectedItem } = reactExports.useMemo(() => {
321
+ const selectedItem2 = selectedAction ? itemMap.get(selectedAction.callId) : void 0;
322
+ return { selectedItem: selectedItem2 };
323
+ }, [itemMap, selectedAction]);
324
+ const isError = reactExports.useCallback((item) => {
325
+ var _a, _b;
326
+ return !!((_b = (_a = item.action) == null ? void 0 : _a.error) == null ? void 0 : _b.message);
327
+ }, []);
328
+ const onAccepted = reactExports.useCallback((item) => {
329
+ return setSelectedTime({ minimum: item.action.startTime, maximum: item.action.endTime });
330
+ }, [setSelectedTime]);
331
+ const render = reactExports.useCallback((item) => {
332
+ return renderAction(item.action, { sdkLanguage, revealConsole, revealAttachment, isLive, showDuration: true, showBadges: true });
333
+ }, [isLive, revealConsole, revealAttachment, sdkLanguage]);
334
+ const isVisible = reactExports.useCallback((item) => {
335
+ return !selectedTime || !item.action || item.action.startTime <= selectedTime.maximum && item.action.endTime >= selectedTime.minimum;
336
+ }, [selectedTime]);
337
+ const onSelectedAction = reactExports.useCallback((item) => {
338
+ onSelected == null ? void 0 : onSelected(item.action);
339
+ }, [onSelected]);
340
+ const onHighlightedAction = reactExports.useCallback((item) => {
341
+ onHighlighted == null ? void 0 : onHighlighted(item == null ? void 0 : item.action);
342
+ }, [onHighlighted]);
343
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", children: [
344
+ selectedTime && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-list-show-all", onClick: () => setSelectedTime(void 0), children: [
345
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-triangle-left" }),
346
+ "Show all"
347
+ ] }),
348
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
349
+ ActionTreeView,
350
+ {
351
+ name: "actions",
352
+ rootItem,
353
+ treeState,
354
+ setTreeState,
355
+ selectedItem,
356
+ onSelected: onSelectedAction,
357
+ onHighlighted: onHighlightedAction,
358
+ onAccepted,
359
+ isError,
360
+ isVisible,
361
+ render
362
+ }
363
+ )
364
+ ] });
365
+ };
366
+ const renderAction = (action, options) => {
367
+ var _a, _b;
368
+ const { sdkLanguage, revealConsole, revealAttachment, isLive, showDuration, showBadges } = options;
369
+ const { errors, warnings } = stats(action);
370
+ const showAttachments = !!((_a = action.attachments) == null ? void 0 : _a.length) && !!revealAttachment;
371
+ const parameterString = actionParameterDisplayString(action, sdkLanguage || "javascript");
372
+ const isSkipped = action.class === "Test" && action.method === "step" && ((_b = action.annotations) == null ? void 0 : _b.some((a2) => a2.type === "skip"));
373
+ let time = "";
374
+ if (action.endTime)
375
+ time = msToString(action.endTime - action.startTime);
376
+ else if (action.error)
377
+ time = "Timed out";
378
+ else if (!isLive)
379
+ time = "-";
380
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
381
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-title", title: action.apiName, children: [
382
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: action.apiName }),
383
+ parameterString && (parameterString.type === "locator" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
384
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "action-parameter action-locator-parameter", children: parameterString.value }),
385
+ parameterString.childDisplayString && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "action-parameter action-generic-parameter", children: parameterString.childDisplayString.value })
386
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "action-parameter action-generic-parameter", children: parameterString.value })),
387
+ action.method === "goto" && action.params.url && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-url", title: action.params.url, children: action.params.url }),
388
+ action.class === "APIRequestContext" && action.params.url && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-url", title: action.params.url, children: excludeOrigin(action.params.url) })
389
+ ] }),
390
+ (showDuration || showBadges || showAttachments || isSkipped) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "spacer" }),
391
+ showAttachments && /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { icon: "attach", title: "Open Attachment", onClick: () => revealAttachment(action.attachments[0]) }),
392
+ showDuration && !isSkipped && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "action-duration", children: time || /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-loading" }) }),
393
+ isSkipped && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("action-skipped", "codicon", testStatusIcon("skipped")), title: "skipped" }),
394
+ showBadges && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-icons", onClick: () => revealConsole == null ? void 0 : revealConsole(), children: [
395
+ !!errors && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-icon", children: [
396
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-error" }),
397
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "action-icon-value", children: errors })
398
+ ] }),
399
+ !!warnings && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-icon", children: [
400
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-warning" }),
401
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "action-icon-value", children: warnings })
402
+ ] })
403
+ ] })
404
+ ] });
405
+ };
406
+ function excludeOrigin(url) {
407
+ try {
408
+ const urlObject = new URL(url);
409
+ return urlObject.pathname + urlObject.search;
410
+ } catch (error) {
411
+ return url;
412
+ }
413
+ }
414
+ const clockDisplayString = (action) => {
415
+ switch (action.method) {
416
+ case "clockPauseAt":
417
+ case "clockSetFixedTime":
418
+ case "clockSetSystemTime": {
419
+ if (action.params.timeString === void 0 && action.params.timeNumber === void 0)
420
+ return void 0;
421
+ return {
422
+ type: "generic",
423
+ value: new Date(
424
+ action.params.timeString ?? action.params.timeNumber
425
+ ).toLocaleString(void 0, { timeZone: "UTC" })
426
+ };
427
+ }
428
+ case "clockFastForward":
429
+ case "clockRunFor": {
430
+ if (action.params.ticksNumber === void 0 && action.params.ticksString === void 0)
431
+ return void 0;
432
+ return {
433
+ type: "generic",
434
+ value: action.params.ticksString ?? `${action.params.ticksNumber}ms`
435
+ };
436
+ }
437
+ }
438
+ return void 0;
439
+ };
440
+ const keyboardDisplayString = (action) => {
441
+ switch (action.method) {
442
+ case "press":
443
+ case "keyboardPress":
444
+ case "keyboardDown":
445
+ case "keyboardUp": {
446
+ if (action.params.key === void 0)
447
+ return void 0;
448
+ return { type: "generic", value: action.params.key };
449
+ }
450
+ case "type":
451
+ case "fill":
452
+ case "keyboardType":
453
+ case "keyboardInsertText": {
454
+ const string = action.params.text ?? action.params.value;
455
+ if (string === void 0)
456
+ return void 0;
457
+ return { type: "generic", value: `"${string}"` };
458
+ }
459
+ }
460
+ };
461
+ const mouseDisplayString = (action) => {
462
+ switch (action.method) {
463
+ case "click":
464
+ case "dblclick":
465
+ case "mouseClick":
466
+ case "mouseMove": {
467
+ if (action.params.x === void 0 || action.params.y === void 0)
468
+ return void 0;
469
+ return {
470
+ type: "generic",
471
+ value: `(${action.params.x}, ${action.params.y})`
472
+ };
473
+ }
474
+ case "mouseWheel": {
475
+ if (action.params.deltaX === void 0 || action.params.deltaY === void 0)
476
+ return void 0;
477
+ return {
478
+ type: "generic",
479
+ value: `(${action.params.deltaX}, ${action.params.deltaY})`
480
+ };
481
+ }
482
+ }
483
+ };
484
+ const touchscreenDisplayString = (action) => {
485
+ switch (action.method) {
486
+ case "tap": {
487
+ if (action.params.x === void 0 || action.params.y === void 0)
488
+ return void 0;
489
+ return {
490
+ type: "generic",
491
+ value: `(${action.params.x}, ${action.params.y})`
492
+ };
493
+ }
494
+ }
495
+ };
496
+ const actionParameterDisplayString = (action, sdkLanguage, ignoreLocator = false) => {
497
+ const params = action.params;
498
+ if (!ignoreLocator && params.selector !== void 0) {
499
+ return {
500
+ type: "locator",
501
+ value: asLocator(sdkLanguage, params.selector),
502
+ childDisplayString: actionParameterDisplayString(
503
+ action,
504
+ sdkLanguage,
505
+ true
506
+ )
507
+ };
508
+ }
509
+ switch (action.class.toLowerCase()) {
510
+ case "browsercontext":
511
+ return clockDisplayString(action);
512
+ case "page":
513
+ case "frame":
514
+ case "elementhandle":
515
+ return keyboardDisplayString(action) ?? mouseDisplayString(action) ?? touchscreenDisplayString(action);
516
+ }
517
+ return void 0;
518
+ };
519
+ const CallTab = ({ action, startTimeOffset, sdkLanguage }) => {
520
+ const paramKeys = reactExports.useMemo(() => Object.keys((action == null ? void 0 : action.params) ?? {}).filter((name) => name !== "info"), [action]);
521
+ if (!action)
522
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No action selected" });
523
+ const startTimeMillis = action.startTime - startTimeOffset;
524
+ const startTime = msToString(startTimeMillis);
525
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-tab", children: [
526
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-line", children: action.apiName }),
527
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Time" }),
528
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DateTimeCallLine, { name: "start:", value: startTime }),
529
+ /* @__PURE__ */ jsxRuntimeExports.jsx(DateTimeCallLine, { name: "duration:", value: renderDuration(action) }),
530
+ !!paramKeys.length && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
531
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Parameters" }),
532
+ paramKeys.map((name) => renderProperty(propertyToString(action, name, action.params[name], sdkLanguage)))
533
+ ] }),
534
+ !!action.result && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
535
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Return value" }),
536
+ Object.keys(action.result).map(
537
+ (name) => renderProperty(propertyToString(action, name, action.result[name], sdkLanguage))
538
+ )
539
+ ] })
540
+ ] });
541
+ };
542
+ const DateTimeCallLine = ({ name, value }) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
543
+ name,
544
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value datetime", title: value, children: value })
545
+ ] });
546
+ function renderDuration(action) {
547
+ if (action.endTime)
548
+ return msToString(action.endTime - action.startTime);
549
+ else if (!!action.error)
550
+ return "Timed Out";
551
+ else
552
+ return "Running";
553
+ }
554
+ function renderProperty(property) {
555
+ let text = property.text.replace(/\n/g, "↵");
556
+ if (property.type === "string")
557
+ text = `"${text}"`;
558
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
559
+ property.name,
560
+ ":",
561
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("call-value", property.type), title: property.text, children: text }),
562
+ ["string", "number", "object", "locator"].includes(property.type) && /* @__PURE__ */ jsxRuntimeExports.jsx(CopyToClipboard, { value: property.text })
563
+ ] }, property.name);
564
+ }
565
+ function propertyToString(event, name, value, sdkLanguage) {
566
+ const isEval = event.method.includes("eval") || event.method === "waitForFunction";
567
+ if (name === "files")
568
+ return { text: "<files>", type: "string", name };
569
+ if (name === "eventInit" || name === "expectedValue" || name === "arg" && isEval)
570
+ value = parseSerializedValue(value.value, new Array(10).fill({ handle: "<handle>" }));
571
+ if (name === "value" && isEval || name === "received" && event.method === "expect")
572
+ value = parseSerializedValue(value, new Array(10).fill({ handle: "<handle>" }));
573
+ if (name === "selector")
574
+ return { text: asLocator(sdkLanguage || "javascript", event.params.selector), type: "locator", name: "locator" };
575
+ const type = typeof value;
576
+ if (type !== "object" || value === null)
577
+ return { text: String(value), type, name };
578
+ if (value.guid)
579
+ return { text: "<handle>", type: "handle", name };
580
+ return { text: JSON.stringify(value).slice(0, 1e3), type: "object", name };
581
+ }
582
+ function parseSerializedValue(value, handles) {
583
+ if (value.n !== void 0)
584
+ return value.n;
585
+ if (value.s !== void 0)
586
+ return value.s;
587
+ if (value.b !== void 0)
588
+ return value.b;
589
+ if (value.v !== void 0) {
590
+ if (value.v === "undefined")
591
+ return void 0;
592
+ if (value.v === "null")
593
+ return null;
594
+ if (value.v === "NaN")
595
+ return NaN;
596
+ if (value.v === "Infinity")
597
+ return Infinity;
598
+ if (value.v === "-Infinity")
599
+ return -Infinity;
600
+ if (value.v === "-0")
601
+ return -0;
602
+ }
603
+ if (value.d !== void 0)
604
+ return new Date(value.d);
605
+ if (value.r !== void 0)
606
+ return new RegExp(value.r.p, value.r.f);
607
+ if (value.a !== void 0)
608
+ return value.a.map((a2) => parseSerializedValue(a2, handles));
609
+ if (value.o !== void 0) {
610
+ const result = {};
611
+ for (const { k: k2, v: v2 } of value.o)
612
+ result[k2] = parseSerializedValue(v2, handles);
613
+ return result;
614
+ }
615
+ if (value.h !== void 0) {
616
+ if (handles === void 0)
617
+ return "<object>";
618
+ return handles[value.h];
619
+ }
620
+ return "<object>";
621
+ }
622
+ const LogList = ListView;
623
+ const LogTab = ({ action, isLive }) => {
624
+ const entries = reactExports.useMemo(() => {
625
+ var _a;
626
+ if (!action || !action.log.length)
627
+ return [];
628
+ const log = action.log;
629
+ const wallTimeOffset = action.context.wallTime - action.context.startTime;
630
+ const entries2 = [];
631
+ for (let i2 = 0; i2 < log.length; ++i2) {
632
+ let time = "";
633
+ if (log[i2].time !== -1) {
634
+ const timeStart = (_a = log[i2]) == null ? void 0 : _a.time;
635
+ if (i2 + 1 < log.length)
636
+ time = msToString(log[i2 + 1].time - timeStart);
637
+ else if (action.endTime > 0)
638
+ time = msToString(action.endTime - timeStart);
639
+ else if (isLive)
640
+ time = msToString(Date.now() - wallTimeOffset - timeStart);
641
+ else
642
+ time = "-";
643
+ }
644
+ entries2.push({
645
+ message: log[i2].message,
646
+ time
647
+ });
648
+ }
649
+ return entries2;
650
+ }, [action, isLive]);
651
+ if (!entries.length)
652
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No log entries" });
653
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
654
+ LogList,
655
+ {
656
+ name: "log",
657
+ items: entries,
658
+ render: (entry) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "log-list-item", children: [
659
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "log-list-duration", children: entry.time }),
660
+ entry.message
661
+ ] }),
662
+ notSelectable: true
663
+ }
664
+ );
665
+ };
666
+ const ErrorMessage = ({ error }) => {
667
+ const html = reactExports.useMemo(() => ansi2html(error), [error]);
668
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "error-message", dangerouslySetInnerHTML: { __html: html || "" } });
669
+ };
670
+ function t() {
671
+ return t = Object.assign ? Object.assign.bind() : function(e) {
672
+ for (var t2 = 1; t2 < arguments.length; t2++) {
673
+ var n2 = arguments[t2];
674
+ for (var r2 in n2) Object.prototype.hasOwnProperty.call(n2, r2) && (e[r2] = n2[r2]);
675
+ }
676
+ return e;
677
+ }, t.apply(this, arguments);
678
+ }
679
+ const n = ["children", "options"], r = { blockQuote: "0", breakLine: "1", breakThematic: "2", codeBlock: "3", codeFenced: "4", codeInline: "5", footnote: "6", footnoteReference: "7", gfmTask: "8", heading: "9", headingSetext: "10", htmlBlock: "11", htmlComment: "12", htmlSelfClosing: "13", image: "14", link: "15", linkAngleBraceStyleDetector: "16", linkBareUrlDetector: "17", linkMailtoDetector: "18", newlineCoalescer: "19", orderedList: "20", paragraph: "21", ref: "22", refImage: "23", refLink: "24", table: "25", text: "27", textBolded: "28", textEmphasized: "29", textEscaped: "30", textMarked: "31", textStrikethroughed: "32", unorderedList: "33" };
680
+ var i;
681
+ !function(e) {
682
+ e[e.MAX = 0] = "MAX", e[e.HIGH = 1] = "HIGH", e[e.MED = 2] = "MED", e[e.LOW = 3] = "LOW", e[e.MIN = 4] = "MIN";
683
+ }(i || (i = {}));
684
+ const l = ["allowFullScreen", "allowTransparency", "autoComplete", "autoFocus", "autoPlay", "cellPadding", "cellSpacing", "charSet", "classId", "colSpan", "contentEditable", "contextMenu", "crossOrigin", "encType", "formAction", "formEncType", "formMethod", "formNoValidate", "formTarget", "frameBorder", "hrefLang", "inputMode", "keyParams", "keyType", "marginHeight", "marginWidth", "maxLength", "mediaGroup", "minLength", "noValidate", "radioGroup", "readOnly", "rowSpan", "spellCheck", "srcDoc", "srcLang", "srcSet", "tabIndex", "useMap"].reduce((e, t2) => (e[t2.toLowerCase()] = t2, e), { class: "className", for: "htmlFor" }), a = { amp: "&", apos: "'", gt: ">", lt: "<", nbsp: " ", quot: "“" }, o = ["style", "script"], c = /([-A-Z0-9_:]+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|(?:\{((?:\\.|{[^}]*?}|[^}])*)\})))?/gi, s = /mailto:/i, d = /\n{2,}$/, u = /^(\s*>[\s\S]*?)(?=\n\n|$)/, p = /^ *> ?/gm, f = /^(?:\[!([^\]]*)\]\n)?([\s\S]*)/, h = /^ {2,}\n/, m = /^(?:( *[-*_])){3,} *(?:\n *)+\n/, g = /^(?: {1,3})?(`{3,}|~{3,}) *(\S+)? *([^\n]*?)?\n([\s\S]*?)(?:\1\n?|$)/, y = /^(?: {4}[^\n]+\n*)+(?:\n *)+\n?/, k = /^(`+)((?:\\`|[^`])+)\1/, x = /^(?:\n *)*\n/, b = /\r\n?/g, v = /^\[\^([^\]]+)](:(.*)((\n+ {4,}.*)|(\n(?!\[\^).+))*)/, C = /^\[\^([^\]]+)]/, $ = /\f/g, S = /^---[ \t]*\n(.|\n)*\n---[ \t]*\n/, w = /^\s*?\[(x|\s)\]/, E = /^ *(#{1,6}) *([^\n]+?)(?: +#*)?(?:\n *)*(?:\n|$)/, z = /^ *(#{1,6}) +([^\n]+?)(?: +#*)?(?:\n *)*(?:\n|$)/, L = /^([^\n]+)\n *(=|-){3,} *(?:\n *)+\n/, A = /^ *(?!<[a-z][^ >/]* ?\/>)<([a-z][^ >/]*) ?((?:[^>]*[^/])?)>\n?(\s*(?:<\1[^>]*?>[\s\S]*?<\/\1>|(?!<\1\b)[\s\S])*?)<\/\1>(?!<\/\1>)\n*/i, T = /&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-fA-F]{1,6});/gi, B = /^<!--[\s\S]*?(?:-->)/, O = /^(data|aria|x)-[a-z_][a-z\d_.-]*$/, M = /^ *<([a-z][a-z0-9:]*)(?:\s+((?:<.*?>|[^>])*))?\/?>(?!<\/\1>)(\s*\n)?/i, R = /^\{.*\}$/, I = /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, U = /^<([^ >]+@[^ >]+)>/, D = /^<([^ >]+:\/[^ >]+)>/, N = /-([a-z])?/gi, j = /^(\|.*)\n(?: *(\|? *[-:]+ *\|[-| :]*)\n((?:.*\|.*\n)*))?\n?/, H = /^\[([^\]]*)\]:\s+<?([^\s>]+)>?\s*("([^"]*)")?/, P = /^!\[([^\]]*)\] ?\[([^\]]*)\]/, _ = /^\[([^\]]*)\] ?\[([^\]]*)\]/, F = /(\n|^[-*]\s|^#|^ {2,}|^-{2,}|^>\s)/, G = /\t/g, W = /(^ *\||\| *$)/g, Z = /^ *:-+: *$/, q = /^ *:-+ *$/, Q = /^ *-+: *$/, V = "((?:\\[.*?\\][([].*?[)\\]]|<.*?>(?:.*?<.*?>)?|`.*?`|\\\\\\1|[\\s\\S])+?)", X = new RegExp(`^([*_])\\1${V}\\1\\1(?!\\1)`), J = new RegExp(`^([*_])${V}\\1(?!\\1)`), K = new RegExp(`^(==)${V}\\1`), Y = new RegExp(`^(~~)${V}\\1`), ee = /^\\([^0-9A-Za-z\s])/, te = /\\([^0-9A-Za-z\s])/g, ne = /^([\s\S](?:(?! |[0-9]\.)[^*_~\-\n<`\\\[!])*)/, re = /^\n+/, ie = /^([ \t]*)/, le = /\\([^\\])/g, ae = /(?:^|\n)( *)$/, oe = "(?:\\d+\\.)", ce = "(?:[*+-])";
685
+ function se(e) {
686
+ return "( *)(" + (1 === e ? oe : ce) + ") +";
687
+ }
688
+ const de = se(1), ue = se(2);
689
+ function pe(e) {
690
+ return new RegExp("^" + (1 === e ? de : ue));
691
+ }
692
+ const fe = pe(1), he = pe(2);
693
+ function me(e) {
694
+ return new RegExp("^" + (1 === e ? de : ue) + "[^\\n]*(?:\\n(?!\\1" + (1 === e ? oe : ce) + " )[^\\n]*)*(\\n|$)", "gm");
695
+ }
696
+ const ge = me(1), ye = me(2);
697
+ function ke(e) {
698
+ const t2 = 1 === e ? oe : ce;
699
+ return new RegExp("^( *)(" + t2 + ") [\\s\\S]+?(?:\\n{2,}(?! )(?!\\1" + t2 + " (?!" + t2 + " ))\\n*|\\s*\\n*$)");
700
+ }
701
+ const xe = ke(1), be = ke(2);
702
+ function ve(e, t2) {
703
+ const n2 = 1 === t2, i2 = n2 ? xe : be, l2 = n2 ? ge : ye, a2 = n2 ? fe : he;
704
+ return { match: Oe(function(e2, t3) {
705
+ const n3 = ae.exec(t3.prevCapture);
706
+ return n3 && (t3.list || !t3.inline && !t3.simple) ? i2.exec(e2 = n3[1] + e2) : null;
707
+ }), order: 1, parse(e2, t3, r2) {
708
+ const i3 = n2 ? +e2[2] : void 0, o2 = e2[0].replace(d, "\n").match(l2);
709
+ let c2 = false;
710
+ return { items: o2.map(function(e3, n3) {
711
+ const i4 = a2.exec(e3)[0].length, l3 = new RegExp("^ {1," + i4 + "}", "gm"), s2 = e3.replace(l3, "").replace(a2, ""), d2 = n3 === o2.length - 1, u2 = -1 !== s2.indexOf("\n\n") || d2 && c2;
712
+ c2 = u2;
713
+ const p2 = r2.inline, f2 = r2.list;
714
+ let h2;
715
+ r2.list = true, u2 ? (r2.inline = false, h2 = Ee(s2) + "\n\n") : (r2.inline = true, h2 = Ee(s2));
716
+ const m2 = t3(h2, r2);
717
+ return r2.inline = p2, r2.list = f2, m2;
718
+ }), ordered: n2, start: i3 };
719
+ }, render: (t3, n3, i3) => e(t3.ordered ? "ol" : "ul", { key: i3.key, start: t3.type === r.orderedList ? t3.start : void 0 }, t3.items.map(function(t4, r2) {
720
+ return e("li", { key: r2 }, n3(t4, i3));
721
+ })) };
722
+ }
723
+ const Ce = new RegExp(`^\\[((?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*)\\]\\(\\s*<?((?:\\([^)]*\\)|[^\\s\\\\]|\\\\.)*?)>?(?:\\s+['"]([\\s\\S]*?)['"])?\\s*\\)`), $e = /^!\[(.*?)\]\( *((?:\([^)]*\)|[^() ])*) *"?([^)"]*)?"?\)/, Se = [u, g, y, E, L, z, j, xe, be], we = [...Se, /^[^\n]+(?: \n|\n{2,})/, A, B, M];
724
+ function Ee(e) {
725
+ let t2 = e.length;
726
+ for (; t2 > 0 && e[t2 - 1] <= " "; ) t2--;
727
+ return e.slice(0, t2);
728
+ }
729
+ function ze(e) {
730
+ return e.replace(/[ÀÁÂÃÄÅàáâãä忯]/g, "a").replace(/[çÇ]/g, "c").replace(/[ðÐ]/g, "d").replace(/[ÈÉÊËéèêë]/g, "e").replace(/[ÏïÎîÍíÌì]/g, "i").replace(/[Ññ]/g, "n").replace(/[øØœŒÕõÔôÓóÒò]/g, "o").replace(/[ÜüÛûÚúÙù]/g, "u").replace(/[ŸÿÝý]/g, "y").replace(/[^a-z0-9- ]/gi, "").replace(/ /gi, "-").toLowerCase();
731
+ }
732
+ function Le(e) {
733
+ return Q.test(e) ? "right" : Z.test(e) ? "center" : q.test(e) ? "left" : null;
734
+ }
735
+ function Ae(e, t2, n2, r2) {
736
+ const i2 = n2.inTable;
737
+ n2.inTable = true;
738
+ let l2 = [[]], a2 = "";
739
+ function o2() {
740
+ if (!a2) return;
741
+ const e2 = l2[l2.length - 1];
742
+ e2.push.apply(e2, t2(a2, n2)), a2 = "";
743
+ }
744
+ return e.trim().split(/(`[^`]*`|\\\||\|)/).filter(Boolean).forEach((e2, t3, n3) => {
745
+ "|" === e2.trim() && (o2(), r2) ? 0 !== t3 && t3 !== n3.length - 1 && l2.push([]) : a2 += e2;
746
+ }), o2(), n2.inTable = i2, l2;
747
+ }
748
+ function Te(e, t2, n2) {
749
+ n2.inline = true;
750
+ const i2 = e[2] ? e[2].replace(W, "").split("|").map(Le) : [], l2 = e[3] ? function(e2, t3, n3) {
751
+ return e2.trim().split("\n").map(function(e3) {
752
+ return Ae(e3, t3, n3, true);
753
+ });
754
+ }(e[3], t2, n2) : [], a2 = Ae(e[1], t2, n2, !!l2.length);
755
+ return n2.inline = false, l2.length ? { align: i2, cells: l2, header: a2, type: r.table } : { children: a2, type: r.paragraph };
756
+ }
757
+ function Be(e, t2) {
758
+ return null == e.align[t2] ? {} : { textAlign: e.align[t2] };
759
+ }
760
+ function Oe(e) {
761
+ return e.inline = 1, e;
762
+ }
763
+ function Me(e) {
764
+ return Oe(function(t2, n2) {
765
+ return n2.inline ? e.exec(t2) : null;
766
+ });
767
+ }
768
+ function Re(e) {
769
+ return Oe(function(t2, n2) {
770
+ return n2.inline || n2.simple ? e.exec(t2) : null;
771
+ });
772
+ }
773
+ function Ie(e) {
774
+ return function(t2, n2) {
775
+ return n2.inline || n2.simple ? null : e.exec(t2);
776
+ };
777
+ }
778
+ function Ue(e) {
779
+ return Oe(function(t2) {
780
+ return e.exec(t2);
781
+ });
782
+ }
783
+ function De(e, t2) {
784
+ if (t2.inline || t2.simple) return null;
785
+ let n2 = "";
786
+ e.split("\n").every((e2) => (e2 += "\n", !Se.some((t3) => t3.test(e2)) && (n2 += e2, !!e2.trim())));
787
+ const r2 = Ee(n2);
788
+ return "" == r2 ? null : [n2, , r2];
789
+ }
790
+ function Ne(e) {
791
+ try {
792
+ if (decodeURIComponent(e).replace(/[^A-Za-z0-9/:]/g, "").match(/^\s*(javascript|vbscript|data(?!:image)):/i)) return null;
793
+ } catch (e2) {
794
+ return null;
795
+ }
796
+ return e;
797
+ }
798
+ function je(e) {
799
+ return e.replace(le, "$1");
800
+ }
801
+ function He(e, t2, n2) {
802
+ const r2 = n2.inline || false, i2 = n2.simple || false;
803
+ n2.inline = true, n2.simple = true;
804
+ const l2 = e(t2, n2);
805
+ return n2.inline = r2, n2.simple = i2, l2;
806
+ }
807
+ function Pe(e, t2, n2) {
808
+ const r2 = n2.inline || false, i2 = n2.simple || false;
809
+ n2.inline = false, n2.simple = true;
810
+ const l2 = e(t2, n2);
811
+ return n2.inline = r2, n2.simple = i2, l2;
812
+ }
813
+ function _e(e, t2, n2) {
814
+ const r2 = n2.inline || false;
815
+ n2.inline = false;
816
+ const i2 = e(t2, n2);
817
+ return n2.inline = r2, i2;
818
+ }
819
+ const Fe = (e, t2, n2) => ({ children: He(t2, e[2], n2) });
820
+ function Ge() {
821
+ return {};
822
+ }
823
+ function We() {
824
+ return null;
825
+ }
826
+ function Ze(...e) {
827
+ return e.filter(Boolean).join(" ");
828
+ }
829
+ function qe(e, t2, n2) {
830
+ let r2 = e;
831
+ const i2 = t2.split(".");
832
+ for (; i2.length && (r2 = r2[i2[0]], void 0 !== r2); ) i2.shift();
833
+ return r2 || n2;
834
+ }
835
+ function Qe(n2 = "", i2 = {}) {
836
+ function d2(e, n3, ...r2) {
837
+ const l2 = qe(i2.overrides, `${e}.props`, {});
838
+ return i2.createElement(function(e2, t2) {
839
+ const n4 = qe(t2, e2);
840
+ return n4 ? "function" == typeof n4 || "object" == typeof n4 && "render" in n4 ? n4 : qe(t2, `${e2}.component`, e2) : e2;
841
+ }(e, i2.overrides), t({}, n3, l2, { className: Ze(null == n3 ? void 0 : n3.className, l2.className) || void 0 }), ...r2);
842
+ }
843
+ function W2(e) {
844
+ e = e.replace(S, "");
845
+ let t2 = false;
846
+ i2.forceInline ? t2 = true : i2.forceBlock || (t2 = false === F.test(e));
847
+ const n3 = ae2(le2(t2 ? e : `${Ee(e).replace(re, "")}
848
+
849
+ `, { inline: t2 }));
850
+ for (; "string" == typeof n3[n3.length - 1] && !n3[n3.length - 1].trim(); ) n3.pop();
851
+ if (null === i2.wrapper) return n3;
852
+ const r2 = i2.wrapper || (t2 ? "span" : "div");
853
+ let l2;
854
+ if (n3.length > 1 || i2.forceWrapper) l2 = n3;
855
+ else {
856
+ if (1 === n3.length) return l2 = n3[0], "string" == typeof l2 ? d2("span", { key: "outer" }, l2) : l2;
857
+ l2 = null;
858
+ }
859
+ return i2.createElement(r2, { key: "outer" }, l2);
860
+ }
861
+ function Z2(e, t2) {
862
+ const n3 = t2.match(c);
863
+ return n3 ? n3.reduce(function(t3, n4) {
864
+ const r2 = n4.indexOf("=");
865
+ if (-1 !== r2) {
866
+ const a2 = function(e2) {
867
+ return -1 !== e2.indexOf("-") && null === e2.match(O) && (e2 = e2.replace(N, function(e3, t4) {
868
+ return t4.toUpperCase();
869
+ })), e2;
870
+ }(n4.slice(0, r2)).trim(), o2 = function(e2) {
871
+ const t4 = e2[0];
872
+ return ('"' === t4 || "'" === t4) && e2.length >= 2 && e2[e2.length - 1] === t4 ? e2.slice(1, -1) : e2;
873
+ }(n4.slice(r2 + 1).trim()), c2 = l[a2] || a2;
874
+ if ("ref" === c2) return t3;
875
+ const s2 = t3[c2] = function(e2, t4, n5, r3) {
876
+ return "style" === t4 ? n5.split(/;\s?/).reduce(function(e3, t5) {
877
+ const n6 = t5.slice(0, t5.indexOf(":"));
878
+ return e3[n6.trim().replace(/(-[a-z])/g, (e4) => e4[1].toUpperCase())] = t5.slice(n6.length + 1).trim(), e3;
879
+ }, {}) : "href" === t4 || "src" === t4 ? r3(n5, e2, t4) : (n5.match(R) && (n5 = n5.slice(1, n5.length - 1)), "true" === n5 || "false" !== n5 && n5);
880
+ }(e, a2, o2, i2.sanitizer);
881
+ "string" == typeof s2 && (A.test(s2) || M.test(s2)) && (t3[c2] = W2(s2.trim()));
882
+ } else "style" !== n4 && (t3[l[n4] || n4] = true);
883
+ return t3;
884
+ }, {}) : null;
885
+ }
886
+ i2.overrides = i2.overrides || {}, i2.sanitizer = i2.sanitizer || Ne, i2.slugify = i2.slugify || ze, i2.namedCodesToUnicode = i2.namedCodesToUnicode ? t({}, a, i2.namedCodesToUnicode) : a, i2.createElement = i2.createElement || reactExports.createElement;
887
+ const q2 = [], Q2 = {}, V2 = { [r.blockQuote]: { match: Ie(u), order: 1, parse(e, t2, n3) {
888
+ const [, r2, i3] = e[0].replace(p, "").match(f);
889
+ return { alert: r2, children: t2(i3, n3) };
890
+ }, render(e, t2, n3) {
891
+ const l2 = { key: n3.key };
892
+ return e.alert && (l2.className = "markdown-alert-" + i2.slugify(e.alert.toLowerCase(), ze), e.children.unshift({ attrs: {}, children: [{ type: r.text, text: e.alert }], noInnerParse: true, type: r.htmlBlock, tag: "header" })), d2("blockquote", l2, t2(e.children, n3));
893
+ } }, [r.breakLine]: { match: Ue(h), order: 1, parse: Ge, render: (e, t2, n3) => d2("br", { key: n3.key }) }, [r.breakThematic]: { match: Ie(m), order: 1, parse: Ge, render: (e, t2, n3) => d2("hr", { key: n3.key }) }, [r.codeBlock]: { match: Ie(y), order: 0, parse: (e) => ({ lang: void 0, text: Ee(e[0].replace(/^ {4}/gm, "")).replace(te, "$1") }), render: (e, n3, r2) => d2("pre", { key: r2.key }, d2("code", t({}, e.attrs, { className: e.lang ? `lang-${e.lang}` : "" }), e.text)) }, [r.codeFenced]: { match: Ie(g), order: 0, parse: (e) => ({ attrs: Z2("code", e[3] || ""), lang: e[2] || void 0, text: e[4].replace(te, "$1"), type: r.codeBlock }) }, [r.codeInline]: { match: Re(k), order: 3, parse: (e) => ({ text: e[2].replace(te, "$1") }), render: (e, t2, n3) => d2("code", { key: n3.key }, e.text) }, [r.footnote]: { match: Ie(v), order: 0, parse: (e) => (q2.push({ footnote: e[2], identifier: e[1] }), {}), render: We }, [r.footnoteReference]: { match: Me(C), order: 1, parse: (e) => ({ target: `#${i2.slugify(e[1], ze)}`, text: e[1] }), render: (e, t2, n3) => d2("a", { key: n3.key, href: i2.sanitizer(e.target, "a", "href") }, d2("sup", { key: n3.key }, e.text)) }, [r.gfmTask]: { match: Me(w), order: 1, parse: (e) => ({ completed: "x" === e[1].toLowerCase() }), render: (e, t2, n3) => d2("input", { checked: e.completed, key: n3.key, readOnly: true, type: "checkbox" }) }, [r.heading]: { match: Ie(i2.enforceAtxHeadings ? z : E), order: 1, parse: (e, t2, n3) => ({ children: He(t2, e[2], n3), id: i2.slugify(e[2], ze), level: e[1].length }), render: (e, t2, n3) => d2(`h${e.level}`, { id: e.id, key: n3.key }, t2(e.children, n3)) }, [r.headingSetext]: { match: Ie(L), order: 0, parse: (e, t2, n3) => ({ children: He(t2, e[1], n3), level: "=" === e[2] ? 1 : 2, type: r.heading }) }, [r.htmlBlock]: { match: Ue(A), order: 1, parse(e, t2, n3) {
894
+ const [, r2] = e[3].match(ie), i3 = new RegExp(`^${r2}`, "gm"), l2 = e[3].replace(i3, ""), a2 = (c2 = l2, we.some((e2) => e2.test(c2)) ? _e : He);
895
+ var c2;
896
+ const s2 = e[1].toLowerCase(), d3 = -1 !== o.indexOf(s2), u2 = (d3 ? s2 : e[1]).trim(), p2 = { attrs: Z2(u2, e[2]), noInnerParse: d3, tag: u2 };
897
+ return n3.inAnchor = n3.inAnchor || "a" === s2, d3 ? p2.text = e[3] : p2.children = a2(t2, l2, n3), n3.inAnchor = false, p2;
898
+ }, render: (e, n3, r2) => d2(e.tag, t({ key: r2.key }, e.attrs), e.text || (e.children ? n3(e.children, r2) : "")) }, [r.htmlSelfClosing]: { match: Ue(M), order: 1, parse(e) {
899
+ const t2 = e[1].trim();
900
+ return { attrs: Z2(t2, e[2] || ""), tag: t2 };
901
+ }, render: (e, n3, r2) => d2(e.tag, t({}, e.attrs, { key: r2.key })) }, [r.htmlComment]: { match: Ue(B), order: 1, parse: () => ({}), render: We }, [r.image]: { match: Re($e), order: 1, parse: (e) => ({ alt: e[1], target: je(e[2]), title: e[3] }), render: (e, t2, n3) => d2("img", { key: n3.key, alt: e.alt || void 0, title: e.title || void 0, src: i2.sanitizer(e.target, "img", "src") }) }, [r.link]: { match: Me(Ce), order: 3, parse: (e, t2, n3) => ({ children: Pe(t2, e[1], n3), target: je(e[2]), title: e[3] }), render: (e, t2, n3) => d2("a", { key: n3.key, href: i2.sanitizer(e.target, "a", "href"), title: e.title }, t2(e.children, n3)) }, [r.linkAngleBraceStyleDetector]: { match: Me(D), order: 0, parse: (e) => ({ children: [{ text: e[1], type: r.text }], target: e[1], type: r.link }) }, [r.linkBareUrlDetector]: { match: Oe((e, t2) => t2.inAnchor || i2.disableAutoLink ? null : Me(I)(e, t2)), order: 0, parse: (e) => ({ children: [{ text: e[1], type: r.text }], target: e[1], title: void 0, type: r.link }) }, [r.linkMailtoDetector]: { match: Me(U), order: 0, parse(e) {
902
+ let t2 = e[1], n3 = e[1];
903
+ return s.test(n3) || (n3 = "mailto:" + n3), { children: [{ text: t2.replace("mailto:", ""), type: r.text }], target: n3, type: r.link };
904
+ } }, [r.orderedList]: ve(d2, 1), [r.unorderedList]: ve(d2, 2), [r.newlineCoalescer]: { match: Ie(x), order: 3, parse: Ge, render: () => "\n" }, [r.paragraph]: { match: Oe(De), order: 3, parse: Fe, render: (e, t2, n3) => d2("p", { key: n3.key }, t2(e.children, n3)) }, [r.ref]: { match: Me(H), order: 0, parse: (e) => (Q2[e[1]] = { target: e[2], title: e[4] }, {}), render: We }, [r.refImage]: { match: Re(P), order: 0, parse: (e) => ({ alt: e[1] || void 0, ref: e[2] }), render: (e, t2, n3) => Q2[e.ref] ? d2("img", { key: n3.key, alt: e.alt, src: i2.sanitizer(Q2[e.ref].target, "img", "src"), title: Q2[e.ref].title }) : null }, [r.refLink]: { match: Me(_), order: 0, parse: (e, t2, n3) => ({ children: t2(e[1], n3), fallbackChildren: e[0], ref: e[2] }), render: (e, t2, n3) => Q2[e.ref] ? d2("a", { key: n3.key, href: i2.sanitizer(Q2[e.ref].target, "a", "href"), title: Q2[e.ref].title }, t2(e.children, n3)) : d2("span", { key: n3.key }, e.fallbackChildren) }, [r.table]: { match: Ie(j), order: 1, parse: Te, render(e, t2, n3) {
905
+ const r2 = e;
906
+ return d2("table", { key: n3.key }, d2("thead", null, d2("tr", null, r2.header.map(function(e2, i3) {
907
+ return d2("th", { key: i3, style: Be(r2, i3) }, t2(e2, n3));
908
+ }))), d2("tbody", null, r2.cells.map(function(e2, i3) {
909
+ return d2("tr", { key: i3 }, e2.map(function(e3, i4) {
910
+ return d2("td", { key: i4, style: Be(r2, i4) }, t2(e3, n3));
911
+ }));
912
+ })));
913
+ } }, [r.text]: { match: Ue(ne), order: 4, parse: (e) => ({ text: e[0].replace(T, (e2, t2) => i2.namedCodesToUnicode[t2] ? i2.namedCodesToUnicode[t2] : e2) }), render: (e) => e.text }, [r.textBolded]: { match: Re(X), order: 2, parse: (e, t2, n3) => ({ children: t2(e[2], n3) }), render: (e, t2, n3) => d2("strong", { key: n3.key }, t2(e.children, n3)) }, [r.textEmphasized]: { match: Re(J), order: 3, parse: (e, t2, n3) => ({ children: t2(e[2], n3) }), render: (e, t2, n3) => d2("em", { key: n3.key }, t2(e.children, n3)) }, [r.textEscaped]: { match: Re(ee), order: 1, parse: (e) => ({ text: e[1], type: r.text }) }, [r.textMarked]: { match: Re(K), order: 3, parse: Fe, render: (e, t2, n3) => d2("mark", { key: n3.key }, t2(e.children, n3)) }, [r.textStrikethroughed]: { match: Re(Y), order: 3, parse: Fe, render: (e, t2, n3) => d2("del", { key: n3.key }, t2(e.children, n3)) } };
914
+ true === i2.disableParsingRawHTML && (delete V2[r.htmlBlock], delete V2[r.htmlSelfClosing]);
915
+ const le2 = function(e) {
916
+ let t2 = Object.keys(e);
917
+ function n3(r2, i3) {
918
+ let l2, a2, o2 = [], c2 = "", s2 = "";
919
+ for (i3.prevCapture = i3.prevCapture || ""; r2; ) {
920
+ let d3 = 0;
921
+ for (; d3 < t2.length; ) {
922
+ if (c2 = t2[d3], l2 = e[c2], i3.inline && !l2.match.inline) {
923
+ d3++;
924
+ continue;
925
+ }
926
+ const u2 = l2.match(r2, i3);
927
+ if (u2) {
928
+ s2 = u2[0], i3.prevCapture += s2, r2 = r2.substring(s2.length), a2 = l2.parse(u2, n3, i3), null == a2.type && (a2.type = c2), o2.push(a2);
929
+ break;
930
+ }
931
+ d3++;
932
+ }
933
+ }
934
+ return i3.prevCapture = "", o2;
935
+ }
936
+ return t2.sort(function(t3, n4) {
937
+ let r2 = e[t3].order, i3 = e[n4].order;
938
+ return r2 !== i3 ? r2 - i3 : t3 < n4 ? -1 : 1;
939
+ }), function(e2, t3) {
940
+ return n3(function(e3) {
941
+ return e3.replace(b, "\n").replace($, "").replace(G, " ");
942
+ }(e2), t3);
943
+ };
944
+ }(V2), ae2 = (oe2 = /* @__PURE__ */ function(e, t2) {
945
+ return function(n3, r2, i3) {
946
+ const l2 = e[n3.type].render;
947
+ return t2 ? t2(() => l2(n3, r2, i3), n3, r2, i3) : l2(n3, r2, i3);
948
+ };
949
+ }(V2, i2.renderRule), function e(t2, n3 = {}) {
950
+ if (Array.isArray(t2)) {
951
+ const r2 = n3.key, i3 = [];
952
+ let l2 = false;
953
+ for (let r3 = 0; r3 < t2.length; r3++) {
954
+ n3.key = r3;
955
+ const a2 = e(t2[r3], n3), o2 = "string" == typeof a2;
956
+ o2 && l2 ? i3[i3.length - 1] += a2 : null !== a2 && i3.push(a2), l2 = o2;
957
+ }
958
+ return n3.key = r2, i3;
959
+ }
960
+ return oe2(t2, e, n3);
961
+ });
962
+ var oe2;
963
+ const ce2 = W2(n2);
964
+ return q2.length ? d2("div", null, ce2, d2("footer", { key: "footer" }, q2.map(function(e) {
965
+ return d2("div", { id: i2.slugify(e.identifier, ze), key: e.identifier }, e.identifier, ae2(le2(e.footnote, { inline: true })));
966
+ }))) : ce2;
967
+ }
968
+ const Markdown = (t2) => {
969
+ let { children: r2 = "", options: i2 } = t2, l2 = function(e, t3) {
970
+ if (null == e) return {};
971
+ var n2, r3, i3 = {}, l3 = Object.keys(e);
972
+ for (r3 = 0; r3 < l3.length; r3++) t3.indexOf(n2 = l3[r3]) >= 0 || (i3[n2] = e[n2]);
973
+ return i3;
974
+ }(t2, n);
975
+ return reactExports.cloneElement(Qe(r2, i2), l2);
976
+ };
977
+ var Disposable;
978
+ ((Disposable2) => {
979
+ function disposeAll(disposables) {
980
+ for (const disposable of disposables.splice(0))
981
+ disposable.dispose();
982
+ }
983
+ Disposable2.disposeAll = disposeAll;
984
+ })(Disposable || (Disposable = {}));
985
+ class EventEmitter {
986
+ constructor() {
987
+ this._listeners = /* @__PURE__ */ new Set();
988
+ this.event = (listener, disposables) => {
989
+ this._listeners.add(listener);
990
+ let disposed = false;
991
+ const self = this;
992
+ const result = {
993
+ dispose() {
994
+ if (!disposed) {
995
+ disposed = true;
996
+ self._listeners.delete(listener);
997
+ }
998
+ }
999
+ };
1000
+ if (disposables)
1001
+ disposables.push(result);
1002
+ return result;
1003
+ };
1004
+ }
1005
+ fire(event) {
1006
+ const dispatch = !this._deliveryQueue;
1007
+ if (!this._deliveryQueue)
1008
+ this._deliveryQueue = [];
1009
+ for (const listener of this._listeners)
1010
+ this._deliveryQueue.push({ listener, event });
1011
+ if (!dispatch)
1012
+ return;
1013
+ for (let index = 0; index < this._deliveryQueue.length; index++) {
1014
+ const { listener, event: event2 } = this._deliveryQueue[index];
1015
+ listener.call(null, event2);
1016
+ }
1017
+ this._deliveryQueue = void 0;
1018
+ }
1019
+ dispose() {
1020
+ this._listeners.clear();
1021
+ if (this._deliveryQueue)
1022
+ this._deliveryQueue = [];
1023
+ }
1024
+ }
1025
+ async function* parseSSE(body) {
1026
+ const reader = body.pipeThrough(new TextDecoderStream()).getReader();
1027
+ let buffer = "";
1028
+ let lastEventId = "";
1029
+ let type = "";
1030
+ let data = "";
1031
+ while (true) {
1032
+ const { value, done } = await reader.read();
1033
+ if (done)
1034
+ break;
1035
+ buffer += value;
1036
+ const lines = buffer.split("\n");
1037
+ buffer = lines.pop();
1038
+ for (const line of lines) {
1039
+ if (line.length === 0) {
1040
+ if (data === "") {
1041
+ data = "";
1042
+ type = "";
1043
+ continue;
1044
+ }
1045
+ if (data[data.length - 1] === "\n")
1046
+ data = data.substring(0, data.length - 1);
1047
+ const event = { type: type || "message", data, id: lastEventId };
1048
+ type = "";
1049
+ data = "";
1050
+ yield event;
1051
+ }
1052
+ if (line[0] === ":")
1053
+ continue;
1054
+ let name = "";
1055
+ let value2 = "";
1056
+ const colon = line.indexOf(":");
1057
+ if (colon === -1) {
1058
+ name = line;
1059
+ } else {
1060
+ name = line.substring(0, colon);
1061
+ value2 = line[colon + 1] === " " ? line.substring(colon + 2) : line.substring(colon + 1);
1062
+ }
1063
+ switch (name) {
1064
+ case "event":
1065
+ type = value2;
1066
+ break;
1067
+ case "data":
1068
+ data += value2 + "\n";
1069
+ break;
1070
+ case "id":
1071
+ lastEventId = value2;
1072
+ break;
1073
+ }
1074
+ }
1075
+ }
1076
+ }
1077
+ class OpenAI {
1078
+ constructor(apiKey, baseURL = "https://api.openai.com") {
1079
+ __publicField(this, "name", "OpenAI");
1080
+ this.apiKey = apiKey;
1081
+ this.baseURL = baseURL;
1082
+ }
1083
+ async *chatCompletion(messages, signal) {
1084
+ const url = new URL("./v1/chat/completions", this.baseURL);
1085
+ const response = await fetch(url, {
1086
+ method: "POST",
1087
+ headers: {
1088
+ "Content-Type": "application/json",
1089
+ "Authorization": `Bearer ${this.apiKey}`,
1090
+ "x-pw-serviceworker": "forward"
1091
+ },
1092
+ body: JSON.stringify({
1093
+ model: "gpt-4o",
1094
+ // TODO: make configurable
1095
+ messages: messages.map(({ role, content }) => ({ role, content })),
1096
+ stream: true
1097
+ }),
1098
+ signal
1099
+ });
1100
+ if (response.status !== 200 || !response.body)
1101
+ throw new Error("Failed to chat with OpenAI, unexpected status: " + response.status + await response.text());
1102
+ for await (const sseEvent of parseSSE(response.body)) {
1103
+ const event = JSON.parse(sseEvent.data);
1104
+ if (event.object === "chat.completion.chunk") {
1105
+ if (event.choices[0].finish_reason)
1106
+ break;
1107
+ yield event.choices[0].delta.content;
1108
+ }
1109
+ }
1110
+ }
1111
+ }
1112
+ class Anthropic {
1113
+ constructor(apiKey, baseURL = "https://api.anthropic.com") {
1114
+ __publicField(this, "name", "Anthropic");
1115
+ this.apiKey = apiKey;
1116
+ this.baseURL = baseURL;
1117
+ }
1118
+ async *chatCompletion(messages, signal) {
1119
+ var _a;
1120
+ const response = await fetch(new URL("./v1/messages", this.baseURL), {
1121
+ method: "POST",
1122
+ headers: {
1123
+ "Content-Type": "application/json",
1124
+ "x-api-key": this.apiKey,
1125
+ "anthropic-version": "2023-06-01",
1126
+ "x-pw-serviceworker": "forward"
1127
+ },
1128
+ body: JSON.stringify({
1129
+ model: "claude-3-5-sonnet-20241022",
1130
+ // TODO: make configurable
1131
+ messages: messages.filter(({ role }) => role !== "developer").map(({ role, content }) => ({ role, content })),
1132
+ system: (_a = messages.find(({ role }) => role === "developer")) == null ? void 0 : _a.content,
1133
+ max_tokens: 1024,
1134
+ stream: true
1135
+ }),
1136
+ signal
1137
+ });
1138
+ if (response.status !== 200 || !response.body)
1139
+ throw new Error("Failed to chat with Anthropic, unexpected status: " + response.status + await response.text());
1140
+ for await (const sseEvent of parseSSE(response.body)) {
1141
+ const event = JSON.parse(sseEvent.data);
1142
+ if (event.type === "content_block_delta")
1143
+ yield event.delta.text;
1144
+ }
1145
+ }
1146
+ }
1147
+ class LLMChat {
1148
+ constructor(api) {
1149
+ __publicField(this, "conversations", /* @__PURE__ */ new Map());
1150
+ this.api = api;
1151
+ }
1152
+ getConversation(id) {
1153
+ return this.conversations.get(id);
1154
+ }
1155
+ startConversation(id, systemPrompt) {
1156
+ const conversation = new Conversation(this, systemPrompt);
1157
+ this.conversations.set(id, conversation);
1158
+ return conversation;
1159
+ }
1160
+ }
1161
+ class Conversation {
1162
+ constructor(chat, systemPrompt) {
1163
+ __publicField(this, "history");
1164
+ __publicField(this, "onChange", new EventEmitter());
1165
+ __publicField(this, "_abortControllers", /* @__PURE__ */ new Set());
1166
+ this.chat = chat;
1167
+ this.history = [{ role: "developer", content: systemPrompt }];
1168
+ }
1169
+ async send(content, displayContent) {
1170
+ const response = { role: "assistant", content: "" };
1171
+ this.history.push({ role: "user", content, displayContent }, response);
1172
+ const abortController = new AbortController();
1173
+ this._abortControllers.add(abortController);
1174
+ this.onChange.fire();
1175
+ try {
1176
+ for await (const chunk of this.chat.api.chatCompletion(this.history, abortController.signal)) {
1177
+ response.content += chunk;
1178
+ this.onChange.fire();
1179
+ }
1180
+ } finally {
1181
+ this._abortControllers.delete(abortController);
1182
+ this.onChange.fire();
1183
+ }
1184
+ }
1185
+ isSending() {
1186
+ return this._abortControllers.size > 0;
1187
+ }
1188
+ abortSending() {
1189
+ for (const controller of this._abortControllers)
1190
+ controller.abort();
1191
+ this._abortControllers.clear();
1192
+ this.onChange.fire();
1193
+ }
1194
+ isEmpty() {
1195
+ return this.history.length < 2;
1196
+ }
1197
+ }
1198
+ const llmContext = reactExports.createContext(void 0);
1199
+ function LLMProvider({ children }) {
1200
+ const cookiePairs = useCookies();
1201
+ const chat = reactExports.useMemo(() => {
1202
+ const cookies = Object.fromEntries(cookiePairs);
1203
+ if (cookies.openai_api_key)
1204
+ return new LLMChat(new OpenAI(cookies.openai_api_key, cookies.openai_base_url));
1205
+ if (cookies.anthropic_api_key)
1206
+ return new LLMChat(new Anthropic(cookies.anthropic_api_key, cookies.anthropic_base_url));
1207
+ }, [cookiePairs]);
1208
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(llmContext.Provider, { value: chat, children });
1209
+ }
1210
+ function useLLMChat() {
1211
+ const chat = reactExports.useContext(llmContext);
1212
+ if (!chat)
1213
+ throw new Error("No LLM chat available, make sure theres a LLMProvider above");
1214
+ return chat;
1215
+ }
1216
+ function useIsLLMAvailable() {
1217
+ return !!reactExports.useContext(llmContext);
1218
+ }
1219
+ function useLLMConversation(id) {
1220
+ const conversation = useLLMChat().getConversation(id);
1221
+ if (!conversation)
1222
+ throw new Error("No conversation found for id: " + id);
1223
+ const [history, setHistory] = reactExports.useState(conversation.history);
1224
+ reactExports.useEffect(() => {
1225
+ function update() {
1226
+ setHistory([...conversation.history]);
1227
+ }
1228
+ update();
1229
+ const subscription = conversation.onChange.event(update);
1230
+ return subscription.dispose;
1231
+ }, [conversation]);
1232
+ return [history, conversation];
1233
+ }
1234
+ function AIConversation({ conversationId }) {
1235
+ const [history, conversation] = useLLMConversation(conversationId);
1236
+ const [input, setInput] = reactExports.useState("");
1237
+ const onSubmit = reactExports.useCallback(() => {
1238
+ setInput((content) => {
1239
+ conversation.send(content);
1240
+ return "";
1241
+ });
1242
+ }, [conversation]);
1243
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "chat-container", children: [
1244
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "chat-disclaimer", children: [
1245
+ "Chat based on ",
1246
+ conversation.chat.api.name,
1247
+ ". Check for mistakes."
1248
+ ] }),
1249
+ /* @__PURE__ */ jsxRuntimeExports.jsx("hr", {}),
1250
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "messages-container", children: history.filter(({ role }) => role !== "developer").map((message, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
1251
+ "div",
1252
+ {
1253
+ className: clsx("message", message.role === "user" && "user-message"),
1254
+ children: [
1255
+ message.role === "assistant" && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "message-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: "playwright-logo.svg" }) }),
1256
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "message-content", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Markdown, { options: { disableParsingRawHTML: true }, children: message.displayContent ?? message.content }) })
1257
+ ]
1258
+ },
1259
+ "" + index
1260
+ )) }),
1261
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "input-form", children: [
1262
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1263
+ "textarea",
1264
+ {
1265
+ name: "content",
1266
+ value: input,
1267
+ onChange: (e) => setInput(e.target.value),
1268
+ onKeyDown: (e) => {
1269
+ if (e.key === "Enter" && !e.shiftKey) {
1270
+ e.preventDefault();
1271
+ onSubmit();
1272
+ }
1273
+ },
1274
+ placeholder: "Ask a question...",
1275
+ className: "message-input"
1276
+ }
1277
+ ),
1278
+ conversation.isSending() ? /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "send-button", onClick: (evt) => {
1279
+ evt.preventDefault();
1280
+ conversation.abortSending();
1281
+ }, children: "Cancel" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "send-button", disabled: !input.trim(), onClick: onSubmit, children: "Send" })
1282
+ ] })
1283
+ ] });
1284
+ }
1285
+ async function loadImage(src) {
1286
+ const image = new Image();
1287
+ if (src) {
1288
+ image.src = src;
1289
+ await new Promise((f2, r2) => {
1290
+ image.onload = f2;
1291
+ image.onerror = f2;
1292
+ });
1293
+ }
1294
+ return image;
1295
+ }
1296
+ const checkerboardStyle = {
1297
+ backgroundImage: `linear-gradient(45deg, #80808020 25%, transparent 25%),
1298
+ linear-gradient(-45deg, #80808020 25%, transparent 25%),
1299
+ linear-gradient(45deg, transparent 75%, #80808020 75%),
1300
+ linear-gradient(-45deg, transparent 75%, #80808020 75%)`,
1301
+ backgroundSize: "20px 20px",
1302
+ backgroundPosition: "0 0, 0 10px, 10px -10px, -10px 0px",
1303
+ boxShadow: `rgb(0 0 0 / 10%) 0px 1.8px 1.9px,
1304
+ rgb(0 0 0 / 15%) 0px 6.1px 6.3px,
1305
+ rgb(0 0 0 / 10%) 0px -2px 4px,
1306
+ rgb(0 0 0 / 15%) 0px -6.1px 12px,
1307
+ rgb(0 0 0 / 25%) 0px 6px 12px`
1308
+ };
1309
+ const ImageDiffView = ({ diff, noTargetBlank, hideDetails }) => {
1310
+ const [mode, setMode] = reactExports.useState(diff.diff ? "diff" : "actual");
1311
+ const [showSxsDiff, setShowSxsDiff] = reactExports.useState(false);
1312
+ const [expectedImage, setExpectedImage] = reactExports.useState(null);
1313
+ const [expectedImageTitle, setExpectedImageTitle] = reactExports.useState("Expected");
1314
+ const [actualImage, setActualImage] = reactExports.useState(null);
1315
+ const [diffImage, setDiffImage] = reactExports.useState(null);
1316
+ const [measure, ref] = useMeasure();
1317
+ reactExports.useEffect(() => {
1318
+ (async () => {
1319
+ var _a, _b, _c, _d;
1320
+ setExpectedImage(await loadImage((_a = diff.expected) == null ? void 0 : _a.attachment.path));
1321
+ setExpectedImageTitle(((_b = diff.expected) == null ? void 0 : _b.title) || "Expected");
1322
+ setActualImage(await loadImage((_c = diff.actual) == null ? void 0 : _c.attachment.path));
1323
+ setDiffImage(await loadImage((_d = diff.diff) == null ? void 0 : _d.attachment.path));
1324
+ })();
1325
+ }, [diff]);
1326
+ const isLoaded = expectedImage && actualImage && diffImage;
1327
+ const imageWidth = isLoaded ? Math.max(expectedImage.naturalWidth, actualImage.naturalWidth, 200) : 500;
1328
+ const imageHeight = isLoaded ? Math.max(expectedImage.naturalHeight, actualImage.naturalHeight, 200) : 500;
1329
+ const scale = Math.min(1, (measure.width - 30) / imageWidth);
1330
+ const sxsScale = Math.min(1, (measure.width - 50) / imageWidth / 2);
1331
+ const fitWidth = imageWidth * scale;
1332
+ const fitHeight = imageHeight * scale;
1333
+ const modeStyle = {
1334
+ flex: "none",
1335
+ margin: "0 10px",
1336
+ cursor: "pointer",
1337
+ userSelect: "none"
1338
+ };
1339
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-testid": "test-result-image-mismatch", style: { display: "flex", flexDirection: "column", alignItems: "center", flex: "auto" }, ref, children: isLoaded && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1340
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "data-testid": "test-result-image-mismatch-tabs", style: { display: "flex", margin: "10px 0 20px" }, children: [
1341
+ diff.diff && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "diff" ? 600 : "initial" }, onClick: () => setMode("diff"), children: "Diff" }),
1342
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "actual" ? 600 : "initial" }, onClick: () => setMode("actual"), children: "Actual" }),
1343
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "expected" ? 600 : "initial" }, onClick: () => setMode("expected"), children: expectedImageTitle }),
1344
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "sxs" ? 600 : "initial" }, onClick: () => setMode("sxs"), children: "Side by side" }),
1345
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...modeStyle, fontWeight: mode === "slider" ? 600 : "initial" }, onClick: () => setMode("slider"), children: "Slider" })
1346
+ ] }),
1347
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", justifyContent: "center", flex: "auto", minHeight: fitHeight + 60 }, children: [
1348
+ diff.diff && mode === "diff" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: diffImage, alt: "Diff", hideSize: hideDetails, canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
1349
+ diff.diff && mode === "actual" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: actualImage, alt: "Actual", hideSize: hideDetails, canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
1350
+ diff.diff && mode === "expected" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: expectedImage, alt: expectedImageTitle, hideSize: hideDetails, canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
1351
+ diff.diff && mode === "slider" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageDiffSlider, { expectedImage, actualImage, hideSize: hideDetails, canvasWidth: fitWidth, canvasHeight: fitHeight, scale, expectedTitle: expectedImageTitle }),
1352
+ diff.diff && mode === "sxs" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex" }, children: [
1353
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: expectedImage, title: expectedImageTitle, hideSize: hideDetails, canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale }),
1354
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: showSxsDiff ? diffImage : actualImage, title: showSxsDiff ? "Diff" : "Actual", onClick: () => setShowSxsDiff(!showSxsDiff), hideSize: hideDetails, canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale })
1355
+ ] }),
1356
+ !diff.diff && mode === "actual" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: actualImage, title: "Actual", hideSize: hideDetails, canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
1357
+ !diff.diff && mode === "expected" && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: expectedImage, title: expectedImageTitle, hideSize: hideDetails, canvasWidth: fitWidth, canvasHeight: fitHeight, scale }),
1358
+ !diff.diff && mode === "sxs" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex" }, children: [
1359
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: expectedImage, title: expectedImageTitle, canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale }),
1360
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ImageWithSize, { image: actualImage, title: "Actual", canvasWidth: sxsScale * imageWidth, canvasHeight: sxsScale * imageHeight, scale: sxsScale })
1361
+ ] })
1362
+ ] }),
1363
+ !hideDetails && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { alignSelf: "start", lineHeight: "18px", marginLeft: "15px" }, children: [
1364
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: diff.diff && /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: "_blank", href: diff.diff.attachment.path, rel: "noreferrer", children: diff.diff.attachment.name }) }),
1365
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: noTargetBlank ? "" : "_blank", href: diff.actual.attachment.path, rel: "noreferrer", children: diff.actual.attachment.name }) }),
1366
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: noTargetBlank ? "" : "_blank", href: diff.expected.attachment.path, rel: "noreferrer", children: diff.expected.attachment.name }) })
1367
+ ] })
1368
+ ] }) });
1369
+ };
1370
+ const ImageDiffSlider = ({ expectedImage, actualImage, canvasWidth, canvasHeight, scale, expectedTitle, hideSize }) => {
1371
+ const absoluteStyle = {
1372
+ position: "absolute",
1373
+ top: 0,
1374
+ left: 0
1375
+ };
1376
+ const [slider, setSlider] = reactExports.useState(canvasWidth / 2);
1377
+ const sameSize = expectedImage.naturalWidth === actualImage.naturalWidth && expectedImage.naturalHeight === actualImage.naturalHeight;
1378
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: "none", display: "flex", alignItems: "center", flexDirection: "column", userSelect: "none" }, children: [
1379
+ !hideSize && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { margin: 5 }, children: [
1380
+ !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: "Expected " }),
1381
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: expectedImage.naturalWidth }),
1382
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: "x" }),
1383
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: expectedImage.naturalHeight }),
1384
+ !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px 0 15px" }, children: "Actual " }),
1385
+ !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: actualImage.naturalWidth }),
1386
+ !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: "x" }),
1387
+ !sameSize && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: actualImage.naturalHeight })
1388
+ ] }),
1389
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { position: "relative", width: canvasWidth, height: canvasHeight, margin: 15, ...checkerboardStyle }, children: [
1390
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1391
+ ResizeView,
1392
+ {
1393
+ orientation: "horizontal",
1394
+ offsets: [slider],
1395
+ setOffsets: (offsets) => setSlider(offsets[0]),
1396
+ resizerColor: "#57606a80",
1397
+ resizerWidth: 6
1398
+ }
1399
+ ),
1400
+ /* @__PURE__ */ jsxRuntimeExports.jsx("img", { alt: expectedTitle, style: {
1401
+ width: expectedImage.naturalWidth * scale,
1402
+ height: expectedImage.naturalHeight * scale
1403
+ }, draggable: "false", src: expectedImage.src }),
1404
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { ...absoluteStyle, bottom: 0, overflow: "hidden", width: slider, ...checkerboardStyle }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { alt: "Actual", style: {
1405
+ width: actualImage.naturalWidth * scale,
1406
+ height: actualImage.naturalHeight * scale
1407
+ }, draggable: "false", src: actualImage.src }) })
1408
+ ] })
1409
+ ] });
1410
+ };
1411
+ const ImageWithSize = ({ image, title, alt, hideSize, canvasWidth, canvasHeight, scale, onClick }) => {
1412
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: "none", display: "flex", alignItems: "center", flexDirection: "column" }, children: [
1413
+ !hideSize && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { margin: 5 }, children: [
1414
+ title && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: title }),
1415
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: image.naturalWidth }),
1416
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { flex: "none", margin: "0 5px" }, children: "x" }),
1417
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: image.naturalHeight })
1418
+ ] }),
1419
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { display: "flex", flex: "none", width: canvasWidth, height: canvasHeight, margin: 15, ...checkerboardStyle }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1420
+ "img",
1421
+ {
1422
+ width: image.naturalWidth * scale,
1423
+ height: image.naturalHeight * scale,
1424
+ alt: title || alt,
1425
+ style: { cursor: onClick ? "pointer" : "initial" },
1426
+ draggable: "false",
1427
+ src: image.src,
1428
+ onClick
1429
+ }
1430
+ ) })
1431
+ ] });
1432
+ };
1433
+ function isTextualMimeType(mimeType) {
1434
+ return !!mimeType.match(/^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$/);
1435
+ }
1436
+ const Expandable = ({ title, children, setExpanded, expanded, expandOnTitleClick }) => {
1437
+ const id = reactExports.useId();
1438
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: clsx("expandable", expanded && "expanded"), children: [
1439
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
1440
+ "div",
1441
+ {
1442
+ role: "button",
1443
+ "aria-expanded": expanded,
1444
+ "aria-controls": id,
1445
+ className: "expandable-title",
1446
+ onClick: () => expandOnTitleClick && setExpanded(!expanded),
1447
+ children: [
1448
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1449
+ "div",
1450
+ {
1451
+ className: clsx("codicon", expanded ? "codicon-chevron-down" : "codicon-chevron-right"),
1452
+ style: { cursor: "pointer", color: "var(--vscode-foreground)", marginLeft: "5px" },
1453
+ onClick: () => !expandOnTitleClick && setExpanded(!expanded)
1454
+ }
1455
+ ),
1456
+ title
1457
+ ]
1458
+ }
1459
+ ),
1460
+ expanded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { id, role: "region", style: { marginLeft: 25 }, children })
1461
+ ] });
1462
+ };
1463
+ function linkifyText(description) {
1464
+ const result = [];
1465
+ let currentIndex = 0;
1466
+ let match;
1467
+ while ((match = kWebLinkRe.exec(description)) !== null) {
1468
+ const stringBeforeMatch = description.substring(currentIndex, match.index);
1469
+ if (stringBeforeMatch)
1470
+ result.push(stringBeforeMatch);
1471
+ const value = match[0];
1472
+ result.push(renderLink(value));
1473
+ currentIndex = match.index + value.length;
1474
+ }
1475
+ const stringAfterMatches = description.substring(currentIndex);
1476
+ if (stringAfterMatches)
1477
+ result.push(stringAfterMatches);
1478
+ return result;
1479
+ }
1480
+ function renderLink(text) {
1481
+ let link = text;
1482
+ if (link.startsWith("www."))
1483
+ link = "https://" + link;
1484
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: link, target: "_blank", rel: "noopener noreferrer", children: text });
1485
+ }
1486
+ const ExpandableAttachment = ({ attachment, reveal }) => {
1487
+ const [expanded, setExpanded] = reactExports.useState(false);
1488
+ const [attachmentText, setAttachmentText] = reactExports.useState(null);
1489
+ const [placeholder, setPlaceholder] = reactExports.useState(null);
1490
+ const [flash, triggerFlash] = useFlash();
1491
+ const ref = reactExports.useRef(null);
1492
+ const isTextAttachment = isTextualMimeType(attachment.contentType);
1493
+ const hasContent = !!attachment.sha1 || !!attachment.path;
1494
+ reactExports.useEffect(() => {
1495
+ var _a;
1496
+ if (reveal) {
1497
+ (_a = ref.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
1498
+ return triggerFlash();
1499
+ }
1500
+ }, [reveal, triggerFlash]);
1501
+ reactExports.useEffect(() => {
1502
+ if (expanded && attachmentText === null && placeholder === null) {
1503
+ setPlaceholder("Loading ...");
1504
+ fetch(attachmentURL(attachment)).then((response) => response.text()).then((text) => {
1505
+ setAttachmentText(text);
1506
+ setPlaceholder(null);
1507
+ }).catch((e) => {
1508
+ setPlaceholder("Failed to load: " + e.message);
1509
+ });
1510
+ }
1511
+ }, [expanded, attachmentText, placeholder, attachment]);
1512
+ const snippetHeight = reactExports.useMemo(() => {
1513
+ const lineCount = attachmentText ? attachmentText.split("\n").length : 0;
1514
+ return Math.min(Math.max(5, lineCount), 20) * lineHeight;
1515
+ }, [attachmentText]);
1516
+ const title = /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { marginLeft: 5 }, ref, "aria-label": attachment.name, children: [
1517
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: linkifyText(attachment.name) }),
1518
+ hasContent && /* @__PURE__ */ jsxRuntimeExports.jsx("a", { style: { marginLeft: 5 }, href: downloadURL(attachment), children: "download" })
1519
+ ] });
1520
+ if (!isTextAttachment || !hasContent)
1521
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginLeft: 20 }, children: title });
1522
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: clsx(flash && "yellow-flash"), children: [
1523
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Expandable, { title, expanded, setExpanded, expandOnTitleClick: true, children: placeholder && /* @__PURE__ */ jsxRuntimeExports.jsx("i", { children: placeholder }) }),
1524
+ expanded && attachmentText !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "vbox", style: { height: snippetHeight }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1525
+ CodeMirrorWrapper,
1526
+ {
1527
+ text: attachmentText,
1528
+ readOnly: true,
1529
+ mimeType: attachment.contentType,
1530
+ linkify: true,
1531
+ lineNumbers: true,
1532
+ wrapLines: false
1533
+ }
1534
+ ) })
1535
+ ] });
1536
+ };
1537
+ const AttachmentsTab = ({ model, revealedAttachment }) => {
1538
+ const { diffMap, screenshots, attachments } = reactExports.useMemo(() => {
1539
+ const attachments2 = new Set((model == null ? void 0 : model.visibleAttachments) ?? []);
1540
+ const screenshots2 = /* @__PURE__ */ new Set();
1541
+ const diffMap2 = /* @__PURE__ */ new Map();
1542
+ for (const attachment of attachments2) {
1543
+ if (!attachment.path && !attachment.sha1)
1544
+ continue;
1545
+ const match = attachment.name.match(/^(.*)-(expected|actual|diff)\.png$/);
1546
+ if (match) {
1547
+ const name = match[1];
1548
+ const type = match[2];
1549
+ const entry = diffMap2.get(name) || { expected: void 0, actual: void 0, diff: void 0 };
1550
+ entry[type] = attachment;
1551
+ diffMap2.set(name, entry);
1552
+ attachments2.delete(attachment);
1553
+ } else if (attachment.contentType.startsWith("image/")) {
1554
+ screenshots2.add(attachment);
1555
+ attachments2.delete(attachment);
1556
+ }
1557
+ }
1558
+ return { diffMap: diffMap2, attachments: attachments2, screenshots: screenshots2 };
1559
+ }, [model]);
1560
+ if (!diffMap.size && !screenshots.size && !attachments.size)
1561
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No attachments" });
1562
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "attachments-tab", children: [
1563
+ [...diffMap.values()].map(({ expected, actual, diff }) => {
1564
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1565
+ expected && actual && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachments-section", children: "Image diff" }),
1566
+ expected && actual && /* @__PURE__ */ jsxRuntimeExports.jsx(ImageDiffView, { noTargetBlank: true, diff: {
1567
+ name: "Image diff",
1568
+ expected: { attachment: { ...expected, path: downloadURL(expected) }, title: "Expected" },
1569
+ actual: { attachment: { ...actual, path: downloadURL(actual) } },
1570
+ diff: diff ? { attachment: { ...diff, path: downloadURL(diff) } } : void 0
1571
+ } })
1572
+ ] });
1573
+ }),
1574
+ screenshots.size ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachments-section", children: "Screenshots" }) : void 0,
1575
+ [...screenshots.values()].map((a2, i2) => {
1576
+ const url = attachmentURL(a2);
1577
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "attachment-item", children: [
1578
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { draggable: "false", src: url }) }),
1579
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { target: "_blank", href: url, rel: "noreferrer", children: a2.name }) })
1580
+ ] }, `screenshot-${i2}`);
1581
+ }),
1582
+ attachments.size ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachments-section", children: "Attachments" }) : void 0,
1583
+ [...attachments.values()].map((a2, i2) => {
1584
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "attachment-item", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1585
+ ExpandableAttachment,
1586
+ {
1587
+ attachment: a2,
1588
+ reveal: !!revealedAttachment && isEqualAttachment(a2, revealedAttachment[0]) ? revealedAttachment : void 0
1589
+ }
1590
+ ) }, attachmentKey(a2, i2));
1591
+ })
1592
+ ] });
1593
+ };
1594
+ function isEqualAttachment(a2, b2) {
1595
+ return a2.name === b2.name && a2.path === b2.path && a2.sha1 === b2.sha1;
1596
+ }
1597
+ function attachmentURL(attachment, queryParams = {}) {
1598
+ const params = new URLSearchParams(queryParams);
1599
+ if (attachment.sha1) {
1600
+ params.set("trace", attachment.traceUrl);
1601
+ return "sha1/" + attachment.sha1 + "?" + params.toString();
1602
+ }
1603
+ params.set("path", attachment.path);
1604
+ return "file?" + params.toString();
1605
+ }
1606
+ function downloadURL(attachment) {
1607
+ const params = { dn: attachment.name };
1608
+ if (attachment.contentType)
1609
+ params.dct = attachment.contentType;
1610
+ return attachmentURL(attachment, params);
1611
+ }
1612
+ function attachmentKey(attachment, index) {
1613
+ return index + "-" + (attachment.sha1 ? `sha1-` + attachment.sha1 : `path-` + attachment.path);
1614
+ }
1615
+ const CopyPromptButton = ({ prompt }) => {
1616
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
1617
+ CopyToClipboardTextButton,
1618
+ {
1619
+ value: prompt,
1620
+ description: "Copy prompt",
1621
+ copiedDescription: /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1622
+ "Copied ",
1623
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "codicon codicon-copy", style: { marginLeft: "5px" } })
1624
+ ] }),
1625
+ style: { width: "120px", justifyContent: "center" }
1626
+ }
1627
+ );
1628
+ };
1629
+ function useErrorsTabModel(model) {
1630
+ return reactExports.useMemo(() => {
1631
+ if (!model)
1632
+ return { errors: /* @__PURE__ */ new Map() };
1633
+ const errors = /* @__PURE__ */ new Map();
1634
+ for (const error of model.errorDescriptors)
1635
+ errors.set(error.message, error);
1636
+ return { errors };
1637
+ }, [model]);
1638
+ }
1639
+ function Error$1({ message, error, errorId, sdkLanguage, revealInSource }) {
1640
+ var _a;
1641
+ const [showLLM, setShowLLM] = reactExports.useState(false);
1642
+ const llmAvailable = useIsLLMAvailable();
1643
+ let location;
1644
+ let longLocation;
1645
+ const stackFrame = (_a = error.stack) == null ? void 0 : _a[0];
1646
+ if (stackFrame) {
1647
+ const file = stackFrame.file.replace(/.*[/\\](.*)/, "$1");
1648
+ location = file + ":" + stackFrame.line;
1649
+ longLocation = stackFrame.file + ":" + stackFrame.line;
1650
+ }
1651
+ const prompt = useAsyncMemo(async () => {
1652
+ if (!error.prompt)
1653
+ return;
1654
+ const response = await fetch(attachmentURL(error.prompt));
1655
+ return await response.text();
1656
+ }, [error], void 0);
1657
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", flexDirection: "column", overflowX: "clip" }, children: [
1658
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "hbox", style: {
1659
+ alignItems: "center",
1660
+ padding: "5px 10px",
1661
+ minHeight: 36,
1662
+ fontWeight: "bold",
1663
+ color: "var(--vscode-errorForeground)",
1664
+ flex: 0
1665
+ }, children: [
1666
+ error.action && renderAction(error.action, { sdkLanguage }),
1667
+ location && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "action-location", children: [
1668
+ "@ ",
1669
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { title: longLocation, onClick: () => revealInSource(error), children: location })
1670
+ ] }),
1671
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { position: "absolute", right: "5px" }, children: prompt && (llmAvailable ? /* @__PURE__ */ jsxRuntimeExports.jsx(FixWithAIButton, { conversationId: errorId, onChange: setShowLLM, value: showLLM, prompt }) : /* @__PURE__ */ jsxRuntimeExports.jsx(CopyPromptButton, { prompt })) })
1672
+ ] }),
1673
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorMessage, { error: message }),
1674
+ showLLM && /* @__PURE__ */ jsxRuntimeExports.jsx(AIConversation, { conversationId: errorId })
1675
+ ] });
1676
+ }
1677
+ function FixWithAIButton({ conversationId, value, onChange, prompt }) {
1678
+ const chat = useLLMChat();
1679
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
1680
+ ToolbarButton,
1681
+ {
1682
+ onClick: () => {
1683
+ if (!chat.getConversation(conversationId)) {
1684
+ const conversation = chat.startConversation(conversationId, [
1685
+ `My Playwright test failed. What's going wrong?`,
1686
+ `Please give me a suggestion how to fix it, and then explain what went wrong. Be very concise and apply Playwright best practices.`,
1687
+ `Don't include many headings in your output. Make sure what you're saying is correct, and take into account whether there might be a bug in the app.`
1688
+ ].join("\n"));
1689
+ let displayPrompt = `Help me with the error above.`;
1690
+ const hasDiff = prompt.includes("Local changes:");
1691
+ const hasSnapshot = prompt.includes("Page snapshot:");
1692
+ if (hasDiff)
1693
+ displayPrompt += ` Take the code diff${hasSnapshot ? " and page snapshot" : ""} into account.`;
1694
+ else if (hasSnapshot)
1695
+ displayPrompt += ` Take the page snapshot into account.`;
1696
+ conversation.send(prompt, displayPrompt);
1697
+ }
1698
+ onChange((v2) => !v2);
1699
+ },
1700
+ style: { width: "96px", justifyContent: "center" },
1701
+ title: "Fix with AI",
1702
+ className: "copy-to-clipboard-text-button",
1703
+ children: value ? "Hide AI" : "Fix with AI"
1704
+ }
1705
+ );
1706
+ }
1707
+ const ErrorsTab = ({ errorsModel, sdkLanguage, revealInSource, wallTime }) => {
1708
+ if (!errorsModel.errors.size)
1709
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No errors" });
1710
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fill", style: { overflow: "auto" }, children: [...errorsModel.errors.entries()].map(([message, error]) => {
1711
+ const errorId = `error-${wallTime}-${message}`;
1712
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Error$1, { errorId, message, error, revealInSource, sdkLanguage }, errorId);
1713
+ }) });
1714
+ };
1715
+ const tileSize = { width: 200, height: 45 };
1716
+ const frameMargin = 2.5;
1717
+ const rowHeight = tileSize.height + frameMargin * 2;
1718
+ const FilmStrip = ({ model, boundaries, previewPoint }) => {
1719
+ var _a, _b;
1720
+ const [measure, ref] = useMeasure();
1721
+ const lanesRef = reactExports.useRef(null);
1722
+ let pageIndex = 0;
1723
+ if (lanesRef.current && previewPoint) {
1724
+ const bounds = lanesRef.current.getBoundingClientRect();
1725
+ pageIndex = (previewPoint.clientY - bounds.top + lanesRef.current.scrollTop) / rowHeight | 0;
1726
+ }
1727
+ const screencastFrames = (_b = (_a = model == null ? void 0 : model.pages) == null ? void 0 : _a[pageIndex]) == null ? void 0 : _b.screencastFrames;
1728
+ let previewImage = void 0;
1729
+ let previewSize = void 0;
1730
+ if (previewPoint !== void 0 && screencastFrames && screencastFrames.length) {
1731
+ const previewTime = boundaries.minimum + (boundaries.maximum - boundaries.minimum) * previewPoint.x / measure.width;
1732
+ previewImage = screencastFrames[upperBound(screencastFrames, previewTime, timeComparator) - 1];
1733
+ const fitInto = {
1734
+ width: Math.min(800, window.innerWidth / 2 | 0),
1735
+ height: Math.min(800, window.innerHeight / 2 | 0)
1736
+ };
1737
+ previewSize = previewImage ? inscribe({ width: previewImage.width, height: previewImage.height }, fitInto) : void 0;
1738
+ }
1739
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "film-strip", ref, children: [
1740
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-lanes", ref: lanesRef, children: model == null ? void 0 : model.pages.map((page, index) => page.screencastFrames.length ? /* @__PURE__ */ jsxRuntimeExports.jsx(
1741
+ FilmStripLane,
1742
+ {
1743
+ boundaries,
1744
+ page,
1745
+ width: measure.width
1746
+ },
1747
+ index
1748
+ ) : null) }),
1749
+ (previewPoint == null ? void 0 : previewPoint.x) !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "film-strip-hover", style: {
1750
+ top: measure.bottom + 5,
1751
+ left: Math.min(previewPoint.x, measure.width - (previewSize ? previewSize.width : 0) - 10)
1752
+ }, children: [
1753
+ previewPoint.action && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-hover-title", children: renderAction(previewPoint.action, previewPoint) }),
1754
+ previewImage && previewSize && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { width: previewSize.width, height: previewSize.height }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: `sha1/${previewImage.sha1}`, width: previewSize.width, height: previewSize.height }) })
1755
+ ] })
1756
+ ] });
1757
+ };
1758
+ const FilmStripLane = ({ boundaries, page, width }) => {
1759
+ const viewportSize = { width: 0, height: 0 };
1760
+ const screencastFrames = page.screencastFrames;
1761
+ for (const frame of screencastFrames) {
1762
+ viewportSize.width = Math.max(viewportSize.width, frame.width);
1763
+ viewportSize.height = Math.max(viewportSize.height, frame.height);
1764
+ }
1765
+ const frameSize = inscribe(viewportSize, tileSize);
1766
+ const startTime = screencastFrames[0].timestamp;
1767
+ const endTime = screencastFrames[screencastFrames.length - 1].timestamp;
1768
+ const boundariesDuration = boundaries.maximum - boundaries.minimum;
1769
+ const gapLeft = (startTime - boundaries.minimum) / boundariesDuration * width;
1770
+ const gapRight = (boundaries.maximum - endTime) / boundariesDuration * width;
1771
+ const effectiveWidth = (endTime - startTime) / boundariesDuration * width;
1772
+ const frameCount = effectiveWidth / (frameSize.width + 2 * frameMargin) | 0;
1773
+ const frameDuration = (endTime - startTime) / frameCount;
1774
+ const frames = [];
1775
+ for (let i2 = 0; startTime && frameDuration && i2 < frameCount; ++i2) {
1776
+ const time = startTime + frameDuration * i2;
1777
+ const index = upperBound(screencastFrames, time, timeComparator) - 1;
1778
+ frames.push(/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-frame", style: {
1779
+ width: frameSize.width,
1780
+ height: frameSize.height,
1781
+ backgroundImage: `url(sha1/${screencastFrames[index].sha1})`,
1782
+ backgroundSize: `${frameSize.width}px ${frameSize.height}px`,
1783
+ margin: frameMargin,
1784
+ marginRight: frameMargin
1785
+ } }, i2));
1786
+ }
1787
+ frames.push(/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-frame", style: {
1788
+ width: frameSize.width,
1789
+ height: frameSize.height,
1790
+ backgroundImage: `url(sha1/${screencastFrames[screencastFrames.length - 1].sha1})`,
1791
+ backgroundSize: `${frameSize.width}px ${frameSize.height}px`,
1792
+ margin: frameMargin,
1793
+ marginRight: frameMargin
1794
+ } }, frames.length));
1795
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "film-strip-lane", style: {
1796
+ marginLeft: gapLeft + "px",
1797
+ marginRight: gapRight + "px"
1798
+ }, children: frames });
1799
+ };
1800
+ function timeComparator(time, frame) {
1801
+ return time - frame.timestamp;
1802
+ }
1803
+ function inscribe(object, area) {
1804
+ const scale = Math.max(object.width / area.width, object.height / area.height);
1805
+ return {
1806
+ width: object.width / scale | 0,
1807
+ height: object.height / scale | 0
1808
+ };
1809
+ }
1810
+ const Timeline = ({ model, boundaries, consoleEntries, onSelected, highlightedAction, highlightedEntry, highlightedConsoleEntry, selectedTime, setSelectedTime, sdkLanguage }) => {
1811
+ const [measure, ref] = useMeasure();
1812
+ const [dragWindow, setDragWindow] = reactExports.useState();
1813
+ const [previewPoint, setPreviewPoint] = reactExports.useState();
1814
+ const { offsets, curtainLeft, curtainRight } = reactExports.useMemo(() => {
1815
+ let activeWindow = selectedTime || boundaries;
1816
+ if (dragWindow && dragWindow.startX !== dragWindow.endX) {
1817
+ const time1 = positionToTime(measure.width, boundaries, dragWindow.startX);
1818
+ const time2 = positionToTime(measure.width, boundaries, dragWindow.endX);
1819
+ activeWindow = { minimum: Math.min(time1, time2), maximum: Math.max(time1, time2) };
1820
+ }
1821
+ const curtainLeft2 = timeToPosition(measure.width, boundaries, activeWindow.minimum);
1822
+ const maxRight = timeToPosition(measure.width, boundaries, boundaries.maximum);
1823
+ const curtainRight2 = maxRight - timeToPosition(measure.width, boundaries, activeWindow.maximum);
1824
+ return { offsets: calculateDividerOffsets(measure.width, boundaries), curtainLeft: curtainLeft2, curtainRight: curtainRight2 };
1825
+ }, [selectedTime, boundaries, dragWindow, measure]);
1826
+ const bars = reactExports.useMemo(() => {
1827
+ const bars2 = [];
1828
+ for (const entry of (model == null ? void 0 : model.actions) || []) {
1829
+ if (entry.class === "Test")
1830
+ continue;
1831
+ bars2.push({
1832
+ action: entry,
1833
+ leftTime: entry.startTime,
1834
+ rightTime: entry.endTime || boundaries.maximum,
1835
+ leftPosition: timeToPosition(measure.width, boundaries, entry.startTime),
1836
+ rightPosition: timeToPosition(measure.width, boundaries, entry.endTime || boundaries.maximum),
1837
+ active: false,
1838
+ error: !!entry.error
1839
+ });
1840
+ }
1841
+ for (const resource of (model == null ? void 0 : model.resources) || []) {
1842
+ const startTime = resource._monotonicTime;
1843
+ const endTime = resource._monotonicTime + resource.time;
1844
+ bars2.push({
1845
+ resource,
1846
+ leftTime: startTime,
1847
+ rightTime: endTime,
1848
+ leftPosition: timeToPosition(measure.width, boundaries, startTime),
1849
+ rightPosition: timeToPosition(measure.width, boundaries, endTime),
1850
+ active: false,
1851
+ error: false
1852
+ });
1853
+ }
1854
+ for (const consoleMessage of consoleEntries || []) {
1855
+ bars2.push({
1856
+ consoleMessage,
1857
+ leftTime: consoleMessage.timestamp,
1858
+ rightTime: consoleMessage.timestamp,
1859
+ leftPosition: timeToPosition(measure.width, boundaries, consoleMessage.timestamp),
1860
+ rightPosition: timeToPosition(measure.width, boundaries, consoleMessage.timestamp),
1861
+ active: false,
1862
+ error: consoleMessage.isError
1863
+ });
1864
+ }
1865
+ return bars2;
1866
+ }, [model, consoleEntries, boundaries, measure]);
1867
+ reactExports.useMemo(() => {
1868
+ for (const bar of bars) {
1869
+ if (highlightedAction)
1870
+ bar.active = bar.action === highlightedAction;
1871
+ else if (highlightedEntry)
1872
+ bar.active = bar.resource === highlightedEntry;
1873
+ else if (highlightedConsoleEntry)
1874
+ bar.active = bar.consoleMessage === highlightedConsoleEntry;
1875
+ else
1876
+ bar.active = false;
1877
+ }
1878
+ }, [bars, highlightedAction, highlightedEntry, highlightedConsoleEntry]);
1879
+ const onMouseDown = reactExports.useCallback((event) => {
1880
+ setPreviewPoint(void 0);
1881
+ if (!ref.current)
1882
+ return;
1883
+ const x2 = event.clientX - ref.current.getBoundingClientRect().left;
1884
+ const time = positionToTime(measure.width, boundaries, x2);
1885
+ const leftX = selectedTime ? timeToPosition(measure.width, boundaries, selectedTime.minimum) : 0;
1886
+ const rightX = selectedTime ? timeToPosition(measure.width, boundaries, selectedTime.maximum) : 0;
1887
+ if (selectedTime && Math.abs(x2 - leftX) < 10) {
1888
+ setDragWindow({ startX: rightX, endX: x2, type: "resize" });
1889
+ } else if (selectedTime && Math.abs(x2 - rightX) < 10) {
1890
+ setDragWindow({ startX: leftX, endX: x2, type: "resize" });
1891
+ } else if (selectedTime && time > selectedTime.minimum && time < selectedTime.maximum && event.clientY - ref.current.getBoundingClientRect().top < 20) {
1892
+ setDragWindow({ startX: leftX, endX: rightX, pivot: x2, type: "move" });
1893
+ } else {
1894
+ setDragWindow({ startX: x2, endX: x2, type: "resize" });
1895
+ }
1896
+ }, [boundaries, measure, ref, selectedTime]);
1897
+ const onGlassPaneMouseMove = reactExports.useCallback((event) => {
1898
+ if (!ref.current)
1899
+ return;
1900
+ const x2 = event.clientX - ref.current.getBoundingClientRect().left;
1901
+ const time = positionToTime(measure.width, boundaries, x2);
1902
+ const action = model == null ? void 0 : model.actions.findLast((action2) => action2.startTime <= time);
1903
+ if (!event.buttons) {
1904
+ setDragWindow(void 0);
1905
+ return;
1906
+ }
1907
+ if (action)
1908
+ onSelected(action);
1909
+ if (!dragWindow)
1910
+ return;
1911
+ let newDragWindow = dragWindow;
1912
+ if (dragWindow.type === "resize") {
1913
+ newDragWindow = { ...dragWindow, endX: x2 };
1914
+ } else {
1915
+ const delta = x2 - dragWindow.pivot;
1916
+ let startX = dragWindow.startX + delta;
1917
+ let endX = dragWindow.endX + delta;
1918
+ if (startX < 0) {
1919
+ startX = 0;
1920
+ endX = startX + (dragWindow.endX - dragWindow.startX);
1921
+ }
1922
+ if (endX > measure.width) {
1923
+ endX = measure.width;
1924
+ startX = endX - (dragWindow.endX - dragWindow.startX);
1925
+ }
1926
+ newDragWindow = { ...dragWindow, startX, endX, pivot: x2 };
1927
+ }
1928
+ setDragWindow(newDragWindow);
1929
+ const time1 = positionToTime(measure.width, boundaries, newDragWindow.startX);
1930
+ const time2 = positionToTime(measure.width, boundaries, newDragWindow.endX);
1931
+ if (time1 !== time2)
1932
+ setSelectedTime({ minimum: Math.min(time1, time2), maximum: Math.max(time1, time2) });
1933
+ }, [boundaries, dragWindow, measure, model, onSelected, ref, setSelectedTime]);
1934
+ const onGlassPaneMouseUp = reactExports.useCallback(() => {
1935
+ setPreviewPoint(void 0);
1936
+ if (!dragWindow)
1937
+ return;
1938
+ if (dragWindow.startX !== dragWindow.endX) {
1939
+ const time1 = positionToTime(measure.width, boundaries, dragWindow.startX);
1940
+ const time2 = positionToTime(measure.width, boundaries, dragWindow.endX);
1941
+ setSelectedTime({ minimum: Math.min(time1, time2), maximum: Math.max(time1, time2) });
1942
+ } else {
1943
+ const time = positionToTime(measure.width, boundaries, dragWindow.startX);
1944
+ const action = model == null ? void 0 : model.actions.findLast((action2) => action2.startTime <= time);
1945
+ if (action)
1946
+ onSelected(action);
1947
+ setSelectedTime(void 0);
1948
+ }
1949
+ setDragWindow(void 0);
1950
+ }, [boundaries, dragWindow, measure, model, setSelectedTime, onSelected]);
1951
+ const onMouseMove = reactExports.useCallback((event) => {
1952
+ if (!ref.current)
1953
+ return;
1954
+ const x2 = event.clientX - ref.current.getBoundingClientRect().left;
1955
+ const time = positionToTime(measure.width, boundaries, x2);
1956
+ const action = model == null ? void 0 : model.actions.findLast((action2) => action2.startTime <= time);
1957
+ setPreviewPoint({ x: x2, clientY: event.clientY, action, sdkLanguage });
1958
+ }, [boundaries, measure, model, ref, sdkLanguage]);
1959
+ const onMouseLeave = reactExports.useCallback(() => {
1960
+ setPreviewPoint(void 0);
1961
+ }, []);
1962
+ const onPaneDoubleClick = reactExports.useCallback(() => {
1963
+ setSelectedTime(void 0);
1964
+ }, [setSelectedTime]);
1965
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { flex: "none", borderBottom: "1px solid var(--vscode-panel-border)" }, children: [
1966
+ !!dragWindow && /* @__PURE__ */ jsxRuntimeExports.jsx(
1967
+ GlassPane,
1968
+ {
1969
+ cursor: (dragWindow == null ? void 0 : dragWindow.type) === "resize" ? "ew-resize" : "grab",
1970
+ onPaneMouseUp: onGlassPaneMouseUp,
1971
+ onPaneMouseMove: onGlassPaneMouseMove,
1972
+ onPaneDoubleClick
1973
+ }
1974
+ ),
1975
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
1976
+ "div",
1977
+ {
1978
+ ref,
1979
+ className: "timeline-view",
1980
+ onMouseDown,
1981
+ onMouseMove,
1982
+ onMouseLeave,
1983
+ children: [
1984
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-grid", children: offsets.map((offset, index) => {
1985
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-divider", style: { left: offset.position + "px" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-time", children: msToString(offset.time - boundaries.minimum) }) }, index);
1986
+ }) }),
1987
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { height: 8 } }),
1988
+ /* @__PURE__ */ jsxRuntimeExports.jsx(FilmStrip, { model, boundaries, previewPoint }),
1989
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-bars", children: bars.map((bar, index) => {
1990
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
1991
+ "div",
1992
+ {
1993
+ className: clsx(
1994
+ "timeline-bar",
1995
+ bar.action && "action",
1996
+ bar.resource && "network",
1997
+ bar.consoleMessage && "console-message",
1998
+ bar.active && "active",
1999
+ bar.error && "error"
2000
+ ),
2001
+ style: {
2002
+ left: bar.leftPosition,
2003
+ width: Math.max(5, bar.rightPosition - bar.leftPosition),
2004
+ top: barTop(bar),
2005
+ bottom: 0
2006
+ }
2007
+ },
2008
+ index
2009
+ );
2010
+ }) }),
2011
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-marker", style: {
2012
+ display: previewPoint !== void 0 ? "block" : "none",
2013
+ left: ((previewPoint == null ? void 0 : previewPoint.x) || 0) + "px"
2014
+ } }),
2015
+ selectedTime && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "timeline-window", children: [
2016
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-curtain left", style: { width: curtainLeft } }),
2017
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-resizer", style: { left: -5 } }),
2018
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-drag" }) }),
2019
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-resizer", style: { left: 5 } }),
2020
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "timeline-window-curtain right", style: { width: curtainRight } })
2021
+ ] })
2022
+ ]
2023
+ }
2024
+ )
2025
+ ] });
2026
+ };
2027
+ function calculateDividerOffsets(clientWidth, boundaries) {
2028
+ const minimumGap = 64;
2029
+ let dividerCount = clientWidth / minimumGap;
2030
+ const boundarySpan = boundaries.maximum - boundaries.minimum;
2031
+ const pixelsPerMillisecond = clientWidth / boundarySpan;
2032
+ let sectionTime = boundarySpan / dividerCount;
2033
+ const logSectionTime = Math.ceil(Math.log(sectionTime) / Math.LN10);
2034
+ sectionTime = Math.pow(10, logSectionTime);
2035
+ if (sectionTime * pixelsPerMillisecond >= 5 * minimumGap)
2036
+ sectionTime = sectionTime / 5;
2037
+ if (sectionTime * pixelsPerMillisecond >= 2 * minimumGap)
2038
+ sectionTime = sectionTime / 2;
2039
+ const firstDividerTime = boundaries.minimum;
2040
+ let lastDividerTime = boundaries.maximum;
2041
+ lastDividerTime += minimumGap / pixelsPerMillisecond;
2042
+ dividerCount = Math.ceil((lastDividerTime - firstDividerTime) / sectionTime);
2043
+ if (!sectionTime)
2044
+ dividerCount = 0;
2045
+ const offsets = [];
2046
+ for (let i2 = 0; i2 < dividerCount; ++i2) {
2047
+ const time = firstDividerTime + sectionTime * i2;
2048
+ offsets.push({ position: timeToPosition(clientWidth, boundaries, time), time });
2049
+ }
2050
+ return offsets;
2051
+ }
2052
+ function timeToPosition(clientWidth, boundaries, time) {
2053
+ return (time - boundaries.minimum) / (boundaries.maximum - boundaries.minimum) * clientWidth;
2054
+ }
2055
+ function positionToTime(clientWidth, boundaries, x2) {
2056
+ return x2 / clientWidth * (boundaries.maximum - boundaries.minimum) + boundaries.minimum;
2057
+ }
2058
+ function barTop(bar) {
2059
+ return bar.resource ? 25 : 20;
2060
+ }
2061
+ const MetadataView = ({ model }) => {
2062
+ var _a, _b;
2063
+ if (!model)
2064
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, {});
2065
+ const wallTime = model.wallTime !== void 0 ? new Date(model.wallTime).toLocaleString(void 0, { timeZoneName: "short" }) : void 0;
2066
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { "data-testid": "metadata-view", className: "vbox", style: { flexShrink: 0 }, children: [
2067
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", style: { paddingTop: 2 }, children: "Time" }),
2068
+ !!wallTime && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2069
+ "start time:",
2070
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value datetime", title: wallTime, children: wallTime })
2071
+ ] }),
2072
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2073
+ "duration:",
2074
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", title: msToString(model.endTime - model.startTime), children: msToString(model.endTime - model.startTime) })
2075
+ ] }),
2076
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Browser" }),
2077
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2078
+ "engine:",
2079
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value string", title: model.browserName, children: model.browserName })
2080
+ ] }),
2081
+ model.channel && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2082
+ "channel:",
2083
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value string", title: model.channel, children: model.channel })
2084
+ ] }),
2085
+ model.platform && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2086
+ "platform:",
2087
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value string", title: model.platform, children: model.platform })
2088
+ ] }),
2089
+ model.options.userAgent && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2090
+ "user agent:",
2091
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value datetime", title: model.options.userAgent, children: model.options.userAgent })
2092
+ ] }),
2093
+ model.options.baseURL && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2094
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", style: { paddingTop: 2 }, children: "Config" }),
2095
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2096
+ "baseURL:",
2097
+ /* @__PURE__ */ jsxRuntimeExports.jsx("a", { className: "call-value string", href: model.options.baseURL, title: model.options.baseURL, target: "_blank", rel: "noopener noreferrer", children: model.options.baseURL })
2098
+ ] })
2099
+ ] }),
2100
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Viewport" }),
2101
+ model.options.viewport && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2102
+ "width:",
2103
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", title: String(!!((_a = model.options.viewport) == null ? void 0 : _a.width)), children: model.options.viewport.width })
2104
+ ] }),
2105
+ model.options.viewport && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2106
+ "height:",
2107
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", title: String(!!((_b = model.options.viewport) == null ? void 0 : _b.height)), children: model.options.viewport.height })
2108
+ ] }),
2109
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2110
+ "is mobile:",
2111
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value boolean", title: String(!!model.options.isMobile), children: String(!!model.options.isMobile) })
2112
+ ] }),
2113
+ model.options.deviceScaleFactor && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2114
+ "device scale:",
2115
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", title: String(model.options.deviceScaleFactor), children: String(model.options.deviceScaleFactor) })
2116
+ ] }),
2117
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "call-section", children: "Counts" }),
2118
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2119
+ "pages:",
2120
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", children: model.pages.length })
2121
+ ] }),
2122
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2123
+ "actions:",
2124
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", children: model.actions.length })
2125
+ ] }),
2126
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "call-line", children: [
2127
+ "events:",
2128
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "call-value number", children: model.events.length })
2129
+ ] })
2130
+ ] });
2131
+ };
2132
+ const AnnotationsTab = ({ annotations }) => {
2133
+ if (!annotations.length)
2134
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PlaceholderPanel, { text: "No annotations" });
2135
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "annotations-tab", children: annotations.map((annotation, i2) => {
2136
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "annotation-item", children: [
2137
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontWeight: "bold" }, children: annotation.type }),
2138
+ annotation.description && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [
2139
+ ": ",
2140
+ linkifyText(annotation.description)
2141
+ ] })
2142
+ ] }, `annotation-${i2}`);
2143
+ }) });
2144
+ };
2145
+ const Workbench = ({ model, showSourcesFirst, rootDir, fallbackLocation, isLive, hideTimeline, status, annotations, inert, onOpenExternally, revealSource }) => {
2146
+ var _a;
2147
+ const [selectedCallId, setSelectedCallId] = reactExports.useState(void 0);
2148
+ const [revealedError, setRevealedError] = reactExports.useState(void 0);
2149
+ const [revealedAttachment, setRevealedAttachment] = reactExports.useState(void 0);
2150
+ const [highlightedCallId, setHighlightedCallId] = reactExports.useState();
2151
+ const [highlightedEntry, setHighlightedEntry] = reactExports.useState();
2152
+ const [highlightedConsoleMessage, setHighlightedConsoleMessage] = reactExports.useState();
2153
+ const [selectedNavigatorTab, setSelectedNavigatorTab] = reactExports.useState("actions");
2154
+ const [selectedPropertiesTab, setSelectedPropertiesTab] = useSetting("propertiesTab", showSourcesFirst ? "source" : "call");
2155
+ const [isInspecting, setIsInspectingState] = reactExports.useState(false);
2156
+ const [highlightedElement, setHighlightedElement] = reactExports.useState({ lastEdited: "none" });
2157
+ const [selectedTime, setSelectedTime] = reactExports.useState();
2158
+ const [sidebarLocation, setSidebarLocation] = useSetting("propertiesSidebarLocation", "bottom");
2159
+ const showScreenshot = false;
2160
+ const setSelectedAction = reactExports.useCallback((action) => {
2161
+ setSelectedCallId(action == null ? void 0 : action.callId);
2162
+ setRevealedError(void 0);
2163
+ }, []);
2164
+ const highlightedAction = reactExports.useMemo(() => {
2165
+ return model == null ? void 0 : model.actions.find((a2) => a2.callId === highlightedCallId);
2166
+ }, [model, highlightedCallId]);
2167
+ const setHighlightedAction = reactExports.useCallback((highlightedAction2) => {
2168
+ setHighlightedCallId(highlightedAction2 == null ? void 0 : highlightedAction2.callId);
2169
+ }, []);
2170
+ const sources = reactExports.useMemo(() => (model == null ? void 0 : model.sources) || /* @__PURE__ */ new Map(), [model]);
2171
+ reactExports.useEffect(() => {
2172
+ setSelectedTime(void 0);
2173
+ setRevealedError(void 0);
2174
+ }, [model]);
2175
+ const selectedAction = reactExports.useMemo(() => {
2176
+ if (selectedCallId) {
2177
+ const action = model == null ? void 0 : model.actions.find((a2) => a2.callId === selectedCallId);
2178
+ if (action)
2179
+ return action;
2180
+ }
2181
+ const failedAction = model == null ? void 0 : model.failedAction();
2182
+ if (failedAction)
2183
+ return failedAction;
2184
+ if (model == null ? void 0 : model.actions.length) {
2185
+ let index = model.actions.length - 1;
2186
+ for (let i2 = 0; i2 < model.actions.length; ++i2) {
2187
+ if (model.actions[i2].apiName === "After Hooks" && i2) {
2188
+ index = i2 - 1;
2189
+ break;
2190
+ }
2191
+ }
2192
+ return model.actions[index];
2193
+ }
2194
+ }, [model, selectedCallId]);
2195
+ const activeAction = reactExports.useMemo(() => {
2196
+ return highlightedAction || selectedAction;
2197
+ }, [selectedAction, highlightedAction]);
2198
+ const revealedStack = reactExports.useMemo(() => {
2199
+ if (revealedError)
2200
+ return revealedError.stack;
2201
+ return activeAction == null ? void 0 : activeAction.stack;
2202
+ }, [activeAction, revealedError]);
2203
+ const onActionSelected = reactExports.useCallback((action) => {
2204
+ setSelectedAction(action);
2205
+ setHighlightedAction(void 0);
2206
+ }, [setSelectedAction, setHighlightedAction]);
2207
+ const selectPropertiesTab = reactExports.useCallback((tab) => {
2208
+ setSelectedPropertiesTab(tab);
2209
+ if (tab !== "inspector")
2210
+ setIsInspectingState(false);
2211
+ }, [setSelectedPropertiesTab]);
2212
+ const setIsInspecting = reactExports.useCallback((value) => {
2213
+ if (!isInspecting && value)
2214
+ selectPropertiesTab("inspector");
2215
+ setIsInspectingState(value);
2216
+ }, [setIsInspectingState, selectPropertiesTab, isInspecting]);
2217
+ const elementPicked = reactExports.useCallback((element) => {
2218
+ setHighlightedElement(element);
2219
+ selectPropertiesTab("inspector");
2220
+ }, [selectPropertiesTab]);
2221
+ const revealAttachment = reactExports.useCallback((attachment) => {
2222
+ selectPropertiesTab("attachments");
2223
+ setRevealedAttachment((currentValue) => {
2224
+ if (!currentValue)
2225
+ return [attachment, 0];
2226
+ const revealCounter = currentValue[1];
2227
+ return [attachment, revealCounter + 1];
2228
+ });
2229
+ }, [selectPropertiesTab]);
2230
+ reactExports.useEffect(() => {
2231
+ if (revealSource)
2232
+ selectPropertiesTab("source");
2233
+ }, [revealSource, selectPropertiesTab]);
2234
+ const consoleModel = useConsoleTabModel(model, selectedTime);
2235
+ const networkModel = useNetworkTabModel(model, selectedTime);
2236
+ const errorsModel = useErrorsTabModel(model);
2237
+ const sdkLanguage = (model == null ? void 0 : model.sdkLanguage) || "javascript";
2238
+ const inspectorTab = {
2239
+ id: "inspector",
2240
+ title: "Locator",
2241
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
2242
+ InspectorTab,
2243
+ {
2244
+ showScreenshot,
2245
+ sdkLanguage,
2246
+ setIsInspecting,
2247
+ highlightedElement,
2248
+ setHighlightedElement
2249
+ }
2250
+ )
2251
+ };
2252
+ const callTab = {
2253
+ id: "call",
2254
+ title: "Call",
2255
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(CallTab, { action: activeAction, startTimeOffset: (model == null ? void 0 : model.startTime) ?? 0, sdkLanguage })
2256
+ };
2257
+ const logTab = {
2258
+ id: "log",
2259
+ title: "Log",
2260
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(LogTab, { action: activeAction, isLive })
2261
+ };
2262
+ const errorsTab = {
2263
+ id: "errors",
2264
+ title: "Errors",
2265
+ errorCount: errorsModel.errors.size,
2266
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorsTab, { errorsModel, sdkLanguage, revealInSource: (error) => {
2267
+ if (error.action)
2268
+ setSelectedAction(error.action);
2269
+ else
2270
+ setRevealedError(error);
2271
+ selectPropertiesTab("source");
2272
+ }, wallTime: (model == null ? void 0 : model.wallTime) ?? 0 })
2273
+ };
2274
+ let fallbackSourceErrorCount = void 0;
2275
+ if (!selectedAction && fallbackLocation)
2276
+ fallbackSourceErrorCount = (_a = fallbackLocation.source) == null ? void 0 : _a.errors.length;
2277
+ const sourceTab = {
2278
+ id: "source",
2279
+ title: "Source",
2280
+ errorCount: fallbackSourceErrorCount,
2281
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
2282
+ SourceTab,
2283
+ {
2284
+ stack: revealedStack,
2285
+ sources,
2286
+ rootDir,
2287
+ stackFrameLocation: sidebarLocation === "bottom" ? "right" : "bottom",
2288
+ fallbackLocation,
2289
+ onOpenExternally
2290
+ }
2291
+ )
2292
+ };
2293
+ const consoleTab = {
2294
+ id: "console",
2295
+ title: "Console",
2296
+ count: consoleModel.entries.length,
2297
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(
2298
+ ConsoleTab,
2299
+ {
2300
+ consoleModel,
2301
+ boundaries,
2302
+ selectedTime,
2303
+ onAccepted: (m2) => setSelectedTime({ minimum: m2.timestamp, maximum: m2.timestamp }),
2304
+ onEntryHovered: setHighlightedConsoleMessage
2305
+ }
2306
+ )
2307
+ };
2308
+ const networkTab = {
2309
+ id: "network",
2310
+ title: "Network",
2311
+ count: networkModel.resources.length,
2312
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(NetworkTab, { boundaries, networkModel, onEntryHovered: setHighlightedEntry, sdkLanguage: (model == null ? void 0 : model.sdkLanguage) ?? "javascript" })
2313
+ };
2314
+ const attachmentsTab = {
2315
+ id: "attachments",
2316
+ title: "Attachments",
2317
+ count: model == null ? void 0 : model.visibleAttachments.length,
2318
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(AttachmentsTab, { model, revealedAttachment })
2319
+ };
2320
+ const tabs = [
2321
+ inspectorTab,
2322
+ callTab,
2323
+ logTab,
2324
+ errorsTab,
2325
+ consoleTab,
2326
+ networkTab,
2327
+ sourceTab,
2328
+ attachmentsTab
2329
+ ];
2330
+ if (annotations !== void 0) {
2331
+ const annotationsTab = {
2332
+ id: "annotations",
2333
+ title: "Annotations",
2334
+ count: annotations.length,
2335
+ render: () => /* @__PURE__ */ jsxRuntimeExports.jsx(AnnotationsTab, { annotations })
2336
+ };
2337
+ tabs.push(annotationsTab);
2338
+ }
2339
+ if (showSourcesFirst) {
2340
+ const sourceTabIndex = tabs.indexOf(sourceTab);
2341
+ tabs.splice(sourceTabIndex, 1);
2342
+ tabs.splice(1, 0, sourceTab);
2343
+ }
2344
+ const { boundaries } = reactExports.useMemo(() => {
2345
+ const boundaries2 = { minimum: (model == null ? void 0 : model.startTime) || 0, maximum: (model == null ? void 0 : model.endTime) || 3e4 };
2346
+ if (boundaries2.minimum > boundaries2.maximum) {
2347
+ boundaries2.minimum = 0;
2348
+ boundaries2.maximum = 3e4;
2349
+ }
2350
+ boundaries2.maximum += (boundaries2.maximum - boundaries2.minimum) / 20;
2351
+ return { boundaries: boundaries2 };
2352
+ }, [model]);
2353
+ let time = 0;
2354
+ if (!isLive && model && model.endTime >= 0)
2355
+ time = model.endTime - model.startTime;
2356
+ else if (model && model.wallTime)
2357
+ time = Date.now() - model.wallTime;
2358
+ const actionsTab = {
2359
+ id: "actions",
2360
+ title: "Actions",
2361
+ component: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox", children: [
2362
+ status && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "workbench-run-status", children: [
2363
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: clsx("codicon", testStatusIcon(status)) }),
2364
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: testStatusText(status) }),
2365
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "spacer" }),
2366
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "workbench-run-duration", children: time ? msToString(time) : "" })
2367
+ ] }),
2368
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
2369
+ ActionList,
2370
+ {
2371
+ sdkLanguage,
2372
+ actions: (model == null ? void 0 : model.actions) || [],
2373
+ selectedAction: model ? selectedAction : void 0,
2374
+ selectedTime,
2375
+ setSelectedTime,
2376
+ onSelected: onActionSelected,
2377
+ onHighlighted: setHighlightedAction,
2378
+ revealAttachment,
2379
+ revealConsole: () => selectPropertiesTab("console"),
2380
+ isLive
2381
+ }
2382
+ )
2383
+ ] })
2384
+ };
2385
+ const metadataTab = {
2386
+ id: "metadata",
2387
+ title: "Metadata",
2388
+ component: /* @__PURE__ */ jsxRuntimeExports.jsx(MetadataView, { model })
2389
+ };
2390
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "vbox workbench", ...inert ? { inert: "true" } : {}, children: [
2391
+ !hideTimeline && /* @__PURE__ */ jsxRuntimeExports.jsx(
2392
+ Timeline,
2393
+ {
2394
+ model,
2395
+ consoleEntries: consoleModel.entries,
2396
+ boundaries,
2397
+ highlightedAction,
2398
+ highlightedEntry,
2399
+ highlightedConsoleEntry: highlightedConsoleMessage,
2400
+ onSelected: onActionSelected,
2401
+ sdkLanguage,
2402
+ selectedTime,
2403
+ setSelectedTime
2404
+ }
2405
+ ),
2406
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
2407
+ SplitView,
2408
+ {
2409
+ sidebarSize: 250,
2410
+ orientation: sidebarLocation === "bottom" ? "vertical" : "horizontal",
2411
+ settingName: "propertiesSidebar",
2412
+ main: /* @__PURE__ */ jsxRuntimeExports.jsx(
2413
+ SplitView,
2414
+ {
2415
+ sidebarSize: 250,
2416
+ orientation: "horizontal",
2417
+ sidebarIsFirst: true,
2418
+ settingName: "actionListSidebar",
2419
+ main: /* @__PURE__ */ jsxRuntimeExports.jsx(
2420
+ SnapshotTabsView,
2421
+ {
2422
+ action: activeAction,
2423
+ model,
2424
+ sdkLanguage,
2425
+ testIdAttributeName: (model == null ? void 0 : model.testIdAttributeName) || "data-testid",
2426
+ isInspecting,
2427
+ setIsInspecting,
2428
+ highlightedElement,
2429
+ setHighlightedElement: elementPicked
2430
+ }
2431
+ ),
2432
+ sidebar: /* @__PURE__ */ jsxRuntimeExports.jsx(
2433
+ TabbedPane,
2434
+ {
2435
+ tabs: [actionsTab, metadataTab],
2436
+ selectedTab: selectedNavigatorTab,
2437
+ setSelectedTab: setSelectedNavigatorTab
2438
+ }
2439
+ )
2440
+ }
2441
+ ),
2442
+ sidebar: /* @__PURE__ */ jsxRuntimeExports.jsx(
2443
+ TabbedPane,
2444
+ {
2445
+ tabs,
2446
+ selectedTab: selectedPropertiesTab,
2447
+ setSelectedTab: selectPropertiesTab,
2448
+ rightToolbar: [
2449
+ sidebarLocation === "bottom" ? /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { title: "Dock to right", icon: "layout-sidebar-right-off", onClick: () => {
2450
+ setSidebarLocation("right");
2451
+ } }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarButton, { title: "Dock to bottom", icon: "layout-panel-off", onClick: () => {
2452
+ setSidebarLocation("bottom");
2453
+ } })
2454
+ ],
2455
+ mode: sidebarLocation === "bottom" ? "default" : "select"
2456
+ }
2457
+ )
2458
+ }
2459
+ )
2460
+ ] });
2461
+ };
2462
+ export {
2463
+ Expandable as E,
2464
+ LLMProvider as L,
2465
+ TreeView as T,
2466
+ Workbench as W,
2467
+ EventEmitter as a,
2468
+ testStatusIcon as t
2469
+ };
2470
+ //# sourceMappingURL=workbench-CWZselvp.js.map