@red-hat-developer-hub/backstage-plugin-intelligent-assistant 4.1.0 → 4.2.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/CHANGELOG.md +13 -0
  2. package/README.md +23 -0
  3. package/config.schema.json +117 -0
  4. package/dist/api/NotebooksApiClient.esm.js +3 -2
  5. package/dist/api/NotebooksApiClient.esm.js.map +1 -1
  6. package/dist/api/notebooksApi.esm.js.map +1 -1
  7. package/dist/components/LightSpeedChat.esm.js +280 -118
  8. package/dist/components/LightSpeedChat.esm.js.map +1 -1
  9. package/dist/components/LightspeedDrawerContext.esm.js.map +1 -1
  10. package/dist/components/LightspeedDrawerProvider.esm.js +5 -4
  11. package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -1
  12. package/dist/components/ToastAlertGroup.esm.js +56 -0
  13. package/dist/components/ToastAlertGroup.esm.js.map +1 -0
  14. package/dist/components/notebooks/AddDocumentModal.esm.js +165 -144
  15. package/dist/components/notebooks/AddDocumentModal.esm.js.map +1 -1
  16. package/dist/components/notebooks/DeleteDocumentModal.esm.js +73 -38
  17. package/dist/components/notebooks/DeleteDocumentModal.esm.js.map +1 -1
  18. package/dist/components/notebooks/DeleteNotebookModal.esm.js +80 -40
  19. package/dist/components/notebooks/DeleteNotebookModal.esm.js.map +1 -1
  20. package/dist/components/notebooks/NotebookHeaderActions.esm.js +78 -0
  21. package/dist/components/notebooks/NotebookHeaderActions.esm.js.map +1 -0
  22. package/dist/components/notebooks/NotebookStreamProvider.esm.js +47 -0
  23. package/dist/components/notebooks/NotebookStreamProvider.esm.js.map +1 -0
  24. package/dist/components/notebooks/NotebookView.esm.js +284 -349
  25. package/dist/components/notebooks/NotebookView.esm.js.map +1 -1
  26. package/dist/components/notebooks/NotebooksTab.esm.js +2 -2
  27. package/dist/components/notebooks/NotebooksTab.esm.js.map +1 -1
  28. package/dist/components/notebooks/OverwriteConfirmModal.esm.js +126 -82
  29. package/dist/components/notebooks/OverwriteConfirmModal.esm.js.map +1 -1
  30. package/dist/components/notebooks/SidebarCollapseIcon.esm.js +8 -6
  31. package/dist/components/notebooks/SidebarCollapseIcon.esm.js.map +1 -1
  32. package/dist/components/notebooks/UploadResourceScreen.esm.js +1 -0
  33. package/dist/components/notebooks/UploadResourceScreen.esm.js.map +1 -1
  34. package/dist/components/notebooks/notebookDialogStyles.esm.js +40 -0
  35. package/dist/components/notebooks/notebookDialogStyles.esm.js.map +1 -0
  36. package/dist/components/notebooks/notebookStreamStore.esm.js +282 -0
  37. package/dist/components/notebooks/notebookStreamStore.esm.js.map +1 -0
  38. package/dist/hooks/notebooks/useCreateNotebookMessage.esm.js +3 -2
  39. package/dist/hooks/notebooks/useCreateNotebookMessage.esm.js.map +1 -1
  40. package/dist/hooks/useConversationMessages.esm.js +31 -108
  41. package/dist/hooks/useConversationMessages.esm.js.map +1 -1
  42. package/dist/hooks/useLightspeedProviderState.esm.js +14 -5
  43. package/dist/hooks/useLightspeedProviderState.esm.js.map +1 -1
  44. package/dist/index.esm.js +2 -2
  45. package/dist/index.esm.js.map +1 -1
  46. package/dist/utils/dom-extractor.esm.js +816 -0
  47. package/dist/utils/dom-extractor.esm.js.map +1 -0
  48. package/dist/utils/dom-selectors.esm.js +91 -0
  49. package/dist/utils/dom-selectors.esm.js.map +1 -0
  50. package/dist/utils/scoped-dialog-utils.esm.js +35 -0
  51. package/dist/utils/scoped-dialog-utils.esm.js.map +1 -0
  52. package/dist/utils/sensitive-data-redactor.esm.js +66 -0
  53. package/dist/utils/sensitive-data-redactor.esm.js.map +1 -0
  54. package/dist/utils/stream-event-helpers.esm.js +105 -0
  55. package/dist/utils/stream-event-helpers.esm.js.map +1 -0
  56. package/package.json +14 -14
  57. package/config.d.ts +0 -99
