@iblai/iblai-js 2.5.7 → 2.5.9

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.
@@ -1612,7 +1612,10 @@ async function openAddMemoryDialog(page) {
1612
1612
  const addMemoryButton = page.getByRole('button', { name: /Add Memory/i });
1613
1613
  await expect(addMemoryButton).toBeVisible({ timeout: 10000 });
1614
1614
  await addMemoryButton.click();
1615
- const dialog = page.getByRole('dialog').filter({ hasText: 'Add Memory' });
1615
+ // Accessible-name match (Radix wires DialogTitle aria-labelledby), NOT a
1616
+ // `hasText` filter: the profile modal is itself a dialog containing the
1617
+ // "Add Memory" *button* text, so a text filter matches both dialogs.
1618
+ const dialog = page.getByRole('dialog', { name: 'Add Memory', exact: true });
1616
1619
  await expect(dialog).toBeVisible({ timeout: 5000 });
1617
1620
  return dialog;
1618
1621
  }
@@ -1664,7 +1667,7 @@ async function deleteMemoryRow(page, memoryRow) {
1664
1667
  await expect(deleteItem).toBeVisible({ timeout: 5000 });
1665
1668
  await deleteItem.click();
1666
1669
  // Deleting asks for confirmation; the dialog stacks on top of everything.
1667
- const confirmDialog = page.getByRole('dialog').filter({ hasText: 'Delete Memory' }).last();
1670
+ const confirmDialog = page.getByRole('dialog', { name: 'Delete Memory', exact: true }).last();
1668
1671
  await expect(confirmDialog).toBeVisible({ timeout: 5000 });
1669
1672
  await confirmDialog.getByRole('button', { name: 'Delete', exact: true }).click();
1670
1673
  await expect(confirmDialog).toBeHidden({ timeout: 15000 });
@@ -1904,13 +1907,25 @@ async function closeUserMemoriesPopup(page) {
1904
1907
  await expect(popup).toBeHidden({ timeout: UI_TIMEOUT$2 });
1905
1908
  }
1906
1909
  /**
1907
- * The innermost open dialog whose text matches `title`. Stacked Radix
1908
- * dialogs portal to the end of `<body>` in mount order, so `.last()` is the
1909
- * one on top — required here because the add/edit/delete dialogs open above
1910
- * the popup, which itself sits above the tenant settings dialog.
1910
+ * The innermost open dialog whose ACCESSIBLE NAME matches `title`. Stacked
1911
+ * Radix dialogs portal to the end of `<body>` in mount order, so `.last()`
1912
+ * is the one on top — required here because the add/edit/delete dialogs open
1913
+ * above the popup, which itself sits above the tenant settings dialog.
1914
+ *
1915
+ * Matches on the dialog's accessible name, NOT a `hasText` filter: the user
1916
+ * and agent memories popups both contain an "Add Memory" *button*, so a
1917
+ * `hasText` filter also matches the popup itself. That made the post-save
1918
+ * `toBeHidden` gate unsatisfiable — while the add dialog was open `.last()`
1919
+ * resolved to it, but the instant it unmounted the same locator re-resolved
1920
+ * to the still-open popup underneath and "waited" on the wrong dialog for
1921
+ * the full timeout. Radix `DialogContent` wires `aria-labelledby` to its
1922
+ * `DialogTitle`, so each stacked dialog's accessible name is exactly its
1923
+ * title ("Add Memory" / "Edit Memory" / "Delete Memory"), while the popups'
1924
+ * names ("Global Memories — …") never equal one — unambiguous, and the
1925
+ * locator resolves to nothing (= hidden) once the dialog closes.
1911
1926
  */
1912
1927
  function topDialogByTitle(page, title) {
1913
- return page.getByRole('dialog').filter({ hasText: title }).last();
1928
+ return page.getByRole('dialog', { name: title, exact: true }).last();
1914
1929
  }
1915
1930
  /** Open a memory row's three-dots menu and click one of its actions. */
1916
1931
  async function clickMemoryRowAction(page, row, action) {
@@ -2001,20 +2016,47 @@ async function toggleUserMemoryAdminSetting(page, popup, setting) {
2001
2016
  /**
2002
2017
  * Filter the agents table to one agent via the autocomplete: types the name,
2003
2018
  * clicks the matching option, and gates on the selected chip rendering.
2019
+ *
2020
+ * Retries with progressively shorter PREFIXES of the name. The options come
2021
+ * from a debounced server-side mentors search whose response RTK Query
2022
+ * caches per search term — so when a just-created mentor hasn't reached the
2023
+ * search backend yet, the first (empty) response keeps being served from
2024
+ * cache for as long as the typed term stays the same, and waiting on the
2025
+ * DOM alone can never recover. Each shorter prefix is a DISTINCT term that
2026
+ * forces a fresh fetch, and still matches the mentor server-side.
2004
2027
  */
2005
2028
  async function filterAgentMemories(page, agentName) {
2006
2029
  const section = memoryAdminAgentSection(page);
2007
2030
  const input = section.getByTestId('agent-memories-filter-input');
2008
2031
  await expect(input).toBeVisible({ timeout: UI_TIMEOUT$2 });
2009
- await input.fill(agentName);
2010
2032
  const option = section
2011
2033
  .getByTestId('agent-memories-filter-results')
2012
2034
  .getByRole('button', { name: agentName, exact: true });
2013
- await expect(option).toBeVisible({ timeout: MUTATION_TIMEOUT$2 });
2035
+ const maxAttempts = 6;
2036
+ for (let attempt = 0;; attempt++) {
2037
+ // Attempt 0 types the full name; each retry trims one more trailing
2038
+ // character (never below the autocomplete's 2-char minimum).
2039
+ const term = agentName.slice(0, Math.max(2, agentName.length - attempt));
2040
+ await input.fill(term);
2041
+ try {
2042
+ await expect(option).toBeVisible({ timeout: MUTATION_TIMEOUT$2 });
2043
+ break;
2044
+ }
2045
+ catch (error) {
2046
+ if (attempt >= maxAttempts - 1)
2047
+ throw error;
2048
+ }
2049
+ }
2014
2050
  await option.click();
2051
+ // Selecting must both render the selected chip AND close the results
2052
+ // dropdown — the open panel overlays the agents table (absolute, z-50),
2053
+ // so a caller's next row interaction would hit the dropdown instead.
2015
2054
  await expect(section.getByTestId('agent-memories-filter-selected')).toBeVisible({
2016
2055
  timeout: UI_TIMEOUT$2,
2017
2056
  });
2057
+ await expect(section.getByTestId('agent-memories-filter-results')).toBeHidden({
2058
+ timeout: UI_TIMEOUT$2,
2059
+ });
2018
2060
  logger.info(`Filtered agent memories to "${agentName}"`);
2019
2061
  }
2020
2062
  /** Clear the agents autocomplete filter (back to the full agents list). */
@@ -2062,13 +2104,27 @@ async function addAgentMemoryFromPopup(page, popup, content, categoryName) {
2062
2104
  await addButton.click();
2063
2105
  const dialog = topDialogByTitle(page, MEMORY_ADMIN_LABELS.dialogs.add);
2064
2106
  await expect(dialog).toBeVisible({ timeout: UI_TIMEOUT$2 });
2107
+ // ALWAYS pick a category — the named one when given, else the first
2108
+ // available option. The dialog's Save enables without one, but the SDK
2109
+ // then falls back to the list's current filter ('All' → the hardcoded
2110
+ // 'general' slug) and the backend 404s with "Category not found or
2111
+ // inactive" for any mentor without a 'general' category (the default
2112
+ // category set has none) — leaving the dialog open with only an error
2113
+ // toast to show for it.
2114
+ await dialog.getByRole('combobox').click();
2115
+ // Radix Select portals its listbox to <body>; one is open at a time.
2116
+ const options = page.getByRole('option');
2117
+ await expect(options.first()).toBeVisible({ timeout: UI_TIMEOUT$2 });
2065
2118
  if (categoryName) {
2066
- await dialog.getByRole('combobox').click();
2067
- // Radix Select portals its listbox to <body>; one is open at a time.
2068
2119
  const option = page.getByRole('option', { name: categoryName, exact: true });
2069
2120
  await expect(option).toBeVisible({ timeout: UI_TIMEOUT$2 });
2070
2121
  await option.click();
2071
2122
  }
2123
+ else {
2124
+ await options.first().click();
2125
+ }
2126
+ // Picking closes the listbox; confirm before touching anything below it.
2127
+ await expect(options).toHaveCount(0, { timeout: 5000 });
2072
2128
  await dialog.getByRole('textbox').fill(content);
2073
2129
  const saveButton = dialog.getByRole('button', { name: 'Save', exact: true });
2074
2130
  await expect(saveButton).toBeEnabled({ timeout: UI_TIMEOUT$2 });
@@ -3802,7 +3858,7 @@ const PRIVACY_LABELS = {
3802
3858
  * reach DOM that Radix renders outside the dialog subtree (popovers,
3803
3859
  * select options, etc.).
3804
3860
  */
3805
- function asPage$7(scope) {
3861
+ function asPage$8(scope) {
3806
3862
  return 'page' in scope ? scope.page() : scope;
3807
3863
  }
3808
3864
  /**
@@ -3863,7 +3919,7 @@ async function selectPrivacyAction(scope, action) {
3863
3919
  await trigger.click();
3864
3920
  // Radix Select renders options in a portal at the document root, so we
3865
3921
  // always look them up on the Page — never on the dialog Locator.
3866
- const option = asPage$7(scope).getByRole('option', {
3922
+ const option = asPage$8(scope).getByRole('option', {
3867
3923
  name: PRIVACY_LABELS.actionOptions[action],
3868
3924
  });
3869
3925
  await expect(option).toBeVisible({ timeout: 5000 });
@@ -3975,7 +4031,7 @@ const CHAT_PRIVACY_LABELS = {
3975
4031
  rowLabel: 'Allow users to control chat privacy',
3976
4032
  },
3977
4033
  };
3978
- function asPage$6(scope) {
4034
+ function asPage$7(scope) {
3979
4035
  return 'page' in scope ? scope.page() : scope;
3980
4036
  }
3981
4037
  // ──────────────────────────────────────────────────────────────────────
@@ -4047,7 +4103,7 @@ async function clickChatPrivacyToggle(scope) {
4047
4103
  // ── Mid-session confirm dialog ────────────────────────────────────────
4048
4104
  /** Locator for the AlertDialog content that the mid-session enable opens. */
4049
4105
  function getChatPrivacyConfirmDialog(scope) {
4050
- return asPage$6(scope).getByTestId('chat-privacy-confirm-dialog');
4106
+ return asPage$7(scope).getByTestId('chat-privacy-confirm-dialog');
4051
4107
  }
4052
4108
  async function expectChatPrivacyConfirmDialogOpen(scope, open) {
4053
4109
  if (open) {
@@ -4066,7 +4122,7 @@ async function expectChatPrivacyConfirmDialogOpen(scope, open) {
4066
4122
  */
4067
4123
  async function confirmEnableChatPrivacyMidSession(scope) {
4068
4124
  await clickChatPrivacyToggle(scope);
4069
- const page = asPage$6(scope);
4125
+ const page = asPage$7(scope);
4070
4126
  await expectChatPrivacyConfirmDialogOpen(page, true);
4071
4127
  const action = page.getByTestId('chat-privacy-confirm-action');
4072
4128
  await expect(action).toBeVisible({ timeout: 10000 });
@@ -4077,7 +4133,7 @@ async function confirmEnableChatPrivacyMidSession(scope) {
4077
4133
  }
4078
4134
  /** Cancel the confirm dialog without enabling. */
4079
4135
  async function cancelEnableChatPrivacyMidSession(scope) {
4080
- const page = asPage$6(scope);
4136
+ const page = asPage$7(scope);
4081
4137
  const cancel = page.getByTestId('chat-privacy-confirm-cancel');
4082
4138
  await expect(cancel).toBeVisible({ timeout: 10000 });
4083
4139
  await cancel.click();
@@ -4272,7 +4328,7 @@ const VOICE_LABELS = {
4272
4328
  * reach DOM that Radix renders outside the dialog subtree (popovers,
4273
4329
  * select options, etc.).
4274
4330
  */
4275
- function asPage$5(scope) {
4331
+ function asPage$6(scope) {
4276
4332
  return 'page' in scope ? scope.page() : scope;
4277
4333
  }
4278
4334
  // ─── Tab navigation ──────────────────────────────────────────────────────
@@ -4354,7 +4410,7 @@ async function openMentorVoicePicker(scope) {
4354
4410
  const openBtn = scope.getByTestId('mentor-voice-trigger-open');
4355
4411
  await expect(openBtn).toBeVisible({ timeout: 10000 });
4356
4412
  await openBtn.click();
4357
- await expect(asPage$5(scope).getByTestId('voice-picker-modal')).toBeVisible({
4413
+ await expect(asPage$6(scope).getByTestId('voice-picker-modal')).toBeVisible({
4358
4414
  timeout: 10000,
4359
4415
  });
4360
4416
  }
@@ -4366,7 +4422,7 @@ async function openCallConfigVoicePicker(scope) {
4366
4422
  const openBtn = scope.getByTestId('call-config-voice-trigger-open');
4367
4423
  await expect(openBtn).toBeVisible({ timeout: 10000 });
4368
4424
  await openBtn.click();
4369
- await expect(asPage$5(scope).getByTestId('voice-picker-modal')).toBeVisible({
4425
+ await expect(asPage$6(scope).getByTestId('voice-picker-modal')).toBeVisible({
4370
4426
  timeout: 10000,
4371
4427
  });
4372
4428
  }
@@ -4458,7 +4514,7 @@ async function openVoiceInstructionsEditor(scope) {
4458
4514
  const btn = scope.getByRole('button', { name: `Edit ${VOICE_LABELS.voiceInstructions.label}` });
4459
4515
  await expect(btn).toBeVisible({ timeout: 10000 });
4460
4516
  await btn.click();
4461
- await expect(asPage$5(scope).getByText(`Edit ${VOICE_LABELS.voiceInstructions.label}`)).toBeVisible({ timeout: 10000 });
4517
+ await expect(asPage$6(scope).getByText(`Edit ${VOICE_LABELS.voiceInstructions.label}`)).toBeVisible({ timeout: 10000 });
4462
4518
  logger.info('Opened voice-instructions editor');
4463
4519
  }
4464
4520
  /**
@@ -4469,7 +4525,7 @@ async function openVoiceInstructionsEditor(scope) {
4469
4525
  */
4470
4526
  async function setVoiceInstructions(scope, text) {
4471
4527
  await openVoiceInstructionsEditor(scope);
4472
- const page = asPage$5(scope);
4528
+ const page = asPage$6(scope);
4473
4529
  const editor = page.getByRole('dialog').locator('[contenteditable="true"]').first();
4474
4530
  await expect(editor).toBeVisible({ timeout: 10000 });
4475
4531
  await editor.click();
@@ -4535,7 +4591,7 @@ async function selectCallMode(scope, mode) {
4535
4591
  const trigger = scope.getByRole('combobox', { name: VOICE_LABELS.callConfigFields.mode });
4536
4592
  await expect(trigger).toBeVisible({ timeout: 10000 });
4537
4593
  await trigger.click();
4538
- const option = asPage$5(scope).getByRole('option', { name: VOICE_LABELS.modeOptions[mode] });
4594
+ const option = asPage$6(scope).getByRole('option', { name: VOICE_LABELS.modeOptions[mode] });
4539
4595
  await expect(option).toBeVisible({ timeout: 5000 });
4540
4596
  await option.click();
4541
4597
  await expect(trigger).toHaveText(new RegExp(VOICE_LABELS.modeOptions[mode]));
@@ -4551,7 +4607,7 @@ async function selectFromCombobox(scope, triggerName, optionName) {
4551
4607
  const trigger = scope.getByRole('combobox', { name: triggerName });
4552
4608
  await expect(trigger).toBeVisible({ timeout: 10000 });
4553
4609
  await trigger.click();
4554
- const option = asPage$5(scope).getByRole('option', { name: optionName });
4610
+ const option = asPage$6(scope).getByRole('option', { name: optionName });
4555
4611
  await expect(option).toBeVisible({ timeout: 5000 });
4556
4612
  await option.click();
4557
4613
  }
@@ -4648,7 +4704,7 @@ const SCREENSHARE_LABELS = {
4648
4704
  },
4649
4705
  saveButton: 'Save',
4650
4706
  };
4651
- function asPage$4(scope) {
4707
+ function asPage$5(scope) {
4652
4708
  return 'page' in scope ? scope.page() : scope;
4653
4709
  }
4654
4710
  /**
@@ -4688,7 +4744,7 @@ async function openScreenSharePromptEditor(scope, field) {
4688
4744
  const btn = scope.getByRole('button', { name: `Edit ${label}` });
4689
4745
  await expect(btn).toBeVisible({ timeout: 10000 });
4690
4746
  await btn.click();
4691
- await expect(asPage$4(scope).getByText(`Edit ${label}`)).toBeVisible({ timeout: 10000 });
4747
+ await expect(asPage$5(scope).getByText(`Edit ${label}`)).toBeVisible({ timeout: 10000 });
4692
4748
  logger.info(`Opened screen-share ${field} editor`);
4693
4749
  }
4694
4750
  /**
@@ -4698,7 +4754,7 @@ async function openScreenSharePromptEditor(scope, field) {
4698
4754
  */
4699
4755
  async function setScreenSharePrompt(scope, field, text) {
4700
4756
  await openScreenSharePromptEditor(scope, field);
4701
- const page = asPage$4(scope);
4757
+ const page = asPage$5(scope);
4702
4758
  const editor = page.getByRole('dialog').locator('[contenteditable="true"]').first();
4703
4759
  await expect(editor).toBeVisible({ timeout: 10000 });
4704
4760
  await editor.click();
@@ -6084,7 +6140,7 @@ const TASKS_LABELS = {
6084
6140
  * reach DOM that Radix renders outside the dialog subtree (popovers,
6085
6141
  * select options, the schedule / delete / log-details dialogs, etc.).
6086
6142
  */
6087
- function asPage$3(scope) {
6143
+ function asPage$4(scope) {
6088
6144
  return 'page' in scope ? scope.page() : scope;
6089
6145
  }
6090
6146
  // ── Tab navigation ─────────────────────────────────────────────────────
@@ -6194,7 +6250,7 @@ async function searchTasks(scope, query) {
6194
6250
  * shares an accessible name with the dialog's submit button.
6195
6251
  */
6196
6252
  function getScheduleTaskDialog(scope) {
6197
- return asPage$3(scope).getByRole('dialog', { name: TASKS_LABELS.scheduleDialog.dialogName });
6253
+ return asPage$4(scope).getByRole('dialog', { name: TASKS_LABELS.scheduleDialog.dialogName });
6198
6254
  }
6199
6255
  /** Open the Schedule Task dialog and wait for it to be interactive. */
6200
6256
  async function openScheduleTaskDialog(scope) {
@@ -6213,7 +6269,7 @@ async function openScheduleTaskDialog(scope) {
6213
6269
  */
6214
6270
  async function scheduleTask(scope, opts) {
6215
6271
  await openScheduleTaskDialog(scope);
6216
- const page = asPage$3(scope);
6272
+ const page = asPage$4(scope);
6217
6273
  // Scope every query to the dialog: the toolbar "Schedule Task" button shares
6218
6274
  // an accessible name with the dialog's submit button, so an unscoped
6219
6275
  // getByRole('button', { name: 'Schedule Task' }) matches two elements.
@@ -6248,13 +6304,13 @@ async function scheduleTask(scope, opts) {
6248
6304
  }
6249
6305
  /** Asserts the in-dialog past-time error is currently shown. */
6250
6306
  async function expectScheduleStartTimeInPastError(scope) {
6251
- await expect(asPage$3(scope).getByText(TASKS_LABELS.scheduleDialog.startTimeInPast)).toBeVisible({
6307
+ await expect(asPage$4(scope).getByText(TASKS_LABELS.scheduleDialog.startTimeInPast)).toBeVisible({
6252
6308
  timeout: 5000,
6253
6309
  });
6254
6310
  }
6255
6311
  // ── Delete flow ────────────────────────────────────────────────────────
6256
6312
  function getDeleteTaskDialog(scope) {
6257
- return asPage$3(scope).locator(`[role="dialog"][aria-label="${TASKS_LABELS.deleteDialog.dialogName}"]`);
6313
+ return asPage$4(scope).locator(`[role="dialog"][aria-label="${TASKS_LABELS.deleteDialog.dialogName}"]`);
6258
6314
  }
6259
6315
  /**
6260
6316
  * Click the trash icon on a task row and confirm the delete in the
@@ -6275,7 +6331,7 @@ async function deleteTask(scope, taskName) {
6275
6331
  }
6276
6332
  // ── Logs panel + log details ───────────────────────────────────────────
6277
6333
  function getLogDetailsDialog(scope) {
6278
- return asPage$3(scope).locator(`[role="dialog"][aria-label="${TASKS_LABELS.logDetails.dialogName}"]`);
6334
+ return asPage$4(scope).locator(`[role="dialog"][aria-label="${TASKS_LABELS.logDetails.dialogName}"]`);
6279
6335
  }
6280
6336
  /**
6281
6337
  * Wait for the logs panel to finish loading and assert that the selected
@@ -6469,7 +6525,7 @@ const EVALS_LABELS = {
6469
6525
  * toasts) — those queries must run on the page, never on the tab pane or a
6470
6526
  * parent dialog.
6471
6527
  */
6472
- function asPage$2(scope) {
6528
+ function asPage$3(scope) {
6473
6529
  return 'page' in scope ? scope.page() : scope;
6474
6530
  }
6475
6531
  /** Escape a user-supplied string (run / benchmark names) for use in a RegExp. */
@@ -6478,7 +6534,7 @@ function escapeRegExp(value) {
6478
6534
  }
6479
6535
  /** Attribute-based dialog locator — immune to title renames and to Radix's `aria-labelledby` name precedence. */
6480
6536
  function dialogByName(scope, dialogName) {
6481
- return asPage$2(scope).locator(`[role="dialog"][aria-label="${dialogName}"]`);
6537
+ return asPage$3(scope).locator(`[role="dialog"][aria-label="${dialogName}"]`);
6482
6538
  }
6483
6539
  // ── Tab navigation ─────────────────────────────────────────────────────
6484
6540
  /**
@@ -6565,7 +6621,7 @@ async function expectNoBenchmarksNotice(scope) {
6565
6621
  function getRunRow(scope, runName) {
6566
6622
  return scope
6567
6623
  .getByRole('row')
6568
- .filter({ has: asPage$2(scope).getByRole('cell', { name: runName, exact: true }) });
6624
+ .filter({ has: asPage$3(scope).getByRole('cell', { name: runName, exact: true }) });
6569
6625
  }
6570
6626
  async function expectRunInTable(scope, runName) {
6571
6627
  await expect(getRunRow(scope, runName)).toBeVisible({ timeout: 15000 });
@@ -6592,7 +6648,7 @@ async function openRunActionsMenu(scope, runName) {
6592
6648
  await getRunRow(scope, runName)
6593
6649
  .getByRole('button', { name: `Actions for ${runName}`, exact: true })
6594
6650
  .click();
6595
- const menu = asPage$2(scope).getByRole('menu');
6651
+ const menu = asPage$3(scope).getByRole('menu');
6596
6652
  await expect(menu).toBeVisible({ timeout: 5000 });
6597
6653
  return menu;
6598
6654
  }
@@ -6629,7 +6685,7 @@ async function openNewReviewForRun(scope, runName) {
6629
6685
  * design (the item prevents default), so we close it with Escape.
6630
6686
  */
6631
6687
  async function checkRunStatus(scope, runName) {
6632
- const page = asPage$2(scope);
6688
+ const page = asPage$3(scope);
6633
6689
  const menu = await openRunActionsMenu(scope, runName);
6634
6690
  await menu.getByRole('menuitem', { name: EVALS_LABELS.actions.checkStatus }).click();
6635
6691
  const toasts = EVALS_LABELS.checkStatusToast;
@@ -6651,7 +6707,7 @@ async function checkRunStatus(scope, runName) {
6651
6707
  * suggested filename (`<benchmark>_<run>_results.csv`).
6652
6708
  */
6653
6709
  async function exportRunCsv(scope, runName) {
6654
- const page = asPage$2(scope);
6710
+ const page = asPage$3(scope);
6655
6711
  const menu = await openRunActionsMenu(scope, runName);
6656
6712
  const item = menu.getByRole('menuitem', { name: EVALS_LABELS.actions.exportCsv });
6657
6713
  await expect(item).toBeEnabled({ timeout: 5000 });
@@ -6747,7 +6803,7 @@ function getLlmPickerDialog(scope) {
6747
6803
  * title text since it has no aria-label). Both pickers close on selection.
6748
6804
  */
6749
6805
  async function selectJudgeLlm(scope, providerName, modelName) {
6750
- const page = asPage$2(scope);
6806
+ const page = asPage$3(scope);
6751
6807
  const judgeDialog = getLlmJudgeDialog(scope);
6752
6808
  await judgeDialog
6753
6809
  .getByRole('button', { name: EVALS_LABELS.judgeDialog.selectorAriaLabel })
@@ -6872,9 +6928,9 @@ async function removeTraceScore(scope, scoreName) {
6872
6928
  const dialog = getEvaluationDetailDialog(scope);
6873
6929
  const chip = dialog
6874
6930
  .locator('div')
6875
- .filter({ has: asPage$2(scope).getByText(scoreName, { exact: true }) })
6931
+ .filter({ has: asPage$3(scope).getByText(scoreName, { exact: true }) })
6876
6932
  .filter({
6877
- has: asPage$2(scope).getByRole('button', {
6933
+ has: asPage$3(scope).getByRole('button', {
6878
6934
  name: EVALS_LABELS.detailDialog.removeScoreAriaLabel,
6879
6935
  }),
6880
6936
  })
@@ -6914,7 +6970,7 @@ async function expandReview(scope, scoreName) {
6914
6970
  /** Close the detail dialog via Escape and wait for it to be gone. */
6915
6971
  async function closeEvaluationDetailDialog(scope) {
6916
6972
  const dialog = getEvaluationDetailDialog(scope);
6917
- await asPage$2(scope).keyboard.press('Escape');
6973
+ await asPage$3(scope).keyboard.press('Escape');
6918
6974
  await expect(dialog).toBeHidden({ timeout: 10000 });
6919
6975
  }
6920
6976
  // ── Manage benchmarks dialog (embedded tenant Benchmarks) ──────────────
@@ -7096,13 +7152,13 @@ async function deleteQaItem(scope, questionText) {
7096
7152
  /** Close the benchmark items dialog via Escape and wait for it to be gone. */
7097
7153
  async function closeBenchmarkItemsDialog(scope) {
7098
7154
  const dialog = getBenchmarkItemsDialog(scope);
7099
- await asPage$2(scope).keyboard.press('Escape');
7155
+ await asPage$3(scope).keyboard.press('Escape');
7100
7156
  await expect(dialog).toBeHidden({ timeout: 10000 });
7101
7157
  }
7102
7158
  /** Close the Manage benchmarks dialog via Escape and wait for it to be gone. */
7103
7159
  async function closeManageBenchmarksDialog(scope) {
7104
7160
  const dialog = getManageBenchmarksDialog(scope);
7105
- await asPage$2(scope).keyboard.press('Escape');
7161
+ await asPage$3(scope).keyboard.press('Escape');
7106
7162
  await expect(dialog).toBeHidden({ timeout: 10000 });
7107
7163
  }
7108
7164
 
@@ -7240,7 +7296,7 @@ const LTI_TEST_IDS = {
7240
7296
  * DOM that Radix renders in a portal outside the dialog subtree (dropdown
7241
7297
  * menus, select options).
7242
7298
  */
7243
- function asPage$1(scope) {
7299
+ function asPage$2(scope) {
7244
7300
  return 'page' in scope ? scope.page() : scope;
7245
7301
  }
7246
7302
  // ── Tab navigation ─────────────────────────────────────────────────────
@@ -7312,7 +7368,7 @@ function getLinkCopyTargetUriButton(scope) {
7312
7368
  return scope.getByRole('button', { name: 'Copy target link URI' });
7313
7369
  }
7314
7370
  function getLinkModal(scope) {
7315
- return asPage$1(scope).getByTestId(LTI_TEST_IDS.links.modal);
7371
+ return asPage$2(scope).getByTestId(LTI_TEST_IDS.links.modal);
7316
7372
  }
7317
7373
  function getLinkNameInput(scope) {
7318
7374
  return getLinkModal(scope).getByTestId(LTI_TEST_IDS.links.nameInput);
@@ -7406,7 +7462,7 @@ async function waitForLinkReady(scope, name, timeoutMs = 180000) {
7406
7462
  if (Date.now() >= deadline) {
7407
7463
  throw new Error(`Timed out waiting for LTI link to be ready: ${name} (last: ${status})`);
7408
7464
  }
7409
- await asPage$1(scope).waitForTimeout(5000);
7465
+ await asPage$2(scope).waitForTimeout(5000);
7410
7466
  await refreshLinks(scope);
7411
7467
  }
7412
7468
  logger.info(`LTI link ready: ${name}`);
@@ -7441,13 +7497,13 @@ function getKeyActionsTrigger(scope, name) {
7441
7497
  /** Open a key's three-dots menu and return the open menu (portal-rendered). */
7442
7498
  async function openKeyActionsMenu(scope, name) {
7443
7499
  await getKeyActionsTrigger(scope, name).click();
7444
- const menu = asPage$1(scope).getByRole('menu');
7500
+ const menu = asPage$2(scope).getByRole('menu');
7445
7501
  await expect(menu).toBeVisible({ timeout: 5000 });
7446
7502
  return menu;
7447
7503
  }
7448
7504
  // — Key: create —
7449
7505
  function getKeyCreateModal(scope) {
7450
- return asPage$1(scope).getByTestId(LTI_TEST_IDS.keys.createModal);
7506
+ return asPage$2(scope).getByTestId(LTI_TEST_IDS.keys.createModal);
7451
7507
  }
7452
7508
  function getKeyCreateNameInput(scope) {
7453
7509
  return getKeyCreateModal(scope).getByTestId(LTI_TEST_IDS.keys.createNameInput);
@@ -7467,7 +7523,7 @@ async function createKey(scope, name) {
7467
7523
  }
7468
7524
  // — Key: edit / detail —
7469
7525
  function getKeyDetailModal(scope) {
7470
- return asPage$1(scope).getByTestId(LTI_TEST_IDS.keys.detailModal);
7526
+ return asPage$2(scope).getByTestId(LTI_TEST_IDS.keys.detailModal);
7471
7527
  }
7472
7528
  function getKeyDetailNameInput(scope) {
7473
7529
  return getKeyDetailModal(scope).getByTestId(LTI_TEST_IDS.keys.detailNameInput);
@@ -7511,7 +7567,7 @@ async function closeKeyDetail(scope) {
7511
7567
  }
7512
7568
  // — Key: delete —
7513
7569
  function getKeyDeleteModal(scope) {
7514
- return asPage$1(scope).getByTestId(LTI_TEST_IDS.keys.deleteModal);
7570
+ return asPage$2(scope).getByTestId(LTI_TEST_IDS.keys.deleteModal);
7515
7571
  }
7516
7572
  /** Open the delete confirmation for a key via its actions menu → Delete. */
7517
7573
  async function openKeyDelete(scope, name) {
@@ -7542,7 +7598,7 @@ async function deleteKey(scope, name) {
7542
7598
  * delete-modal convention); the modal stays open so the user can cancel.
7543
7599
  */
7544
7600
  async function expectKeyDeleteError(scope, message) {
7545
- const page = asPage$1(scope);
7601
+ const page = asPage$2(scope);
7546
7602
  await expect(page.getByText(message, { exact: false }).first()).toBeVisible({ timeout: 15000 });
7547
7603
  await expect(getKeyDeleteModal(scope)).toBeVisible();
7548
7604
  }
@@ -7574,7 +7630,7 @@ function getToolEditButton(scope, name) {
7574
7630
  return scope.getByRole('button', { name: `Edit ${name}` });
7575
7631
  }
7576
7632
  function getToolModal(scope) {
7577
- return asPage$1(scope).getByTestId(LTI_TEST_IDS.tools.modal);
7633
+ return asPage$2(scope).getByTestId(LTI_TEST_IDS.tools.modal);
7578
7634
  }
7579
7635
  /** Field locators inside the (open) tool modal. */
7580
7636
  const toolFields = {
@@ -7607,7 +7663,7 @@ async function selectToolKeySetMode(scope, mode) {
7607
7663
  /** Pick a signing key by name from the Radix select in the open tool modal. */
7608
7664
  async function selectToolSigningKey(scope, name) {
7609
7665
  await getToolKeySelect(scope).click();
7610
- await asPage$1(scope).getByRole('option', { name }).click();
7666
+ await asPage$2(scope).getByRole('option', { name }).click();
7611
7667
  }
7612
7668
  /** Submit button inside the tool modal ("Create" or "Save"). */
7613
7669
  function getToolSubmitButton(scope) {
@@ -7784,7 +7840,7 @@ const SUPPORT_LABELS = {
7784
7840
  * reach DOM that Radix renders outside the dialog subtree (select option
7785
7841
  * lists, popover contents).
7786
7842
  */
7787
- function asPage(scope) {
7843
+ function asPage$1(scope) {
7788
7844
  return 'page' in scope ? scope.page() : scope;
7789
7845
  }
7790
7846
  // ── Dialog capture ─────────────────────────────────────────────────────
@@ -7973,7 +8029,7 @@ async function filterTicketsByStatus(dialog, status) {
7973
8029
  const label = status === 'all' ? SUPPORT_LABELS.filters.allStatuses : SUPPORT_LABELS.status[status];
7974
8030
  await getStatusFilter(dialog).click();
7975
8031
  // Radix renders the option list in a portal outside the dialog subtree.
7976
- await asPage(dialog).getByRole('option', { name: label, exact: true }).click();
8032
+ await asPage$1(dialog).getByRole('option', { name: label, exact: true }).click();
7977
8033
  logger.info(`Filtered tickets by status: ${label}`);
7978
8034
  }
7979
8035
  /** The "Search for User" combobox trigger (opens the requester popover). */
@@ -8054,7 +8110,7 @@ function getTicketDetail(dialog) {
8054
8110
  function getTicketDescription(dialog) {
8055
8111
  // On mobile the detail renders in a nested preview dialog instead of the
8056
8112
  // side pane; the testid is unique either way, so query from the page.
8057
- return asPage(dialog).getByTestId(SUPPORT_LABELS.testIds.ticketDescription).first();
8113
+ return asPage$1(dialog).getByTestId(SUPPORT_LABELS.testIds.ticketDescription).first();
8058
8114
  }
8059
8115
  /**
8060
8116
  * Open a ticket from the list and wait for its detail to render. Returns
@@ -8081,7 +8137,7 @@ async function setTicketStatus(dialog, status) {
8081
8137
  const detail = getTicketDetail(dialog);
8082
8138
  await detail.getByRole('combobox', { name: SUPPORT_LABELS.detail.statusLabel }).click();
8083
8139
  // Radix renders the option list in a portal outside the dialog subtree.
8084
- await asPage(dialog)
8140
+ await asPage$1(dialog)
8085
8141
  .getByRole('option', { name: SUPPORT_LABELS.status[status], exact: true })
8086
8142
  .click();
8087
8143
  logger.info(`Set ticket status: ${SUPPORT_LABELS.status[status]}`);
@@ -8217,6 +8273,299 @@ async function createSupportTicketViaChatAndVerify(page, opts) {
8217
8273
  return dialog;
8218
8274
  }
8219
8275
 
8276
+ /**
8277
+ * Profile History tab Playwright bindings (user profile modal > History).
8278
+ *
8279
+ * The tab has two sub-tabs:
8280
+ * 1. **Conversations** — filter row (agent autocomplete, date range,
8281
+ * sentiment, topic, Export), a two-column conversation list + transcript
8282
+ * preview, and numbered pagination.
8283
+ * 2. **Exports** — a table of previously generated `my-chat-history`
8284
+ * reports with state badges and re-download actions.
8285
+ *
8286
+ * Anti-flake rules baked into every helper:
8287
+ * - The profile dialog is captured ONCE via `getProfileDialog` — a
8288
+ * `getByRole('dialog')` + `.filter(...)` pair — and every sub-element is
8289
+ * resolved from that scoped locator. Page-level queries are used only for
8290
+ * Radix portals (select dropdowns, toasts).
8291
+ * - Selectors are role / aria-label / data-testid based only — no CSS
8292
+ * classes, no `networkidle`; readiness is always "wait for the element".
8293
+ */
8294
+ const HISTORY_TAB_LABELS = {
8295
+ /** Tab name in the user profile modal sidebar. */
8296
+ tabName: 'History',
8297
+ subTabs: {
8298
+ conversations: 'Conversations',
8299
+ exports: 'Exports',
8300
+ },
8301
+ filters: {
8302
+ /** Placeholder (and accessible name) of the agent autocomplete input. */
8303
+ searchAgents: 'Search Agents',
8304
+ pickDateRange: 'Pick a Date Range',
8305
+ /** `aria-label` of the sentiment select trigger. */
8306
+ sentiment: 'Filter by Sentiment',
8307
+ /** `aria-label` of the topic select trigger. */
8308
+ topic: 'Filter by Topic',
8309
+ export: 'Export',
8310
+ exporting: 'Exporting...',
8311
+ },
8312
+ regions: {
8313
+ /** `aria-label` of the conversation list region. */
8314
+ list: 'Conversation list',
8315
+ /** `aria-label` of the transcript preview region. */
8316
+ preview: 'Conversation preview',
8317
+ },
8318
+ /** Per-conversation download button in the preview header. */
8319
+ download: 'Download',
8320
+ emptyState: 'No conversations found',
8321
+ selectPrompt: 'Select a conversation to view details.',
8322
+ toasts: {
8323
+ exportReady: 'Your chat history has been downloaded.',
8324
+ exportFailed: 'Failed to export chat history. Please try again.',
8325
+ },
8326
+ exports: {
8327
+ columns: {
8328
+ status: 'Status',
8329
+ created: 'Created',
8330
+ filters: 'Filters',
8331
+ expires: 'Expires',
8332
+ },
8333
+ states: {
8334
+ completed: 'Completed',
8335
+ processing: 'Processing',
8336
+ pending: 'Pending',
8337
+ failed: 'Failed',
8338
+ },
8339
+ empty: 'No exports yet.',
8340
+ },
8341
+ };
8342
+ /** data-testid prefix of the agent autocomplete (`SearchSelect`). */
8343
+ const AGENT_FILTER_TEST_ID = 'history-agent-filter';
8344
+ function asPage(scope) {
8345
+ return 'page' in scope ? scope.page() : scope;
8346
+ }
8347
+ // ──────────────────────────────────────────────────────────────────────
8348
+ // Dialog + tab navigation
8349
+ // ──────────────────────────────────────────────────────────────────────
8350
+ /**
8351
+ * The user profile dialog, captured tag-first (`getByRole('dialog')`) and
8352
+ * narrowed by a solid child — the History tab button — so it never matches
8353
+ * a different dialog stacked on the page.
8354
+ */
8355
+ function getProfileDialog(page) {
8356
+ return page
8357
+ .getByRole('dialog')
8358
+ .filter({ has: page.getByRole('tab', { name: HISTORY_TAB_LABELS.tabName, exact: true }) });
8359
+ }
8360
+ /**
8361
+ * Open the History tab inside the (already open) profile dialog and wait
8362
+ * for its Conversations sub-tab to render. Returns the scoped dialog
8363
+ * locator every other helper should be handed.
8364
+ */
8365
+ async function openHistoryTab(page) {
8366
+ const dialog = getProfileDialog(page);
8367
+ await expect(dialog).toBeVisible({ timeout: 15000 });
8368
+ const historyTab = dialog.getByRole('tab', {
8369
+ name: HISTORY_TAB_LABELS.tabName,
8370
+ exact: true,
8371
+ });
8372
+ await expect(historyTab).toBeVisible({ timeout: 10000 });
8373
+ await historyTab.click();
8374
+ await expect(dialog.getByRole('tab', { name: HISTORY_TAB_LABELS.subTabs.conversations, exact: true })).toBeVisible({ timeout: 10000 });
8375
+ logger.info('Opened profile History tab');
8376
+ return dialog;
8377
+ }
8378
+ /**
8379
+ * Switch between the Conversations and Exports sub-tabs, waiting for a
8380
+ * stable landmark of the destination before returning.
8381
+ */
8382
+ async function switchHistorySubTab(dialog, subTab) {
8383
+ const trigger = dialog.getByRole('tab', { name: subTab, exact: true });
8384
+ await expect(trigger).toBeVisible({ timeout: 10000 });
8385
+ await trigger.click();
8386
+ await expect(trigger).toHaveAttribute('aria-selected', 'true', { timeout: 10000 });
8387
+ if (subTab === 'Exports') {
8388
+ await expect(dialog.getByRole('table')).toBeVisible({ timeout: 15000 });
8389
+ }
8390
+ else {
8391
+ await expect(dialog.getByRole('button', { name: HISTORY_TAB_LABELS.filters.export, exact: true })).toBeVisible({ timeout: 15000 });
8392
+ }
8393
+ logger.info(`Switched History sub-tab to ${subTab}`);
8394
+ }
8395
+ // ──────────────────────────────────────────────────────────────────────
8396
+ // Conversations — list + preview
8397
+ // ──────────────────────────────────────────────────────────────────────
8398
+ function getConversationList(dialog) {
8399
+ return dialog.getByRole('region', { name: HISTORY_TAB_LABELS.regions.list });
8400
+ }
8401
+ function getConversationPreview(dialog) {
8402
+ return dialog.getByRole('region', { name: HISTORY_TAB_LABELS.regions.preview });
8403
+ }
8404
+ /** Every conversation row in the list (each row is a `role="button"`). */
8405
+ function getConversationRows(dialog) {
8406
+ return getConversationList(dialog).getByTestId('history-conversation-row');
8407
+ }
8408
+ /**
8409
+ * Wait for the conversation area to settle into one of its two valid
8410
+ * states: at least one row rendered, or the empty state.
8411
+ */
8412
+ async function waitForConversations(dialog) {
8413
+ const firstRow = getConversationRows(dialog).first();
8414
+ const emptyState = dialog.getByText(HISTORY_TAB_LABELS.emptyState, { exact: true });
8415
+ await expect(firstRow.or(emptyState).first()).toBeVisible({ timeout: 30000 });
8416
+ }
8417
+ /**
8418
+ * Click a conversation row — by zero-based `index`, or the first row whose
8419
+ * text contains `title` — then wait for the transcript preview to show its
8420
+ * per-conversation Download button (the signal the messages have loaded).
8421
+ */
8422
+ async function selectConversation(dialog, options = {}) {
8423
+ var _a;
8424
+ const rows = getConversationRows(dialog);
8425
+ const row = options.title !== undefined
8426
+ ? rows.filter({ hasText: options.title }).first()
8427
+ : rows.nth((_a = options.index) !== null && _a !== void 0 ? _a : 0);
8428
+ await expect(row).toBeVisible({ timeout: 30000 });
8429
+ await row.click();
8430
+ const preview = getConversationPreview(dialog);
8431
+ await expect(preview.getByRole('button', { name: HISTORY_TAB_LABELS.download, exact: true })).toBeVisible({ timeout: 30000 });
8432
+ logger.info('Selected conversation and transcript preview loaded');
8433
+ }
8434
+ /**
8435
+ * Download the currently previewed conversation as CSV (client-side file).
8436
+ * Returns the Playwright `Download` so the test can assert on the file.
8437
+ */
8438
+ async function downloadConversationCsv(dialog) {
8439
+ const page = asPage(dialog);
8440
+ const button = getConversationPreview(dialog).getByRole('button', {
8441
+ name: HISTORY_TAB_LABELS.download,
8442
+ exact: true,
8443
+ });
8444
+ await expect(button).toBeVisible({ timeout: 10000 });
8445
+ const downloadPromise = page.waitForEvent('download', { timeout: 30000 });
8446
+ await button.click();
8447
+ const download = await downloadPromise;
8448
+ logger.info(`Downloaded conversation file: ${download.suggestedFilename()}`);
8449
+ return download;
8450
+ }
8451
+ // ──────────────────────────────────────────────────────────────────────
8452
+ // Conversations — filters
8453
+ // ──────────────────────────────────────────────────────────────────────
8454
+ /**
8455
+ * Type into the agent autocomplete and pick the result whose label matches
8456
+ * `agentName`, then wait for the picker to collapse into its selected chip.
8457
+ */
8458
+ async function filterHistoryByAgent(dialog, agentName) {
8459
+ const input = dialog.getByTestId(`${AGENT_FILTER_TEST_ID}-input`);
8460
+ await expect(input).toBeVisible({ timeout: 10000 });
8461
+ await input.fill(agentName);
8462
+ const option = dialog
8463
+ .getByTestId(`${AGENT_FILTER_TEST_ID}-results`)
8464
+ .getByRole('button', { name: agentName })
8465
+ .first();
8466
+ await expect(option).toBeVisible({ timeout: 30000 });
8467
+ await option.click();
8468
+ await expect(dialog.getByTestId(`${AGENT_FILTER_TEST_ID}-selected`)).toBeVisible({
8469
+ timeout: 10000,
8470
+ });
8471
+ logger.info(`Filtered History by agent: ${agentName}`);
8472
+ }
8473
+ /** Clear the agent filter chip and wait for the search input to return. */
8474
+ async function clearHistoryAgentFilter(dialog) {
8475
+ const clearButton = dialog.getByTestId(`${AGENT_FILTER_TEST_ID}-clear`);
8476
+ await expect(clearButton).toBeVisible({ timeout: 10000 });
8477
+ await clearButton.click();
8478
+ await expect(dialog.getByTestId(`${AGENT_FILTER_TEST_ID}-input`)).toBeVisible({
8479
+ timeout: 10000,
8480
+ });
8481
+ }
8482
+ /**
8483
+ * Pick an option in one of the filter selects (sentiment / topic). The
8484
+ * trigger lives in the dialog; the option list is a Radix portal, so it is
8485
+ * the one place resolved from the page root.
8486
+ */
8487
+ async function pickFilterOption(dialog, triggerLabel, optionName) {
8488
+ const page = asPage(dialog);
8489
+ const trigger = dialog.getByRole('combobox', { name: triggerLabel });
8490
+ await expect(trigger).toBeVisible({ timeout: 10000 });
8491
+ await trigger.click();
8492
+ const option = page.getByRole('option', { name: optionName, exact: true });
8493
+ await expect(option).toBeVisible({ timeout: 10000 });
8494
+ await option.click();
8495
+ // The trigger echoes the chosen option — the sign the select applied.
8496
+ await expect(trigger).toContainText(optionName, { timeout: 10000 });
8497
+ }
8498
+ async function filterHistoryBySentiment(dialog, sentiment) {
8499
+ await pickFilterOption(dialog, HISTORY_TAB_LABELS.filters.sentiment, sentiment);
8500
+ logger.info(`Filtered History by sentiment: ${sentiment}`);
8501
+ }
8502
+ async function filterHistoryByTopic(dialog, topic) {
8503
+ await pickFilterOption(dialog, HISTORY_TAB_LABELS.filters.topic, topic);
8504
+ logger.info(`Filtered History by topic: ${topic}`);
8505
+ }
8506
+ // ──────────────────────────────────────────────────────────────────────
8507
+ // Export (server-side report) + Exports sub-tab
8508
+ // ──────────────────────────────────────────────────────────────────────
8509
+ /**
8510
+ * Click Export on the Conversations sub-tab. The report generates
8511
+ * server-side and downloads automatically when ready — pass the returned
8512
+ * promise handling to `waitForHistoryExportDownload` for the full flow.
8513
+ */
8514
+ async function startHistoryExport(dialog) {
8515
+ const exportButton = dialog.getByRole('button', {
8516
+ name: HISTORY_TAB_LABELS.filters.export,
8517
+ exact: true,
8518
+ });
8519
+ await expect(exportButton).toBeVisible({ timeout: 10000 });
8520
+ await expect(exportButton).toBeEnabled({ timeout: 10000 });
8521
+ await exportButton.click();
8522
+ logger.info('Started History export');
8523
+ }
8524
+ /**
8525
+ * Full export flow: click Export, then wait for the report to finish
8526
+ * polling and the browser download to fire. Report generation is a
8527
+ * background task, so the timeout is generous by default.
8528
+ */
8529
+ async function exportHistoryAndWaitForDownload(dialog, { timeout = 120000 } = {}) {
8530
+ const page = asPage(dialog);
8531
+ const downloadPromise = page.waitForEvent('download', { timeout });
8532
+ await startHistoryExport(dialog);
8533
+ const download = await downloadPromise;
8534
+ logger.info(`History export downloaded: ${download.suggestedFilename()}`);
8535
+ return download;
8536
+ }
8537
+ /** The Exports sub-tab's reports table. */
8538
+ function getExportsTable(dialog) {
8539
+ return dialog.getByRole('table');
8540
+ }
8541
+ /**
8542
+ * Rows of the Exports table matching a state badge label (e.g.
8543
+ * `Completed`), each of which carries its own Download action when done.
8544
+ */
8545
+ function getExportRowsByState(dialog, state) {
8546
+ return getExportsTable(dialog).getByRole('row').filter({ hasText: state });
8547
+ }
8548
+ /**
8549
+ * Wait until at least one report row reaches the Completed state. Reports
8550
+ * finish asynchronously, so the timeout is generous by default.
8551
+ */
8552
+ async function waitForCompletedExportRow(dialog, { timeout = 120000 } = {}) {
8553
+ const row = getExportRowsByState(dialog, HISTORY_TAB_LABELS.exports.states.completed).first();
8554
+ await expect(row.getByRole('button', { name: HISTORY_TAB_LABELS.download, exact: true })).toBeVisible({ timeout });
8555
+ return row;
8556
+ }
8557
+ /** Re-download a completed report from its Exports-table row. */
8558
+ async function downloadExportedReport(dialog, row) {
8559
+ const page = asPage(dialog);
8560
+ const button = row.getByRole('button', { name: HISTORY_TAB_LABELS.download, exact: true });
8561
+ await expect(button).toBeVisible({ timeout: 10000 });
8562
+ const downloadPromise = page.waitForEvent('download', { timeout: 60000 });
8563
+ await button.click();
8564
+ const download = await downloadPromise;
8565
+ logger.info(`Re-downloaded report: ${download.suggestedFilename()}`);
8566
+ return download;
8567
+ }
8568
+
8220
8569
  /** Extract browser key from device name (e.g., 'Desktop Chrome' -> 'chrome') */
8221
8570
  function getBrowserKey(deviceName) {
8222
8571
  return deviceName.toLowerCase().replace(/^desktop\s+/, '');
@@ -8342,5 +8691,5 @@ function createPlaywrightConfig(options) {
8342
8691
  });
8343
8692
  }
8344
8693
 
8345
- export { AuthFlowBuilder, CHAT_PRIVACY_LABELS, CustomReporter, EVALS_LABELS, GRADER_LABELS, LTI_LABELS, LTI_TEST_IDS, MEMORY_ADMIN_LABELS, MailsacClient, PRIVACY_LABELS, SCREENSHARE_LABELS, SPEND_LIMITS_LABELS, SUPPORT_LABELS, TASKS_LABELS, VOICE_LABELS, addAgentMemoryFromPopup, addGraderCriterion, addManualScore, addMemory, addQaPairsManually, addSkillToAgent, addTextResource, addUserGlobalMemory, addUserSpendLimit, addUserSpendLimitFromTenantBilling, agentLimitsRow, agentLimitsSection, applyVoiceInstructionsPreset, archiveFirstMemory, archiveMemoryByContent, billingAutoRechargeSection, billingCreditsSection, billingPlanSection, buildReportUrl, canChatWithEmbedMentor, cancelDeleteEvaluation, cancelDeleteInstance, cancelDeleteSkill, cancelDisconnectInstance, cancelEnableChatPrivacyMidSession, cancelKeyDelete, cancelLlmJudge, cancelNewInstanceDialog, cancelStartEvaluation, checkAdminStatus, checkRunStatus, clearAgentLimitsFilter, clearAgentMemoriesFilter, clearDateRangeFilter, clearGradeResultOverride, clearInstanceSearch, clearUserFilter, clickBackHome, clickBillingAddCredits, clickBillingManageBilling, clickBillingManageUsage, clickBillingUpgrade, clickChatPrivacyToggle, clickDownloadAgain, clickManualDownloadLink, clickSetSpendLimitForFilteredAgent, closeAgentLimitsPopup, closeAgentMemoriesPopup, closeBenchmarkItemsDialog, closeCreditBalanceDropdown, closeEvaluationDetailDialog, closeKeyDetail, closeManageBenchmarksDialog, closeUserMemoriesPopup, closeWithEsc, confirmEnableChatPrivacyMidSession, confirmKeyDelete, connectToInstance, copyEndpoint, createAgentSpendLimitViaFilter, createAuthSetup, createBenchmark, createEnvConfig, createInstance, createKey, createLink, createPlaywrightConfig, createSkill, createSupportTicketViaChatAndVerify, createTool, creditBalancePanel, creditBalancePlanBadge, creditBalanceTrigger, deleteAgentSpendLimit, deleteAgentSpendLimitFromTenantBilling, deleteEvaluation, deleteFirstMemory, deleteGraderCriterion, deleteInstance, deleteKey, deleteMemoryByContent, deleteQaItem, deleteResource, deleteSkill, deleteTask, deleteUserGlobalMemory, deleteUserSpendLimit, deleteWorkspaceSpendLimit, disableSkill, disableSupport, disconnectInstance, editAgentPrompt, editGraderCriterion, editInstance, editLink, editSkill, editTextResource, editTool, editUserGlobalMemory, editUserSpendLimit, enableSkill, enableSupport, expandReview, expandTrace, expectAgentLimitsRowContent, expectAllEndpointsVisible, expectBenchmarkListed, expectBillingAutoRechargeSection, expectBillingCreditsSection, expectBillingPlanSection, expectBillingTabForCurrentPlan, expectBillingTabForFreePlan, expectBillingTabForPremiumPlan, expectBillingTabForTrialPlan, expectCallConfigVisible, expectCallConfigVoiceTriggerShows, expectChatPrivacyConfirmDialogOpen, expectChatPrivacyLocked, expectChatPrivacySource, expectChatPrivacyState, expectChatPrivacyToggleVisible, expectCompletedTasks, expectCreditBalanceForCurrentPlan, expectCreditBalancePanelForFreePlan, expectCreditBalancePanelForPremiumPlan, expectCreditBalancePanelForTrialPlan, expectCreditBalanceVisibilityForTenant, expectDetailWaitingForTraces, expectEndpointUrl, expectEntitySelected, expectFailedTasks, expectGradeResultRow, expectGraderMisconfiguredWarning, expectGraderTotalPoints, expectKeyDeleteError, expectKeyInList, expectKeyNotInList, expectKeysEmpty, expectLastCriterionDeleteDisabled, expectLinkInList, expectLinkNotInList, expectLinkStatus, expectLinkTargetUri, expectLinksEmpty, expectLogDetailsStatus, expectLogsForTask, expectLtiHeader, expectMentorVoiceTriggerShows, expectMessageInConversation, expectNoAccessibilityViolations, expectNoAccessibilityViolationsOnDialogs, expectNoBenchmarksNotice, expectNoLogsForSelectedTask, expectNoRepliesYet, expectNoTickets, expectOutputFilterEnabled, expectPrivacyFieldsHidden, expectPrivacyFieldsVisible, expectPrivateModeSelected, expectPrivateModeTabReady, expectQaItemListed, expectReviewInList, expectReviewStatus, expectRunInTable, expectRunNotInTable, expectRunStatus, expectRunsTableEmpty, expectScheduleStartTimeInPastError, expectScreenShareDisabledHint, expectSelectedBenchmark, expectSttSelectDisabled, expectTaskInList, expectTaskNotInList, expectTaskStatus, expectTasksEmpty, expectTenantChatPrivacyEnabled, expectTenantChatPrivacyVisible, expectTicketClosedNotice, expectTicketDescriptionContains, expectTicketInList, expectTicketStatusInList, expectToolInList, expectToolNotInList, expectToolsEmpty, expectTotalTasks, expectTraceScore, expectTtsSelectDisabled, expectVoiceInstructionsValue, expectVoiceProviderSelected, expectVoiceVisible, expectWorkspaceActualSpendStats, expectWorkspaceSpendStats, exportRunCsv, fillLinkName, fillToolForm, filterAgentLimits, filterAgentMemories, filterByAction, filterByActionAndVerify, filterByActor, filterByActorAndVerify, filterByDateRange, filterGradeResultsByEmail, filterTicketsByStatus, filterTicketsByUser, generateBrowserSetupProjects, generateProjectConfig, getAddItemsDialog, getAuditLogRowCount, getAvailableActors, getBenchmarkCombobox, getBenchmarkComboboxDropdown, getBenchmarkItemsDialog, getBillingAutoRechargeStatus, getBillingPlanLabel, getBrowserKey, getCallConfigForm, getChatInput, getChatPrivacyConfirmDialog, getChatPrivacyToggle, getCreateBenchmarkDialog, getCreateKeyButton, getCreateLinkButton, getCreateToolButton, getCreditBalancePlanLabel, getCreditBalanceRemaining, getCurrentModel, getCurrentTenantShowPaywall, getDeleteEvaluationDialog, getDeleteQaItemDialog, getEditAgentDialog, getEndpoint, getEndpointCopyButton, getEndpointUrl, getEntityChip, getEvaluationDetailDialog, getInstanceHealthLabel, getInstanceRowCount, getInstanceStatusLabel, getKeyActionsTrigger, getKeyCreateModal, getKeyCreateNameInput, getKeyDeleteModal, getKeyDetailModal, getKeyDetailNameInput, getKeyPublicJwkField, getKeyPublicKeyField, getKeyRow, getKeysEmptyState, getKeysSection, getLinkCopyTargetUriButton, getLinkEditButton, getLinkModal, getLinkNameInput, getLinkRow, getLinksEmptyState, getLinksRefreshButton, getLinksSection, getLlmJudgeDialog, getLlmPickerDialog, getLtiSubTab, getManageBenchmarksButton, getManageBenchmarksDialog, getMemoryCount, getMentorIdFromUrl, getNewEvaluationButton, getOutputFilterSwitch, getPaginationInfo, getPrivateModeCard, getReplyComposer, getReviewRow, getRunRow, getScheduleTaskButton, getSearchInput, getSkillRowCount, getStartEvaluationDialog, getStatusFilter, getSupportInfoBox, getSupportTabTrigger, getSupportToggle, getTaskRow, getTenantChatPrivacyRow, getTenantChatPrivacySwitch, getTicketDescription, getTicketDetail, getTicketList, getTicketRow, getTicketRowByIndex, getToolEditButton, getToolKeySelect, getToolModal, getToolRow, getToolsEmptyState, getToolsSection, getTraceRow, getUserFilter, getVoiceProviderCard, getVoiceRow, goToFirstPage, goToLastPage, goToNextPage, goToPage, goToPreviousPage, goToSkillsListPage, graderTabBody, inviteUserTest, isEvaluationTabVisible, isFirefox, isGraderTabVisible, isGradingEnabled, isJSON, isLtiTabVisible, isMemoryTabVisible, isOnFirstPage, isOnLastPage, isPrivacyTabVisible, isPrivateModeTabVisible, isSandboxTabVisible, isScreenShareTabVisible, isSkillEnabled, isSpendLimitsTabVisible, isSupportEnabled, isSupportTabVisible, isTasksTabVisible, isTenantMemoryTabVisible, isVoiceTabVisible, logger, loginWithEmailAndPassword, loginWithMicrosoftIdp, memoryAdminAgentRow, memoryAdminAgentSection, memoryAdminGlobalSection, memoryAdminUserRow, memoryRowByContent, navigateToAccountComponent, navigateToAuditLog, navigateToAuditLogAndWaitForData, navigateToDataReports, navigateToReportDownload, openAddItemsDialog, openAddMemoryDialog, openAgentLimitsManage, openAgentMemoriesPopup, openAgentPromptEditModal, openBenchmarkItems, openCallConfigVoicePicker, openCreateKeyModal, openCreateLinkModal, openCreateToolModal, openCreditBalanceDropdown, openEditInstanceDialog, openEditLinkModal, openEditSkillDialog, openEditToolModal, openFirstLogDetails, openInstanceActionsMenu, openKeyActionsMenu, openKeyDelete, openKeyDetail, openLLMProviderPicker, openManageBenchmarksDialog, openMentorVoicePicker, openNewInstanceDialog, openNewReviewForRun, openNewReviewFromDetail, openNewSkillDialog, openRunActionsMenu, openRunResults, openScheduleTaskDialog, openScreenSharePromptEditor, openSkillActionsMenu, openSlashSkillPicker, openStartEvaluationDialog, openTicket, openUserMemoriesPopup, openVoiceInstructionsEditor, overrideGradeResult, parseReportUrlParams, previewCallConfigVoiceInline, previewMentorVoiceInline, previewVoice, pushConfiguration, readEndpointUrl, readKeyPublicJwk, readKeyPublicKey, refreshEvaluationDetail, refreshLinks, refreshTickets, reliableClick, reliableFill, removeSkillFromAgent, removeTraceScore, renameKey, replyToTicket, requestSupportTicketViaChat, resetCallConfig, retry, retryFailedLink, runConnectedInstanceChecks, runInstanceChecks, safeWaitForURL, saveCallConfig, saveGraderConfig, saveScreenSharePrompts, saveVoiceSettings, scheduleTask, searchBenchmarks, searchInstances, searchMemoryAdminUsers, searchTasks, searchVoices, selectBenchmark, selectCallMode, selectDateFromCalendar, selectJudgeLlm, selectLLMModel, selectLlmProvider, selectPrivacyAction, selectPrivateMode, selectSlashSkill, selectSttProvider, selectTaskInList, selectToolKeySetMode, selectToolSigningKey, selectTtsProvider, selectVoice, selectVoiceProvider, sendAgentChatMessage, setAgentLimitsRowEnabled, setAgentSpendLimit, setAgentSpendLimitFromTenantBilling, setBlockMessage, setCallLanguage, setCatalogSkillEnabled, setEnableVideo, setEntitySelected, setGradingEnabled, setOutputFilterEnabled, setScreenSharePrompt, setSupportEnabled, setTenantChatPrivacyEnabled, setTicketStatus, setUseFunctionCallingEnabled, setUserSpendLimitEnabled, setVoiceInstructions, setWorkspaceSpendLimit, setupSandboxInstance, shouldAddNewRowWhenClickingAddRowButton, shouldAllowEditingCellValuesInCSVEditor, shouldCancelCombiningReports, shouldCloseCSVEditorWhenClickingCloseButton, shouldCloseCSVEditorWithoutSavingWhenClickingCancel, shouldCombineRecommendationReports, shouldDirectlyDownloadChatHistoryReportWithoutCSVEditor, shouldDisableOtherDownloadButtonsWhileGeneratingReport, shouldDisplayCSVInEditableTableFormat, shouldDisplayReportCards, shouldHaveCombinedReportDataTestIds, shouldOpenCSVEditorDialog, shouldOpenCSVEditorForUserMetadataReport, shouldSaveEditedCSVAndTriggerDownload, shouldShowCombiningReportsDialog, shouldVerifyCSVEditorDialogAccessibility, signUpWithEmailAndPassword, spendLimitsTabBody, startEvaluation, submitLinkModal, submitLlmJudge, submitToolModal, switchToAddItemsSubTab, switchToAgentLimits, switchToAgentSkillsSubTab, switchToAvailableSkillsSubTab, switchToEvaluationTab, switchToGraderSubTab, switchToGraderTab, switchToLtiSubTab, switchToLtiTab, switchToMemoryAdminSubTab, switchToMemoryTab, switchToPlanAndCredits, switchToPrivacyTab, switchToPrivateModeTab, switchToSandboxTab, switchToScreenShareTab, switchToSkillResourcesSubTab, switchToSkillsTab, switchToSpendLimitsSubTab, switchToSpendLimitsTab, switchToSupportTab, switchToTasksTab, switchToTenantMemoryTab, switchToVoiceSubTab, switchToVoiceTab, switchToWorkspaceSpendLimits, teardownSandboxInstance, test, toggleAutoPush, toggleMemorySwitch, toggleSkill, toggleUserMemoryAdminSetting, toolFields, uploadAssetResource, uploadQaCsv, userSpendLimitRow, verifyAgentConfigPromptsVisible, verifyAgentSkillsEmptyState, verifyAuditLogEmptyState, verifyAuditLogEntryStructure, verifyAuditLogGenericError, verifyAuditLogLoading, verifyAuditLogPermissionError, verifyAuditLogTableVisible, verifyConnectDisabledForUnhealthy, verifyConnectedInstanceCard, verifyCurrentPage, verifyDonePhase, verifyDownloadingPhase, verifyErrorPhase, verifyInstanceTableEmpty, verifyInstanceTableVisible, verifyMemoryExists, verifyMemoryNotExists, verifyMemoryTabMemoriesList, verifyMemoryTabSettings, verifyPreparingPhase, verifySkillAdded, verifySkillVisible, verifySkillsEmptyState, verifySkillsTabVisible, waitForAgentChatResponse, waitForAuditLogDataLoaded, waitForBillingTabReady, waitForCreditBalanceLoaded, waitForDialogReady, waitForElementStable, waitForLinkReady, waitForPageLoad, waitForPageReady, waitForReportDownload, waitForTicketInList, workspaceSpendLimitSection };
8694
+ export { AuthFlowBuilder, CHAT_PRIVACY_LABELS, CustomReporter, EVALS_LABELS, GRADER_LABELS, HISTORY_TAB_LABELS, LTI_LABELS, LTI_TEST_IDS, MEMORY_ADMIN_LABELS, MailsacClient, PRIVACY_LABELS, SCREENSHARE_LABELS, SPEND_LIMITS_LABELS, SUPPORT_LABELS, TASKS_LABELS, VOICE_LABELS, addAgentMemoryFromPopup, addGraderCriterion, addManualScore, addMemory, addQaPairsManually, addSkillToAgent, addTextResource, addUserGlobalMemory, addUserSpendLimit, addUserSpendLimitFromTenantBilling, agentLimitsRow, agentLimitsSection, applyVoiceInstructionsPreset, archiveFirstMemory, archiveMemoryByContent, billingAutoRechargeSection, billingCreditsSection, billingPlanSection, buildReportUrl, canChatWithEmbedMentor, cancelDeleteEvaluation, cancelDeleteInstance, cancelDeleteSkill, cancelDisconnectInstance, cancelEnableChatPrivacyMidSession, cancelKeyDelete, cancelLlmJudge, cancelNewInstanceDialog, cancelStartEvaluation, checkAdminStatus, checkRunStatus, clearAgentLimitsFilter, clearAgentMemoriesFilter, clearDateRangeFilter, clearGradeResultOverride, clearHistoryAgentFilter, clearInstanceSearch, clearUserFilter, clickBackHome, clickBillingAddCredits, clickBillingManageBilling, clickBillingManageUsage, clickBillingUpgrade, clickChatPrivacyToggle, clickDownloadAgain, clickManualDownloadLink, clickSetSpendLimitForFilteredAgent, closeAgentLimitsPopup, closeAgentMemoriesPopup, closeBenchmarkItemsDialog, closeCreditBalanceDropdown, closeEvaluationDetailDialog, closeKeyDetail, closeManageBenchmarksDialog, closeUserMemoriesPopup, closeWithEsc, confirmEnableChatPrivacyMidSession, confirmKeyDelete, connectToInstance, copyEndpoint, createAgentSpendLimitViaFilter, createAuthSetup, createBenchmark, createEnvConfig, createInstance, createKey, createLink, createPlaywrightConfig, createSkill, createSupportTicketViaChatAndVerify, createTool, creditBalancePanel, creditBalancePlanBadge, creditBalanceTrigger, deleteAgentSpendLimit, deleteAgentSpendLimitFromTenantBilling, deleteEvaluation, deleteFirstMemory, deleteGraderCriterion, deleteInstance, deleteKey, deleteMemoryByContent, deleteQaItem, deleteResource, deleteSkill, deleteTask, deleteUserGlobalMemory, deleteUserSpendLimit, deleteWorkspaceSpendLimit, disableSkill, disableSupport, disconnectInstance, downloadConversationCsv, downloadExportedReport, editAgentPrompt, editGraderCriterion, editInstance, editLink, editSkill, editTextResource, editTool, editUserGlobalMemory, editUserSpendLimit, enableSkill, enableSupport, expandReview, expandTrace, expectAgentLimitsRowContent, expectAllEndpointsVisible, expectBenchmarkListed, expectBillingAutoRechargeSection, expectBillingCreditsSection, expectBillingPlanSection, expectBillingTabForCurrentPlan, expectBillingTabForFreePlan, expectBillingTabForPremiumPlan, expectBillingTabForTrialPlan, expectCallConfigVisible, expectCallConfigVoiceTriggerShows, expectChatPrivacyConfirmDialogOpen, expectChatPrivacyLocked, expectChatPrivacySource, expectChatPrivacyState, expectChatPrivacyToggleVisible, expectCompletedTasks, expectCreditBalanceForCurrentPlan, expectCreditBalancePanelForFreePlan, expectCreditBalancePanelForPremiumPlan, expectCreditBalancePanelForTrialPlan, expectCreditBalanceVisibilityForTenant, expectDetailWaitingForTraces, expectEndpointUrl, expectEntitySelected, expectFailedTasks, expectGradeResultRow, expectGraderMisconfiguredWarning, expectGraderTotalPoints, expectKeyDeleteError, expectKeyInList, expectKeyNotInList, expectKeysEmpty, expectLastCriterionDeleteDisabled, expectLinkInList, expectLinkNotInList, expectLinkStatus, expectLinkTargetUri, expectLinksEmpty, expectLogDetailsStatus, expectLogsForTask, expectLtiHeader, expectMentorVoiceTriggerShows, expectMessageInConversation, expectNoAccessibilityViolations, expectNoAccessibilityViolationsOnDialogs, expectNoBenchmarksNotice, expectNoLogsForSelectedTask, expectNoRepliesYet, expectNoTickets, expectOutputFilterEnabled, expectPrivacyFieldsHidden, expectPrivacyFieldsVisible, expectPrivateModeSelected, expectPrivateModeTabReady, expectQaItemListed, expectReviewInList, expectReviewStatus, expectRunInTable, expectRunNotInTable, expectRunStatus, expectRunsTableEmpty, expectScheduleStartTimeInPastError, expectScreenShareDisabledHint, expectSelectedBenchmark, expectSttSelectDisabled, expectTaskInList, expectTaskNotInList, expectTaskStatus, expectTasksEmpty, expectTenantChatPrivacyEnabled, expectTenantChatPrivacyVisible, expectTicketClosedNotice, expectTicketDescriptionContains, expectTicketInList, expectTicketStatusInList, expectToolInList, expectToolNotInList, expectToolsEmpty, expectTotalTasks, expectTraceScore, expectTtsSelectDisabled, expectVoiceInstructionsValue, expectVoiceProviderSelected, expectVoiceVisible, expectWorkspaceActualSpendStats, expectWorkspaceSpendStats, exportHistoryAndWaitForDownload, exportRunCsv, fillLinkName, fillToolForm, filterAgentLimits, filterAgentMemories, filterByAction, filterByActionAndVerify, filterByActor, filterByActorAndVerify, filterByDateRange, filterGradeResultsByEmail, filterHistoryByAgent, filterHistoryBySentiment, filterHistoryByTopic, filterTicketsByStatus, filterTicketsByUser, generateBrowserSetupProjects, generateProjectConfig, getAddItemsDialog, getAuditLogRowCount, getAvailableActors, getBenchmarkCombobox, getBenchmarkComboboxDropdown, getBenchmarkItemsDialog, getBillingAutoRechargeStatus, getBillingPlanLabel, getBrowserKey, getCallConfigForm, getChatInput, getChatPrivacyConfirmDialog, getChatPrivacyToggle, getConversationList, getConversationPreview, getConversationRows, getCreateBenchmarkDialog, getCreateKeyButton, getCreateLinkButton, getCreateToolButton, getCreditBalancePlanLabel, getCreditBalanceRemaining, getCurrentModel, getCurrentTenantShowPaywall, getDeleteEvaluationDialog, getDeleteQaItemDialog, getEditAgentDialog, getEndpoint, getEndpointCopyButton, getEndpointUrl, getEntityChip, getEvaluationDetailDialog, getExportRowsByState, getExportsTable, getInstanceHealthLabel, getInstanceRowCount, getInstanceStatusLabel, getKeyActionsTrigger, getKeyCreateModal, getKeyCreateNameInput, getKeyDeleteModal, getKeyDetailModal, getKeyDetailNameInput, getKeyPublicJwkField, getKeyPublicKeyField, getKeyRow, getKeysEmptyState, getKeysSection, getLinkCopyTargetUriButton, getLinkEditButton, getLinkModal, getLinkNameInput, getLinkRow, getLinksEmptyState, getLinksRefreshButton, getLinksSection, getLlmJudgeDialog, getLlmPickerDialog, getLtiSubTab, getManageBenchmarksButton, getManageBenchmarksDialog, getMemoryCount, getMentorIdFromUrl, getNewEvaluationButton, getOutputFilterSwitch, getPaginationInfo, getPrivateModeCard, getProfileDialog, getReplyComposer, getReviewRow, getRunRow, getScheduleTaskButton, getSearchInput, getSkillRowCount, getStartEvaluationDialog, getStatusFilter, getSupportInfoBox, getSupportTabTrigger, getSupportToggle, getTaskRow, getTenantChatPrivacyRow, getTenantChatPrivacySwitch, getTicketDescription, getTicketDetail, getTicketList, getTicketRow, getTicketRowByIndex, getToolEditButton, getToolKeySelect, getToolModal, getToolRow, getToolsEmptyState, getToolsSection, getTraceRow, getUserFilter, getVoiceProviderCard, getVoiceRow, goToFirstPage, goToLastPage, goToNextPage, goToPage, goToPreviousPage, goToSkillsListPage, graderTabBody, inviteUserTest, isEvaluationTabVisible, isFirefox, isGraderTabVisible, isGradingEnabled, isJSON, isLtiTabVisible, isMemoryTabVisible, isOnFirstPage, isOnLastPage, isPrivacyTabVisible, isPrivateModeTabVisible, isSandboxTabVisible, isScreenShareTabVisible, isSkillEnabled, isSpendLimitsTabVisible, isSupportEnabled, isSupportTabVisible, isTasksTabVisible, isTenantMemoryTabVisible, isVoiceTabVisible, logger, loginWithEmailAndPassword, loginWithMicrosoftIdp, memoryAdminAgentRow, memoryAdminAgentSection, memoryAdminGlobalSection, memoryAdminUserRow, memoryRowByContent, navigateToAccountComponent, navigateToAuditLog, navigateToAuditLogAndWaitForData, navigateToDataReports, navigateToReportDownload, openAddItemsDialog, openAddMemoryDialog, openAgentLimitsManage, openAgentMemoriesPopup, openAgentPromptEditModal, openBenchmarkItems, openCallConfigVoicePicker, openCreateKeyModal, openCreateLinkModal, openCreateToolModal, openCreditBalanceDropdown, openEditInstanceDialog, openEditLinkModal, openEditSkillDialog, openEditToolModal, openFirstLogDetails, openHistoryTab, openInstanceActionsMenu, openKeyActionsMenu, openKeyDelete, openKeyDetail, openLLMProviderPicker, openManageBenchmarksDialog, openMentorVoicePicker, openNewInstanceDialog, openNewReviewForRun, openNewReviewFromDetail, openNewSkillDialog, openRunActionsMenu, openRunResults, openScheduleTaskDialog, openScreenSharePromptEditor, openSkillActionsMenu, openSlashSkillPicker, openStartEvaluationDialog, openTicket, openUserMemoriesPopup, openVoiceInstructionsEditor, overrideGradeResult, parseReportUrlParams, previewCallConfigVoiceInline, previewMentorVoiceInline, previewVoice, pushConfiguration, readEndpointUrl, readKeyPublicJwk, readKeyPublicKey, refreshEvaluationDetail, refreshLinks, refreshTickets, reliableClick, reliableFill, removeSkillFromAgent, removeTraceScore, renameKey, replyToTicket, requestSupportTicketViaChat, resetCallConfig, retry, retryFailedLink, runConnectedInstanceChecks, runInstanceChecks, safeWaitForURL, saveCallConfig, saveGraderConfig, saveScreenSharePrompts, saveVoiceSettings, scheduleTask, searchBenchmarks, searchInstances, searchMemoryAdminUsers, searchTasks, searchVoices, selectBenchmark, selectCallMode, selectConversation, selectDateFromCalendar, selectJudgeLlm, selectLLMModel, selectLlmProvider, selectPrivacyAction, selectPrivateMode, selectSlashSkill, selectSttProvider, selectTaskInList, selectToolKeySetMode, selectToolSigningKey, selectTtsProvider, selectVoice, selectVoiceProvider, sendAgentChatMessage, setAgentLimitsRowEnabled, setAgentSpendLimit, setAgentSpendLimitFromTenantBilling, setBlockMessage, setCallLanguage, setCatalogSkillEnabled, setEnableVideo, setEntitySelected, setGradingEnabled, setOutputFilterEnabled, setScreenSharePrompt, setSupportEnabled, setTenantChatPrivacyEnabled, setTicketStatus, setUseFunctionCallingEnabled, setUserSpendLimitEnabled, setVoiceInstructions, setWorkspaceSpendLimit, setupSandboxInstance, shouldAddNewRowWhenClickingAddRowButton, shouldAllowEditingCellValuesInCSVEditor, shouldCancelCombiningReports, shouldCloseCSVEditorWhenClickingCloseButton, shouldCloseCSVEditorWithoutSavingWhenClickingCancel, shouldCombineRecommendationReports, shouldDirectlyDownloadChatHistoryReportWithoutCSVEditor, shouldDisableOtherDownloadButtonsWhileGeneratingReport, shouldDisplayCSVInEditableTableFormat, shouldDisplayReportCards, shouldHaveCombinedReportDataTestIds, shouldOpenCSVEditorDialog, shouldOpenCSVEditorForUserMetadataReport, shouldSaveEditedCSVAndTriggerDownload, shouldShowCombiningReportsDialog, shouldVerifyCSVEditorDialogAccessibility, signUpWithEmailAndPassword, spendLimitsTabBody, startEvaluation, startHistoryExport, submitLinkModal, submitLlmJudge, submitToolModal, switchHistorySubTab, switchToAddItemsSubTab, switchToAgentLimits, switchToAgentSkillsSubTab, switchToAvailableSkillsSubTab, switchToEvaluationTab, switchToGraderSubTab, switchToGraderTab, switchToLtiSubTab, switchToLtiTab, switchToMemoryAdminSubTab, switchToMemoryTab, switchToPlanAndCredits, switchToPrivacyTab, switchToPrivateModeTab, switchToSandboxTab, switchToScreenShareTab, switchToSkillResourcesSubTab, switchToSkillsTab, switchToSpendLimitsSubTab, switchToSpendLimitsTab, switchToSupportTab, switchToTasksTab, switchToTenantMemoryTab, switchToVoiceSubTab, switchToVoiceTab, switchToWorkspaceSpendLimits, teardownSandboxInstance, test, toggleAutoPush, toggleMemorySwitch, toggleSkill, toggleUserMemoryAdminSetting, toolFields, uploadAssetResource, uploadQaCsv, userSpendLimitRow, verifyAgentConfigPromptsVisible, verifyAgentSkillsEmptyState, verifyAuditLogEmptyState, verifyAuditLogEntryStructure, verifyAuditLogGenericError, verifyAuditLogLoading, verifyAuditLogPermissionError, verifyAuditLogTableVisible, verifyConnectDisabledForUnhealthy, verifyConnectedInstanceCard, verifyCurrentPage, verifyDonePhase, verifyDownloadingPhase, verifyErrorPhase, verifyInstanceTableEmpty, verifyInstanceTableVisible, verifyMemoryExists, verifyMemoryNotExists, verifyMemoryTabMemoriesList, verifyMemoryTabSettings, verifyPreparingPhase, verifySkillAdded, verifySkillVisible, verifySkillsEmptyState, verifySkillsTabVisible, waitForAgentChatResponse, waitForAuditLogDataLoaded, waitForBillingTabReady, waitForCompletedExportRow, waitForConversations, waitForCreditBalanceLoaded, waitForDialogReady, waitForElementStable, waitForLinkReady, waitForPageLoad, waitForPageReady, waitForReportDownload, waitForTicketInList, workspaceSpendLimitSection };
8346
8695
  //# sourceMappingURL=index.esm.js.map