@@ -0,0 +1,816 @@
1
+ import { NOISE_SELECTOR, PLUGIN_NAME_SELECTOR, PAGE_TITLE_SELECTOR, ACTIVE_TAB_SELECTOR, BREADCRUMB_SELECTOR, ACTIVE_NAV_SELECTOR, MODAL_DIALOG_SELECTOR, DIALOG_TITLE_SELECTOR, DIALOG_CONTENT_SELECTOR, DOCKED_DRAWER_BODY_CLASS, DRAWER_PAPER_SELECTOR, SEARCH_INPUT_SELECTOR, FILTER_NAV_SELECTOR, ACCORDION_ROOT_SELECTOR, ACCORDION_DETAILS_SELECTOR, ACCORDION_SUMMARY_CONTENT_SELECTOR, FILTER_BOX_SELECTOR, SELECTED_ITEM_SELECTOR, LIST_ITEM_TEXT_PRIMARY_SELECTOR, LIST_ITEM_TEXT_SECONDARY_SELECTOR, MENU_SELECTOR, CARD_ROOT_SELECTOR, LIST_ITEM_TEXT_ROOT_SELECTOR, FILTER_CONTAINER_SELECTOR, TAB_LIST_SELECTOR, TAB_SELECTOR, BUI_NAV_SELECTOR, BUI_NAV_ITEM_SELECTOR, ALERT_SELECTOR, STEPPER_ROOT_SELECTOR, STEPPER_LABEL_SELECTOR, STEPPER_ACTIVE_CLASS, STEPPER_COMPLETED_CLASS, CARD_TITLE_SELECTOR, CARD_LAYOUT_SELECTOR, CARD_ITEM_SELECTOR, RECHARTS_LEGEND_SELECTOR, STATUS_INDICATOR_SELECTOR, RJSF_FORM_SELECTOR, FORM_CONTROL_SELECTOR, SELECT_DISPLAY_SELECTOR, CHIP_LABEL_SELECTOR, EMPTY_STATE_SELECTOR, EMPTY_STATE_BODY_SELECTOR, PAGINATION_ROOT_SELECTOR, PAGINATION_ACTIONS_SELECTOR, SHADOW_HOST_SELECTOR, SHADOW_NOISE_SELECTOR, FORM_LABEL_SELECTOR, FORM_CONTROL_LABEL_SELECTOR, FORM_HTML_STRIP_SELECTOR } from './dom-selectors.esm.js';
2
+ import { redactText, isSensitiveElement } from './sensitive-data-redactor.esm.js';
3
+
4
+ const DEFAULT_MAX_CHARS = 8e3;
5
+ const MAX_TABLE_ROWS = 50;
6
+ const MAX_TABLES = 10;
7
+ const MAX_CARDS = 10;
8
+ const MAX_CARD_CHARS = 500;
9
+ const MIN_CARDS_THRESHOLD = 1;
10
+ const MAX_FORM_HTML_CHARS = 4e3;
11
+ const SENSITIVE_VALUE = "[REDACTED]";
12
+ function extractPageContext(options) {
13
+ try {
14
+ return extractPageContextInternal(options);
15
+ } catch {
16
+ return "";
17
+ }
18
+ }
19
+ function extractPageContextInternal(options) {
20
+ const maxChars = options?.maxChars ?? DEFAULT_MAX_CHARS;
21
+ const root = document.querySelector("#root");
22
+ if (!root) {
23
+ return "";
24
+ }
25
+ const clone = root.cloneNode(true);
26
+ clone.querySelectorAll(NOISE_SELECTOR).forEach((el) => el.remove());
27
+ if (options?.excludeSelector) {
28
+ clone.querySelectorAll(options.excludeSelector).forEach((el) => el.remove());
29
+ }
30
+ const sections = [];
31
+ let charCount = 0;
32
+ const appendSection = (content) => {
33
+ if (!content.trim()) return true;
34
+ if (charCount + content.length > maxChars) {
35
+ const remaining = maxChars - charCount;
36
+ if (remaining > 50) {
37
+ sections.push(content.slice(0, remaining));
38
+ charCount = maxChars;
39
+ }
40
+ return false;
41
+ }
42
+ sections.push(content);
43
+ charCount += content.length;
44
+ return true;
45
+ };
46
+ const headerLines = [`Page: ${window.location.pathname}`];
47
+ const pluginName = document.querySelector(PLUGIN_NAME_SELECTOR)?.textContent?.trim();
48
+ if (pluginName) {
49
+ headerLines.push(`Plugin: ${pluginName}`);
50
+ }
51
+ const pageTitle = document.querySelector(PAGE_TITLE_SELECTOR)?.textContent?.trim();
52
+ if (pageTitle) {
53
+ headerLines.push(`Title: ${pageTitle}`);
54
+ }
55
+ const activeTab = document.querySelector(ACTIVE_TAB_SELECTOR)?.textContent?.trim();
56
+ if (activeTab) {
57
+ headerLines.push(`CurrentTab: ${activeTab}`);
58
+ }
59
+ const breadcrumb = document.querySelector(BREADCRUMB_SELECTOR);
60
+ if (breadcrumb) {
61
+ const crumbs = Array.from(breadcrumb.querySelectorAll("li, a, p")).map((el) => el.textContent?.trim()).filter(Boolean);
62
+ if (crumbs.length > 0) {
63
+ headerLines.push(`Breadcrumb: ${crumbs.join(" > ")}`);
64
+ }
65
+ }
66
+ const activeNav = document.querySelector(ACTIVE_NAV_SELECTOR)?.textContent?.trim();
67
+ if (activeNav) {
68
+ headerLines.push(`Nav: ${activeNav}`);
69
+ }
70
+ headerLines.push(`Document: ${document.title}`);
71
+ const header = headerLines.join("\n");
72
+ if (!appendSection(header)) {
73
+ return redactText(sections.join("\n\n"));
74
+ }
75
+ const overlayText = extractActiveOverlay();
76
+ if (overlayText && !appendSection(overlayText)) {
77
+ return redactText(sections.join("\n\n"));
78
+ }
79
+ const searchText = extractSearchInputs();
80
+ if (searchText && !appendSection(searchText)) {
81
+ return redactText(sections.join("\n\n"));
82
+ }
83
+ const filterText = extractFilterSections();
84
+ if (filterText && !appendSection(filterText)) {
85
+ return redactText(sections.join("\n\n"));
86
+ }
87
+ const tabsText = extractTabs(clone);
88
+ if (tabsText && !appendSection(tabsText)) {
89
+ return redactText(sections.join("\n\n"));
90
+ }
91
+ clone.querySelectorAll('nav, [role="navigation"]').forEach((el) => el.remove());
92
+ const alertText = extractAlerts(clone);
93
+ if (alertText && !appendSection(alertText)) {
94
+ return redactText(sections.join("\n\n"));
95
+ }
96
+ const stepperText = extractStepperState(clone);
97
+ if (stepperText && !appendSection(stepperText)) {
98
+ return redactText(sections.join("\n\n"));
99
+ }
100
+ const cardsText = extractCards(clone);
101
+ if (cardsText && !appendSection(cardsText)) {
102
+ return redactText(sections.join("\n\n"));
103
+ }
104
+ const headingsText = extractHeadings(clone);
105
+ if (headingsText && !appendSection(headingsText)) {
106
+ return redactText(sections.join("\n\n"));
107
+ }
108
+ const statusText = extractStatusIndicators(clone);
109
+ if (statusText && !appendSection(statusText)) {
110
+ return redactText(sections.join("\n\n"));
111
+ }
112
+ const formsText = extractFormFields(clone);
113
+ if (formsText && !appendSection(formsText)) {
114
+ return redactText(sections.join("\n\n"));
115
+ }
116
+ const tablesText = extractTables(clone);
117
+ if (tablesText && !appendSection(tablesText)) {
118
+ return redactText(sections.join("\n\n"));
119
+ }
120
+ const dlText = extractDescriptionLists(clone);
121
+ if (dlText && !appendSection(dlText)) {
122
+ return redactText(sections.join("\n\n"));
123
+ }
124
+ const emptyText = extractEmptyState(clone);
125
+ if (emptyText && !appendSection(emptyText)) {
126
+ return redactText(sections.join("\n\n"));
127
+ }
128
+ const paginationText = extractPagination(clone);
129
+ if (paginationText && !appendSection(paginationText)) {
130
+ return redactText(sections.join("\n\n"));
131
+ }
132
+ const bodyText = extractBodyText(clone, maxChars - charCount);
133
+ if (bodyText) {
134
+ appendSection(bodyText);
135
+ }
136
+ const shadowText = extractShadowDomContent();
137
+ if (shadowText) {
138
+ appendSection(shadowText);
139
+ }
140
+ const result = sections.join("\n\n");
141
+ return result ? redactText(result) : "";
142
+ }
143
+ function extractActiveOverlay() {
144
+ const dialog = document.querySelector(MODAL_DIALOG_SELECTOR);
145
+ if (dialog) {
146
+ const title = dialog.querySelector(DIALOG_TITLE_SELECTOR)?.textContent?.trim();
147
+ const content = collapseWhitespace(
148
+ dialog.querySelector(DIALOG_CONTENT_SELECTOR)?.textContent || ""
149
+ );
150
+ const lines = ["## Active Dialog"];
151
+ if (title) lines.push(`Title: ${title}`);
152
+ if (content) lines.push(content);
153
+ return lines.length > 1 ? lines.join("\n") : "";
154
+ }
155
+ if (document.body.classList.contains(DOCKED_DRAWER_BODY_CLASS)) {
156
+ const drawerPaper = document.querySelector(DRAWER_PAPER_SELECTOR);
157
+ if (drawerPaper && !drawerPaper.querySelector(".pf-chatbot")) {
158
+ const text = collapseWhitespace(drawerPaper.textContent || "");
159
+ if (text) {
160
+ return `## Active Drawer
161
+ ${text.slice(0, 2e3)}`;
162
+ }
163
+ }
164
+ }
165
+ return "";
166
+ }
167
+ function extractAlerts(root) {
168
+ const alerts = root.querySelectorAll(ALERT_SELECTOR);
169
+ if (alerts.length === 0) return "";
170
+ const lines = ["## Alerts"];
171
+ alerts.forEach((alert) => {
172
+ const text = collapseWhitespace(alert.textContent || "");
173
+ if (text) {
174
+ lines.push(`- ${text}`);
175
+ }
176
+ alert.remove();
177
+ });
178
+ return lines.length > 1 ? lines.join("\n") : "";
179
+ }
180
+ function extractStepperState(root) {
181
+ const steppers = root.querySelectorAll(STEPPER_ROOT_SELECTOR);
182
+ if (steppers.length === 0) return "";
183
+ const lines = ["## Stepper"];
184
+ steppers.forEach((stepper) => {
185
+ const labels = stepper.querySelectorAll(STEPPER_LABEL_SELECTOR);
186
+ labels.forEach((label) => {
187
+ const text = label.textContent?.trim();
188
+ if (!text) return;
189
+ const className = label.className || "";
190
+ const isActive = className.includes(STEPPER_ACTIVE_CLASS);
191
+ const isCompleted = className.includes(STEPPER_COMPLETED_CLASS);
192
+ let marker = "";
193
+ if (isActive) marker = " [active]";
194
+ else if (isCompleted) marker = " [done]";
195
+ lines.push(`- ${text}${marker}`);
196
+ });
197
+ stepper.remove();
198
+ });
199
+ return lines.length > 1 ? lines.join("\n") : "";
200
+ }
201
+ function extractTabs(root) {
202
+ const lines = ["## Tabs"];
203
+ const tabLists = root.querySelectorAll(TAB_LIST_SELECTOR);
204
+ tabLists.forEach((tabList) => {
205
+ const tabs = tabList.querySelectorAll(TAB_SELECTOR);
206
+ tabs.forEach((tab) => {
207
+ const text = collapseWhitespace(tab.textContent || "");
208
+ if (!text) return;
209
+ const isSelected = tab.getAttribute("aria-selected") === "true";
210
+ lines.push(`- ${text}${isSelected ? " [active]" : ""}`);
211
+ });
212
+ tabList.remove();
213
+ });
214
+ if (lines.length <= 1) {
215
+ const navs = root.querySelectorAll(BUI_NAV_SELECTOR);
216
+ for (const nav of Array.from(navs)) {
217
+ const links = nav.querySelectorAll(BUI_NAV_ITEM_SELECTOR);
218
+ if (links.length < 2) continue;
219
+ links.forEach((link) => {
220
+ const text = collapseWhitespace(link.textContent || "");
221
+ if (!text) return;
222
+ const isActive = link.getAttribute("aria-current") === "page";
223
+ lines.push(`- ${text}${isActive ? " [active]" : ""}`);
224
+ });
225
+ nav.remove();
226
+ break;
227
+ }
228
+ }
229
+ return lines.length > 1 ? lines.join("\n") : "";
230
+ }
231
+ function extractHeadings(root) {
232
+ const headings = root.querySelectorAll("h1, h2, h3, h4");
233
+ if (headings.length === 0) return "";
234
+ const lines = ["## Headings"];
235
+ headings.forEach((heading) => {
236
+ const level = parseInt(heading.tagName[1], 10);
237
+ const indent = " ".repeat(level - 1);
238
+ const text = collapseWhitespace(heading.textContent || "");
239
+ if (text) {
240
+ lines.push(`${indent}- ${text}`);
241
+ }
242
+ heading.remove();
243
+ });
244
+ return lines.length > 1 ? lines.join("\n") : "";
245
+ }
246
+ function extractCards(root) {
247
+ try {
248
+ let cardElements = [];
249
+ const hasTitle = (el) => !!el.querySelector(CARD_TITLE_SELECTOR);
250
+ const layouts = root.querySelectorAll(CARD_LAYOUT_SELECTOR);
251
+ for (const layout of Array.from(layouts)) {
252
+ const directCards = Array.from(layout.children).filter((el) => {
253
+ try {
254
+ return el.matches(CARD_ITEM_SELECTOR) && hasTitle(el);
255
+ } catch {
256
+ return false;
257
+ }
258
+ });
259
+ if (directCards.length >= MIN_CARDS_THRESHOLD) {
260
+ cardElements = directCards;
261
+ break;
262
+ }
263
+ const nestedCards = [];
264
+ for (const child of Array.from(layout.children)) {
265
+ for (const grandchild of Array.from(child.children)) {
266
+ try {
267
+ if (grandchild.matches(CARD_ITEM_SELECTOR) && hasTitle(grandchild)) {
268
+ nestedCards.push(grandchild);
269
+ }
270
+ } catch {
271
+ }
272
+ }
273
+ }
274
+ if (nestedCards.length >= MIN_CARDS_THRESHOLD) {
275
+ cardElements = nestedCards;
276
+ break;
277
+ }
278
+ }
279
+ if (cardElements.length < MIN_CARDS_THRESHOLD) {
280
+ const allCards = Array.from(
281
+ root.querySelectorAll(CARD_ITEM_SELECTOR)
282
+ ).filter((el) => {
283
+ if (el.parentElement?.closest(CARD_ITEM_SELECTOR)) return false;
284
+ return hasTitle(el);
285
+ });
286
+ if (allCards.length >= MIN_CARDS_THRESHOLD) {
287
+ cardElements = allCards;
288
+ }
289
+ }
290
+ if (cardElements.length < MIN_CARDS_THRESHOLD) return "";
291
+ const sections = ["## Cards"];
292
+ let totalChars = 0;
293
+ let cardCount = 0;
294
+ for (const card of cardElements) {
295
+ if (cardCount >= MAX_CARDS) break;
296
+ const titleEl = card.querySelector(CARD_TITLE_SELECTOR);
297
+ const title = collapseWhitespace(titleEl?.textContent || "").replace(
298
+ /\s*\*$/,
299
+ ""
300
+ );
301
+ if (!title) {
302
+ card.remove();
303
+ continue;
304
+ }
305
+ const cardLines = [`### ${title}`];
306
+ const legendItems = card.querySelectorAll(RECHARTS_LEGEND_SELECTOR);
307
+ if (legendItems.length > 0) {
308
+ const seriesNames = Array.from(legendItems).map((el) => collapseWhitespace(el.textContent || "")).filter(Boolean);
309
+ if (seriesNames.length > 0) {
310
+ cardLines.push(`Chart: ${seriesNames.join(", ")}`);
311
+ }
312
+ }
313
+ card.querySelectorAll('svg, button, [aria-hidden="true"], hr, tfoot').forEach((el) => el.remove());
314
+ titleEl?.remove();
315
+ const table = card.querySelector("table");
316
+ if (table) {
317
+ const rows = table.querySelectorAll("tr");
318
+ const tableLines = [];
319
+ let rowCount = 0;
320
+ rows.forEach((row) => {
321
+ if (rowCount >= MAX_TABLE_ROWS) return;
322
+ const cells = row.querySelectorAll("th, td");
323
+ const cellTexts = Array.from(cells).map(
324
+ (cell) => collapseWhitespace(cell.textContent || "")
325
+ );
326
+ if (cellTexts.some(Boolean)) {
327
+ tableLines.push(`| ${cellTexts.join(" | ")} |`);
328
+ }
329
+ rowCount++;
330
+ });
331
+ if (tableLines.length > 0) {
332
+ cardLines.push(tableLines.join("\n"));
333
+ }
334
+ table.remove();
335
+ }
336
+ const innerHeadings = card.querySelectorAll("h2, h3");
337
+ if (innerHeadings.length >= 2) {
338
+ let extractedKV = false;
339
+ innerHeadings.forEach((h) => {
340
+ const key = collapseWhitespace(h.textContent || "");
341
+ if (!key) return;
342
+ const parent = h.parentElement;
343
+ if (!parent) return;
344
+ const cloned = parent.cloneNode(true);
345
+ const hClone = cloned.querySelector(h.tagName.toLowerCase());
346
+ hClone?.remove();
347
+ const val = collapseWhitespace(cloned.textContent || "") || "--";
348
+ cardLines.push(`${key}: ${val}`);
349
+ extractedKV = true;
350
+ h.remove();
351
+ });
352
+ if (extractedKV) {
353
+ innerHeadings.forEach((h) => h.remove());
354
+ }
355
+ }
356
+ const textContent = collapseWhitespace(card.textContent || "");
357
+ if (textContent && textContent !== title) {
358
+ cardLines.push(textContent);
359
+ }
360
+ const cardText = cardLines.join("\n");
361
+ if (totalChars + cardText.length > MAX_CARD_CHARS * MAX_CARDS) break;
362
+ sections.push(
363
+ cardText.length > MAX_CARD_CHARS ? cardText.slice(0, MAX_CARD_CHARS) : cardText
364
+ );
365
+ totalChars += Math.min(cardText.length, MAX_CARD_CHARS);
366
+ cardCount++;
367
+ card.remove();
368
+ }
369
+ return sections.length > 1 ? sections.join("\n\n") : "";
370
+ } catch (e) {
371
+ console.log("[DOM Cards] Error in extractCards:", e);
372
+ return "";
373
+ }
374
+ }
375
+ function extractStatusIndicators(root) {
376
+ const indicators = root.querySelectorAll(STATUS_INDICATOR_SELECTOR);
377
+ if (indicators.length === 0) return "";
378
+ const lines = ["## Status"];
379
+ const seen = /* @__PURE__ */ new Set();
380
+ indicators.forEach((el) => {
381
+ if (el.closest("td, th")) return;
382
+ const status = el.getAttribute("aria-label")?.replace("Status ", "") || "";
383
+ const text = el.textContent?.trim();
384
+ const entry = text ? `${status}: ${text}` : status;
385
+ if (entry && !seen.has(entry)) {
386
+ seen.add(entry);
387
+ lines.push(`- ${entry}`);
388
+ }
389
+ el.remove();
390
+ });
391
+ return lines.length > 1 ? lines.join("\n") : "";
392
+ }
393
+ function extractFormFields(root) {
394
+ const htmlParts = [];
395
+ let totalChars = 0;
396
+ const appendHtml = (html) => {
397
+ if (!html) return false;
398
+ if (totalChars + html.length > MAX_FORM_HTML_CHARS) {
399
+ const remaining = MAX_FORM_HTML_CHARS - totalChars;
400
+ if (remaining > 100) {
401
+ htmlParts.push(html.slice(0, remaining));
402
+ totalChars = MAX_FORM_HTML_CHARS;
403
+ }
404
+ return false;
405
+ }
406
+ htmlParts.push(html);
407
+ totalChars += html.length;
408
+ return true;
409
+ };
410
+ const liveForms = document.querySelectorAll(RJSF_FORM_SELECTOR);
411
+ const cloneForms = root.querySelectorAll(RJSF_FORM_SELECTOR);
412
+ const forms = liveForms.length > 0 ? liveForms : cloneForms;
413
+ const formsSource = liveForms.length > 0 ? "live" : "clone";
414
+ console.debug("[DOM Forms] Strategy 1:", {
415
+ selector: RJSF_FORM_SELECTOR,
416
+ liveFound: liveForms.length,
417
+ cloneFound: cloneForms.length,
418
+ using: formsSource
419
+ });
420
+ if (forms.length > 0) {
421
+ forms.forEach((form, idx) => {
422
+ if (form.closest(FILTER_CONTAINER_SELECTOR)) {
423
+ console.debug(
424
+ `[DOM Forms] Form ${idx} skipped: inside filter container`
425
+ );
426
+ return;
427
+ }
428
+ try {
429
+ const html = serializeFormControlHtml(form);
430
+ console.debug(`[DOM Forms] Form ${idx} serialized:`, {
431
+ length: html.length,
432
+ preview: html.slice(0, 200)
433
+ });
434
+ appendHtml(html);
435
+ } catch (e) {
436
+ console.debug(`[DOM Forms] Form ${idx} serialization error:`, e);
437
+ }
438
+ });
439
+ if (htmlParts.length > 0) {
440
+ root.querySelectorAll(RJSF_FORM_SELECTOR).forEach((el) => el.remove());
441
+ return `## Form Fields (HTML)
442
+ ${htmlParts.join("\n")}`;
443
+ }
444
+ }
445
+ const liveControls = Array.from(
446
+ document.querySelectorAll(FORM_CONTROL_SELECTOR)
447
+ );
448
+ const cloneControls = Array.from(
449
+ root.querySelectorAll(FORM_CONTROL_SELECTOR)
450
+ );
451
+ const controlsSource = liveControls.length > 0 ? liveControls : cloneControls;
452
+ console.debug("[DOM Forms] Strategy 2:", {
453
+ selector: FORM_CONTROL_SELECTOR,
454
+ liveCount: liveControls.length,
455
+ cloneCount: cloneControls.length,
456
+ using: liveControls.length > 0 ? "live" : "clone"
457
+ });
458
+ if (controlsSource.length === 0) return "";
459
+ const leafControls = controlsSource.filter(
460
+ (control) => !control.querySelector(FORM_CONTROL_SELECTOR)
461
+ );
462
+ leafControls.forEach((control) => {
463
+ if (control.closest(FILTER_CONTAINER_SELECTOR)) return;
464
+ if (control.closest(RJSF_FORM_SELECTOR)) return;
465
+ const searchInput = control.querySelector(SEARCH_INPUT_SELECTOR);
466
+ if (searchInput && !control.querySelector(
467
+ `${SELECT_DISPLAY_SELECTOR}, ${CHIP_LABEL_SELECTOR}, input[type="checkbox"]`
468
+ )) {
469
+ return;
470
+ }
471
+ try {
472
+ appendHtml(serializeFormControlHtml(control));
473
+ } catch {
474
+ }
475
+ });
476
+ root.querySelectorAll(FORM_CONTROL_SELECTOR).forEach((el) => el.remove());
477
+ return htmlParts.length > 0 ? `## Form Fields (HTML)
478
+ ${htmlParts.join("\n")}` : "";
479
+ }
480
+ function serializeFormControlHtml(control) {
481
+ const clone = control.cloneNode(true);
482
+ clone.querySelectorAll(FORM_HTML_STRIP_SELECTOR).forEach((el) => el.remove());
483
+ syncLiveValuesToClone(control, clone);
484
+ redactSensitiveInClone(clone);
485
+ stripPresentationAttributes(clone);
486
+ unwrapNoiseDivs(clone);
487
+ const html = clone.outerHTML.replace(/\s+/g, " ").trim();
488
+ console.debug("[DOM Forms] serializeFormControlHtml result:", {
489
+ inputTag: control.tagName,
490
+ inputClass: control.className?.slice(0, 80),
491
+ outputLength: html.length
492
+ });
493
+ return html.length > 0 ? html : "";
494
+ }
495
+ function syncLiveValuesToClone(liveRoot, cloneRoot) {
496
+ const liveInputs = liveRoot.querySelectorAll("input, textarea, select");
497
+ const cloneInputs = cloneRoot.querySelectorAll("input, textarea, select");
498
+ liveInputs.forEach((liveEl, i) => {
499
+ const cloneEl = cloneInputs[i];
500
+ if (!cloneEl) return;
501
+ if (cloneEl instanceof HTMLSelectElement) {
502
+ cloneEl.value = liveEl.value;
503
+ } else if (cloneEl instanceof HTMLInputElement && (cloneEl.type === "checkbox" || cloneEl.type === "radio")) {
504
+ cloneEl.checked = liveEl.checked;
505
+ if (cloneEl.checked) {
506
+ cloneEl.setAttribute("checked", "");
507
+ } else {
508
+ cloneEl.removeAttribute("checked");
509
+ }
510
+ } else {
511
+ const liveValue = liveEl.value;
512
+ cloneEl.value = liveValue;
513
+ cloneEl.setAttribute("value", liveValue);
514
+ }
515
+ });
516
+ }
517
+ function redactSensitiveInClone(root) {
518
+ root.querySelectorAll("input, textarea, select").forEach((el) => {
519
+ if (isSensitiveElement(el, document)) {
520
+ el.value = SENSITIVE_VALUE;
521
+ el.setAttribute("value", SENSITIVE_VALUE);
522
+ if (el.type === "checkbox") {
523
+ el.checked = false;
524
+ el.removeAttribute("checked");
525
+ }
526
+ }
527
+ });
528
+ }
529
+ function stripPresentationAttributes(root) {
530
+ root.removeAttribute("class");
531
+ root.removeAttribute("style");
532
+ root.querySelectorAll("*").forEach((el) => {
533
+ el.removeAttribute("class");
534
+ el.removeAttribute("style");
535
+ el.removeAttribute("data-testid");
536
+ });
537
+ }
538
+ function unwrapNoiseDivs(root) {
539
+ const isSemanticTag = (tag) => !["DIV", "SPAN"].includes(tag);
540
+ const hasSemanticAttrs = (el) => el.hasAttribute("id") || el.hasAttribute("role") || el.hasAttribute("aria-label") || el.hasAttribute("aria-describedby") || el.hasAttribute("for") || el.hasAttribute("novalidate");
541
+ let changed = true;
542
+ while (changed) {
543
+ changed = false;
544
+ const wrappers = root.querySelectorAll("div, span");
545
+ for (const el of Array.from(wrappers)) {
546
+ if (isSemanticTag(el.tagName)) continue;
547
+ if (hasSemanticAttrs(el)) continue;
548
+ if (el === root) continue;
549
+ const parent = el.parentNode;
550
+ if (!parent) continue;
551
+ while (el.firstChild) {
552
+ parent.insertBefore(el.firstChild, el);
553
+ }
554
+ parent.removeChild(el);
555
+ changed = true;
556
+ }
557
+ }
558
+ }
559
+ function extractSearchInputs() {
560
+ const searchInputs = document.querySelectorAll(SEARCH_INPUT_SELECTOR);
561
+ if (searchInputs.length === 0) return "";
562
+ const lines = ["## Search"];
563
+ const seen = /* @__PURE__ */ new Set();
564
+ searchInputs.forEach((el) => {
565
+ const input = el;
566
+ if (input.type === "hidden") return;
567
+ const label = input.getAttribute("placeholder") || input.getAttribute("aria-label") || input.closest("[aria-label]")?.getAttribute("aria-label") || "Search";
568
+ const value = isSensitiveElement(input, document) ? SENSITIVE_VALUE : input.value;
569
+ const key = `${label}:${value}`;
570
+ if (!seen.has(key)) {
571
+ seen.add(key);
572
+ lines.push(`- ${label}: ${value || "(empty)"}`);
573
+ }
574
+ });
575
+ return lines.length > 1 ? lines.join("\n") : "";
576
+ }
577
+ function extractFilterSections() {
578
+ const lines = ["## Filters"];
579
+ const filterNavs = document.querySelectorAll(FILTER_NAV_SELECTOR);
580
+ filterNavs.forEach((nav) => {
581
+ const heading = nav.closest(ACCORDION_ROOT_SELECTOR)?.previousElementSibling?.textContent?.trim() || nav.closest(ACCORDION_DETAILS_SELECTOR)?.closest(ACCORDION_ROOT_SELECTOR)?.querySelector(ACCORDION_SUMMARY_CONTENT_SELECTOR)?.textContent?.trim();
582
+ const groupLabel = heading || nav.closest(FILTER_BOX_SELECTOR)?.querySelector("h2")?.textContent?.trim();
583
+ const selected = nav.querySelector(SELECTED_ITEM_SELECTOR);
584
+ if (selected) {
585
+ const primary = selected.querySelector(LIST_ITEM_TEXT_PRIMARY_SELECTOR)?.textContent?.trim();
586
+ const secondary = selected.querySelector(LIST_ITEM_TEXT_SECONDARY_SELECTOR)?.textContent?.trim();
587
+ const text = secondary ? `${primary} (${secondary})` : primary;
588
+ if (groupLabel && text) {
589
+ lines.push(`- ${groupLabel}: ${text}`);
590
+ }
591
+ }
592
+ });
593
+ const menus = document.querySelectorAll(MENU_SELECTOR);
594
+ menus.forEach((menu) => {
595
+ const groupLabel = menu.getAttribute("aria-label") || menu.closest(CARD_ROOT_SELECTOR)?.previousElementSibling?.textContent?.trim();
596
+ const selected = menu.querySelector(SELECTED_ITEM_SELECTOR);
597
+ if (selected) {
598
+ const selectedText = selected.querySelector(`p, ${LIST_ITEM_TEXT_ROOT_SELECTOR}`)?.textContent?.trim();
599
+ if (groupLabel && selectedText) {
600
+ lines.push(`- ${groupLabel}: ${selectedText}`);
601
+ }
602
+ }
603
+ });
604
+ const filterContainers = document.querySelectorAll(FILTER_CONTAINER_SELECTOR);
605
+ filterContainers.forEach((container) => {
606
+ const resolved = resolveFilterControl(container);
607
+ if (resolved && resolved.label) {
608
+ lines.push(`- ${resolved.label}: ${resolved.value || "(empty)"}`);
609
+ }
610
+ });
611
+ return lines.length > 1 ? lines.join("\n") : "";
612
+ }
613
+ function resolveFilterControl(container) {
614
+ const labelEl = container.querySelector(`label, ${FORM_LABEL_SELECTOR}`);
615
+ let label = labelEl?.textContent?.trim() || container.getAttribute("aria-label") || "";
616
+ const selectDisplay = container.querySelector(SELECT_DISPLAY_SELECTOR);
617
+ if (selectDisplay) {
618
+ if (!label) {
619
+ label = container.querySelector("[aria-label]")?.getAttribute("aria-label") || "";
620
+ }
621
+ return { label, value: selectDisplay.textContent?.trim() || "" };
622
+ }
623
+ const chips = container.querySelectorAll(CHIP_LABEL_SELECTOR);
624
+ if (chips.length > 0) {
625
+ const chipValues = Array.from(chips).map((c) => c.textContent?.trim()).filter(Boolean);
626
+ return { label, value: chipValues.join(", ") };
627
+ }
628
+ const checkboxes = container.querySelectorAll('input[type="checkbox"]');
629
+ if (checkboxes.length > 0) {
630
+ const checked = [];
631
+ checkboxes.forEach((cb) => {
632
+ const input2 = cb;
633
+ if (input2.checked) {
634
+ const cbLabel = cb.closest("label")?.querySelector(FORM_CONTROL_LABEL_SELECTOR)?.textContent?.trim() || input2.value;
635
+ checked.push(cbLabel);
636
+ }
637
+ });
638
+ return { label, value: checked.join(", ") };
639
+ }
640
+ const input = container.querySelector(
641
+ 'input:not([type="checkbox"]):not([type="radio"]):not([aria-hidden="true"]):not([placeholder*="earch" i]), textarea'
642
+ );
643
+ if (input) {
644
+ if (!label) {
645
+ label = input.getAttribute("placeholder") || "";
646
+ }
647
+ const value = isSensitiveElement(input, document) ? SENSITIVE_VALUE : input.value || "";
648
+ return { label, value };
649
+ }
650
+ return null;
651
+ }
652
+ function extractTables(root) {
653
+ const tables = root.querySelectorAll("table");
654
+ if (tables.length === 0) return "";
655
+ const output = ["## Tables"];
656
+ let tableCount = 0;
657
+ tables.forEach((table) => {
658
+ if (tableCount >= MAX_TABLES) {
659
+ table.remove();
660
+ return;
661
+ }
662
+ table.querySelectorAll("tfoot").forEach((el) => el.remove());
663
+ table.querySelectorAll('[class*="TablePagination"]').forEach((el) => el.remove());
664
+ const rows = table.querySelectorAll("tr");
665
+ const tableLines = [];
666
+ let rowCount = 0;
667
+ rows.forEach((row) => {
668
+ if (rowCount >= MAX_TABLE_ROWS) return;
669
+ if (!row.querySelector("th, td") || row.children.length === 0) return;
670
+ const cells = row.querySelectorAll("th, td");
671
+ const cellTexts = Array.from(cells).map(
672
+ (cell) => collapseWhitespace(cell.textContent || "")
673
+ );
674
+ if (cellTexts.some(Boolean)) {
675
+ tableLines.push(`| ${cellTexts.join(" | ")} |`);
676
+ }
677
+ rowCount++;
678
+ });
679
+ if (tableLines.length > 0) {
680
+ output.push(tableLines.join("\n"));
681
+ }
682
+ table.remove();
683
+ tableCount++;
684
+ });
685
+ return output.length > 1 ? output.join("\n") : "";
686
+ }
687
+ function extractDescriptionLists(root) {
688
+ const dls = root.querySelectorAll("dl");
689
+ if (dls.length === 0) return "";
690
+ const lines = ["## Details"];
691
+ dls.forEach((dl) => {
692
+ const terms = dl.querySelectorAll("dt");
693
+ terms.forEach((dt) => {
694
+ const key = collapseWhitespace(dt.textContent || "");
695
+ const dd = dt.nextElementSibling;
696
+ const val = dd?.tagName === "DD" ? collapseWhitespace(dd.textContent || "") : "";
697
+ if (key) lines.push(`- ${key}: ${val}`);
698
+ });
699
+ dl.remove();
700
+ });
701
+ return lines.length > 1 ? lines.join("\n") : "";
702
+ }
703
+ function extractEmptyState(root) {
704
+ const emptyState = root.querySelector(EMPTY_STATE_SELECTOR);
705
+ if (!emptyState) return "";
706
+ const title = emptyState.querySelector("h5")?.textContent?.trim();
707
+ const desc = emptyState.querySelector(EMPTY_STATE_BODY_SELECTOR)?.textContent?.trim();
708
+ const lines = ["## Empty State"];
709
+ if (title) lines.push(`Title: ${title}`);
710
+ if (desc) lines.push(desc);
711
+ emptyState.remove();
712
+ return lines.length > 1 ? lines.join("\n") : "";
713
+ }
714
+ function extractPagination(root) {
715
+ const paginations = root.querySelectorAll(PAGINATION_ROOT_SELECTOR);
716
+ if (paginations.length === 0) return "";
717
+ const lines = [];
718
+ paginations.forEach((pg) => {
719
+ const hasActions = pg.querySelector(PAGINATION_ACTIONS_SELECTOR);
720
+ if (hasActions) {
721
+ const text = collapseWhitespace(pg.textContent || "");
722
+ if (text) lines.push(`Pagination: ${text}`);
723
+ }
724
+ pg.remove();
725
+ });
726
+ return lines.length > 0 ? lines.join("\n") : "";
727
+ }
728
+ function extractBodyText(root, budget) {
729
+ if (budget <= 0) return "";
730
+ const preBlocks = root.querySelectorAll("pre");
731
+ const preTexts = [];
732
+ preBlocks.forEach((pre) => {
733
+ const text = pre.textContent || "";
734
+ if (text.trim()) {
735
+ preTexts.push(text.slice(0, 500));
736
+ }
737
+ pre.remove();
738
+ });
739
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
740
+ const lines = ["## Content"];
741
+ let length = lines[0].length;
742
+ const seen = /* @__PURE__ */ new Set();
743
+ for (const preText of preTexts) {
744
+ const block = `\`\`\`
745
+ ${preText}
746
+ \`\`\``;
747
+ const blockLength = block.length + 1;
748
+ if (length + blockLength > budget) break;
749
+ lines.push(block);
750
+ length += blockLength;
751
+ }
752
+ let node = walker.nextNode();
753
+ while (node) {
754
+ const text = collapseWhitespace(node.textContent || "");
755
+ if (text && text.length > 1 && !seen.has(text)) {
756
+ seen.add(text);
757
+ const lineLength = text.length + 1;
758
+ if (length + lineLength > budget) {
759
+ break;
760
+ }
761
+ lines.push(text);
762
+ length += lineLength;
763
+ }
764
+ node = walker.nextNode();
765
+ }
766
+ return lines.length > 1 ? lines.join("\n") : "";
767
+ }
768
+ function extractShadowDomContent() {
769
+ const shadowHosts = document.querySelectorAll(SHADOW_HOST_SELECTOR);
770
+ if (shadowHosts.length === 0) return "";
771
+ const lines = ["## Documentation"];
772
+ shadowHosts.forEach((host) => {
773
+ const root = host.shadowRoot;
774
+ if (!root) return;
775
+ const container = root.querySelector("article.md-content__inner") || root.querySelector(".md-content__inner") || root.querySelector(".md-typeset") || root.querySelector(".md-content") || root.querySelector("main");
776
+ if (!container) return;
777
+ container.querySelectorAll(SHADOW_NOISE_SELECTOR).forEach((el) => el.remove());
778
+ const headings = container.querySelectorAll("h1, h2, h3, h4");
779
+ if (headings.length > 0) {
780
+ headings.forEach((h) => {
781
+ const level = parseInt(h.tagName[1], 10);
782
+ const indent = " ".repeat(level - 1);
783
+ const text = h.textContent?.trim().replace(/¶/g, "");
784
+ if (text) lines.push(`${indent}- ${text}`);
785
+ });
786
+ lines.push("");
787
+ }
788
+ container.querySelectorAll("p").forEach((p) => {
789
+ if (p.closest(".md-nav, .md-sidebar, .md-footer")) return;
790
+ const text = collapseWhitespace(p.textContent || "").replace(/¶/g, "");
791
+ if (text && text.length > 2) lines.push(text);
792
+ });
793
+ container.querySelectorAll("ul, ol").forEach((list) => {
794
+ if (list.closest(".md-nav, .md-sidebar, .md-footer")) return;
795
+ list.querySelectorAll(":scope > li").forEach((li) => {
796
+ const text = collapseWhitespace(li.textContent || "").replace(/¶/g, "");
797
+ if (text && text.length > 2) lines.push(`- ${text}`);
798
+ });
799
+ });
800
+ container.querySelectorAll("pre").forEach((pre) => {
801
+ const code = pre.textContent?.trim();
802
+ if (code) {
803
+ lines.push(`\`\`\`
804
+ ${code.slice(0, 500)}
805
+ \`\`\``);
806
+ }
807
+ });
808
+ });
809
+ return lines.length > 1 ? lines.join("\n") : "";
810
+ }
811
+ function collapseWhitespace(text) {
812
+ return text.replace(/\s+/g, " ").trim();
813
+ }
814
+
815
+ export { extractPageContext };
816
+ //# sourceMappingURL=dom-extractor.esm.js.map