@aintela/chat 0.2.20 → 0.2.25

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 (32) hide show
  1. package/dist/{auth-CcTgInbY.js → auth-DbmLacBc.js} +2 -2
  2. package/dist/{auth-CcTgInbY.js.map → auth-DbmLacBc.js.map} +1 -1
  3. package/dist/components.js +5234 -4951
  4. package/dist/components.js.map +1 -1
  5. package/dist/hooks.js +5 -4
  6. package/dist/{httpArtifactService-BAR60Gu1.js → httpArtifactService-Dh9LGQ9a.js} +2 -2
  7. package/dist/{httpArtifactService-BAR60Gu1.js.map → httpArtifactService-Dh9LGQ9a.js.map} +1 -1
  8. package/dist/index.js +126 -122
  9. package/dist/{sortable-table-DgQHxWIh.js → promptHighlight-BHSQkdFs.js} +330 -282
  10. package/dist/promptHighlight-BHSQkdFs.js.map +1 -0
  11. package/dist/services.js +1 -1
  12. package/dist/src/components/AiChat/AiChatContext.d.ts +14 -2
  13. package/dist/src/components/AiChat/AiChatTypes.d.ts +28 -0
  14. package/dist/src/components/AiChat/ChatPane/AskUserSheet.d.ts +2 -1
  15. package/dist/src/components/AiChat/ChatPane/parts/AskAuthPart.d.ts +8 -0
  16. package/dist/src/components/AiChat/ChatPane/parts/types.d.ts +6 -1
  17. package/dist/src/components/index.d.ts +1 -1
  18. package/dist/src/components/v2/PromptDateMarkers.d.ts +15 -0
  19. package/dist/src/components/v2/PromptV2.d.ts +25 -0
  20. package/dist/src/components/v2/index.d.ts +2 -0
  21. package/dist/src/hooks/index.d.ts +2 -0
  22. package/dist/src/hooks/usePromptAssist.d.ts +64 -0
  23. package/dist/src/services/httpPromptAssistService.d.ts +77 -0
  24. package/dist/src/utils/index.d.ts +2 -0
  25. package/dist/src/utils/promptHighlight.d.ts +16 -0
  26. package/dist/useContainerWidth-0EA-kdzl.js +260 -0
  27. package/dist/useContainerWidth-0EA-kdzl.js.map +1 -0
  28. package/dist/utils.js +34 -32
  29. package/package.json +1 -1
  30. package/dist/sortable-table-DgQHxWIh.js.map +0 -1
  31. package/dist/useContainerWidth-Df2PmSoC.js +0 -52
  32. package/dist/useContainerWidth-Df2PmSoC.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptHighlight-BHSQkdFs.js","sources":["../src/utils/urlParser.ts","../src/utils/stringUtils.ts","../src/utils/interactionIdChecker.ts","../src/utils/sortable-table.js","../src/utils/promptHighlight.ts"],"sourcesContent":["export const parseAndValidateArtifactUrl = (url: string): string | null => {\n if (url[0] == \"#\")\n return null;\n\n const urlParts = url.split(\"/\");\n let lastPart = urlParts[urlParts.length - 1];\n if (lastPart == \"\" && urlParts.length > 1)\n lastPart = urlParts[urlParts.length - 2];\n if (lastPart == \"\")\n return null;\n\n const removedUrlParams = lastPart.split(\"?\")[0];\n const removedUrlHash = removedUrlParams.startsWith(\"#\") ? removedUrlParams : removedUrlParams.split(\"#\")[0];\n const stripExtension = removedUrlHash;\n return stripExtension;\n}\n\n/*\nlink can be:\n#openartifact:qual-é-o-valor-total-de-tarifas-em-maio?\n#openartifact:e97c89936040425cba07d42a4e89c2bb_valor_medio_por_num_passageiros.png\n#openartifact:http://localhost:8000/static/artifacts/e97c89936040425cba07d42a4e89c2bb_valor_medio_por_num_passageiros.png\n\ncontent can be:\nQual é o valor total de tarifas em maio?\n*/\n// export const extractLinkAction = (link: string, content: string | null): { artifactId: string | null, question: string | null } => {\n\n// const parts = link.split(\"-\");\n// if (parts[0] && parts[0] == \"#openartifact\") {\n// const artifactId = decodeURIComponent(parts.slice(1).join(\"-\"));\n// if (artifactId == \"\") {\n// return { artifactId: null, question: null };\n// }\n// else {\n// return { artifactId: artifactId, question: null };\n// }\n// }\n// else if (link[0] !== \"#\") {\n// return { artifactId: null, question: null };\n// }\n// else {\n// if (!content) {\n// const extractedArtifactId = parseAndValidateArtifactUrl(link);\n// if (extractedArtifactId) {\n// return { artifactId: extractedArtifactId, question: null };\n// }\n// else if (isValidUri(link)) { //to not transform a mal formed full URL into a question\n// return { artifactId: null, question: null };\n// }\n// }\n// }\n// content = content == \"\" ? null : content;\n// if (link || content) {\n// return { artifactId: null, question: content ?? link };\n// }\n// else {\n// console.warn(\"Unknown link format: \", link, content);\n// return { artifactId: null, question: null };\n// }\n// }\n\nexport type LinkAction = 'Export' | 'Question' | 'OpenDashboard' | 'URL'\n\nexport const extractLinkAction = (link: string, sessionId: string, content: string | null): { action: LinkAction, url: string | null, question: string | null, parameter: string | null } => {\n let action: LinkAction = 'URL';\n let question: string | null = null;\n let url: string | null = null;\n let parameter: string | null = null;\n if (link[0] == '#') {\n const firstDash = link.indexOf(\"-\");\n const firstPart = link.slice(1, firstDash);\n parameter = link.slice(firstDash + 1);\n switch (firstPart.toLowerCase()) {\n case \"opendashboard\":\n action = 'OpenDashboard'\n break;\n case \"ask\":\n action = 'Question'\n question = content\n break;\n }\n }\n else {\n if (link.indexOf(\"http\") > -1) {\n action = 'URL'\n url = link\n }\n else {\n link = link.replaceAll(\"exported/\", `exported/${sessionId}/`)\n action = 'Export'\n }\n }\n\n return { action, url, question, parameter }\n}","export const chunkArray = (char: string[], size: number): string[][] =>\n Array.from({ length: Math.ceil(char.length / size) }, (_v, i) =>\n char.slice(i * size, i * size + size)\n );\n\nexport const splitBigLinesWithSpaces = (content: string): string => {\n // If content already contains newlines or is short, return as-is\n content = content.replaceAll(\"\\\\n\", \"\\n\");\n\n const limit = 90;\n\n const whiteSpaceBreak = content.split(\" \");\n const allWords: string[] = []\n let hadOne = false;\n for (const word of whiteSpaceBreak) {\n if (word.length > limit) {\n hadOne = true;\n const charArray = [...word];\n const chunkedText = chunkArray(charArray, limit);\n const chunkedWord = chunkedText.map(chunk => chunk.join(\"\")).join(\"\\n\");\n allWords.push(chunkedWord);\n }\n else {\n allWords.push(word);\n }\n }\n\n return hadOne ? allWords.join(\" \") : content;\n}\n\nexport function parseRawNumber(text: string): number {\n let number = parseFloat(text);\n if (!isNaN(number)) {\n text = text.replaceAll(/[,\\.]/g, '');\n return parseInt(text);\n }\n\n var finalNumber = \"\"\n for (const char of text) {\n if (char.match(/[0-9]/)) {\n finalNumber += char;\n }\n }\n\n const ratio = finalNumber.length / text.length;\n number = parseInt(finalNumber);\n if (!isNaN(number) && ratio > 0.5) {\n return number;\n }\n\n return NaN;\n}\n\nexport function parseKnownNumbers(text?: string): { prefix?: string, suffix?: string, number?: number } {\n if (!text) return { prefix: undefined, suffix: undefined, number: undefined };\n\n const knownChars = /[$%(\\w?\\$)]/gi;\n const currencySymbol = /[a-z]?\\$/gi;\n\n let prefix = \"\";\n let suffix = \"\";\n\n if (text.match(knownChars)) {\n if (text.indexOf(\"%\") > -1) {\n suffix = \" %\"\n }\n const match = text.match(currencySymbol)\n if (match) {\n prefix = match[0] + \" \";\n }\n }\n\n let number = parseFloat(text);\n\n if (!isNaN(number)) {\n text = text.replaceAll(\".\", '').replaceAll(\",\", \".\");\n return { prefix, suffix, number: parseFloat(text) };\n }\n\n var finalNumber = \"\"\n for (const char of text) {\n if (char.match(/[0-9.,]/)) {\n let replacedChar = char;\n if (replacedChar == '.')\n replacedChar = \"\"\n else if (replacedChar == \",\")\n replacedChar = \".\"\n finalNumber += replacedChar;\n }\n }\n\n number = parseFloat(finalNumber);\n if (!isNaN(number)) {\n return { prefix, suffix, number: number };\n }\n\n return { prefix: undefined, suffix: undefined, number: undefined };;\n}","/**\n * Utility function to check if a string starts with an interaction ID (UUID)\n * Supports both formats:\n * - With dashes: ebd067ef-0dbd-49b3-8eff-c54b2a9ff314\n * - Without dashes: 62ec037ae42c439192c64dd112136583\n */\n\n/**\n * Regular expression for UUID with dashes (standard format)\n * Format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n */\nconst UUID_WITH_DASHES_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;\n\n/**\n * Regular expression for UUID without dashes (compact format)\n * Format: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (32 hex characters)\n */\nconst UUID_WITHOUT_DASHES_REGEX = /^[0-9a-f]{32}/i;\n\n/**\n * Check if a string starts with an interaction ID (UUID)\n * @param str - The string to check\n * @returns true if the string starts with a valid UUID, false otherwise\n */\nexport function startsWithInteractionId(str: string): boolean {\n if (!str || typeof str !== 'string') {\n return false;\n }\n\n const interactionId = extractInteractionId(str);\n\n return interactionId === null ? false : str.startsWith(interactionId);\n}\n\n/**\n * Extract the interaction ID from the beginning of a string\n * @param str - The string to extract from\n * @returns The interaction ID if found, null otherwise\n */\nexport function extractInteractionId(str: string): string | null {\n if (!str || typeof str !== 'string') {\n return null;\n }\n\n // Try to match UUID with dashes first\n const withDashesMatch = str.match(UUID_WITH_DASHES_REGEX);\n if (withDashesMatch) {\n return withDashesMatch[0];\n }\n\n // Try to match UUID without dashes\n const withoutDashesMatch = str.match(UUID_WITHOUT_DASHES_REGEX);\n if (withoutDashesMatch) {\n return withoutDashesMatch[0];\n }\n\n return null;\n}\n\nexport function prettiffyFileName(fileName: string) {\n const prettyName = fileName.replaceAll(\"_\", \" \").replaceAll(\"-\", \" \");\n const userRemoved = prettyName.replaceAll(\"user:\", \"\");\n const withNoExtension = userRemoved.replace(/\\.[^/.]+$/, \"\");\n const withNoInteractionId = extractNameFromStringWithInteractionId(withNoExtension).trim();\n if (withNoInteractionId.length > 1)\n return withNoInteractionId[0].toUpperCase() + withNoInteractionId.slice(1);\n else\n return withNoInteractionId;\n}\n\nexport function prettiffyPythonFunctionName(functionName: string) {\n if (functionName.length == 0)\n return functionName;\n\n const prettyName = functionName.replaceAll(\"_\", \" \").replaceAll(\"-\", \" \");\n const withFirstCapitalLetter = prettyName[0].toUpperCase() + prettyName.slice(1);\n\n return withFirstCapitalLetter;\n}\n\nexport function extractNameFromStringWithInteractionId(str: string): string {\n // Try to match UUID with dashes first and remove it\n const withDashesMatch = str.match(UUID_WITH_DASHES_REGEX);\n if (withDashesMatch) {\n return str.replace(withDashesMatch[0], \"\");\n }\n\n // Try to match UUID without dashes\n const withoutDashesMatch = str.match(UUID_WITHOUT_DASHES_REGEX);\n if (withoutDashesMatch) {\n return str.replace(withoutDashesMatch[0], \"\");\n }\n\n return str;\n}\n\n/**\n * Check if a string is a valid interaction ID (UUID) on its own\n * @param str - The string to check\n * @returns true if the string is a valid UUID, false otherwise\n */\nexport function isValidInteractionId(str: string): boolean {\n if (!str || typeof str !== 'string') {\n return false;\n }\n\n // Check if it's exactly a UUID with dashes\n if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(str)) {\n return true;\n }\n\n // Check if it's exactly a UUID without dashes\n if (/^[0-9a-f]{32}$/i.test(str)) {\n return true;\n }\n\n return false;\n}\n","/**\n * SortableTable - A pure JavaScript library for making tables sortable\n * \n * Features:\n * - Automatically scans document for tables\n * - Supports tables with or without thead elements (converts first row to header if needed)\n * - Adds Material UI icons to column headers\n * - Supports text, number, and date sorting\n * - Visual feedback for sort direction\n * - Preserves existing table styling\n */\n\nconst initializedTables = new Set(); // Track which tables have been initialized\n\nimport { parseRawNumber } from './stringUtils';\n\nclass SortableTable {\n constructor(options = {}) {\n this.options = {\n // CSS class for sortable headers\n sortableClass: 'sortable-header',\n // CSS class for active sort\n activeSortClass: 'active-sort',\n // CSS class for ascending sort\n ascendingClass: 'sort-asc',\n // CSS class for descending sort\n descendingClass: 'sort-desc',\n // Icon for unsorted state\n unsortedIcon: 'unfold_more',\n // Icon for ascending sort\n ascendingIcon: 'keyboard_arrow_up',\n // Icon for descending sort\n descendingIcon: 'keyboard_arrow_down',\n // Whether to sort on first click (true) or cycle through states (false)\n sortOnFirstClick: true,\n // Custom sort functions for specific columns\n customSorters: {},\n // Columns to exclude from sorting (0-based index)\n excludeColumns: [],\n // Whether to preserve existing icons in headers\n preserveExistingIcons: false,\n // Enable column resizing\n enableResizing: true,\n // Enable column reordering\n enableReordering: true,\n // CSS class for resizable columns\n resizableClass: 'resizable-column',\n // CSS class for draggable columns\n draggableClass: 'draggable-column',\n // CSS class for drag placeholder\n dragPlaceholderClass: 'drag-placeholder',\n // CSS class for drag over state\n dragOverClass: 'drag-over',\n theme: {\n palette: {\n primary: {\n main: '#999',\n },\n background: {\n default: '#fff',\n paper: '#555',\n },\n text: {\n primary: \"#000\",\n secondary: \"#999\",\n disabled: \"#BBB\",\n },\n surface: {\n panel: \"#999\",\n raised: \"#999\",\n hover: \"#444\",\n },\n divider: \"#999\",\n border: {\n default: \"#999\",\n soft: \"#BBB\",\n },\n },\n shape: {\n borderRadius: 7,\n radiusSm: 1,\n radiusLg: 10,\n },\n },\n ...options\n };\n\n this.tables = [];\n this.sortStates = new Map(); // Track sort state for each table\n this.originalColumnOrder = new Map(); // Track original column order\n this.isDragging = false;\n this.dragSource = null;\n this.dragTarget = null;\n this.charWidth = 0;\n }\n\n /**\n * Initialize the library - scan document for tables and make them sortable\n * @param {HTMLElement} container - Optional container element to limit search scope\n */\n init(container = null) {\n if (this.charWidth == 0)\n this.charWidth = this.getCharWidth(this.options.theme.typography.fontFamily, this.options.theme.typography.fontMono)\n\n this.scanTables(container);\n this.makeTablesSortable();\n this.addStyles();\n }\n\n /**\n * Scan for tables in the document or within a specific container\n * @param {HTMLElement} container - Optional container element to limit search scope\n */\n scanTables(container = null) {\n const searchScope = container || document;\n const tables = searchScope.querySelectorAll('table');\n this.tables = Array.from(tables);\n }\n\n /**\n * Make all found tables sortable\n */\n makeTablesSortable() {\n this.tables.forEach((table, tableIndex) => {\n this.makeTableSortable(table, tableIndex);\n });\n }\n\n /**\n * Make a specific table sortable\n */\n makeTableSortable(table, tableIndex) {\n let thead = table.querySelector('thead');\n let headerRow = null;\n let headers = [];\n\n // Check if table has a proper thead\n if (thead) {\n headerRow = thead.querySelector('tr');\n if (headerRow) {\n headers = headerRow.querySelectorAll('th');\n }\n }\n\n if (headers.length === 0) {\n console.warn('Table has no sortable columns, skipping');\n return;\n }\n // First-time-only arrival animation. ChatPane's effect\n // destroys + re-inits the SortableTable on every `messages`\n // update, so a CSS animation tied to `.sortable-table`\n // alone would replay on each new chunk and feel jittery.\n // The DOM attribute persists across destroy/init cycles\n // (destroy() doesn't touch table attributes), so it cleanly\n // marks \"this table has already arrived once.\"\n const isFirstSortableMount = !table.hasAttribute('data-sortable-arrived');\n // Add sortable-table class for styling\n table.classList.add('sortable-table');\n if (isFirstSortableMount) {\n table.setAttribute('data-sortable-arrived', 'true');\n table.classList.add('sortable-table-arriving');\n // Drop the trigger class after the animation finishes so\n // it can't fire again if the table is somehow re-added to\n // a different DOM position.\n setTimeout(() => {\n table.classList.remove('sortable-table-arriving');\n }, 400);\n }\n\n // Calculate intelligent table width based on header text length\n //const calculatedWidth = this.calculateTableWidth(table);\n // table.style.width = 'auto';\n // table.style.minWidth = '80%';\n //table.style.tableLayout = 'fixed'; // Use fixed layout to respect manual widths\n\n // Cell styles are now handled by CSS only\n\n // Initialize sort state for this table\n this.sortStates.set(tableIndex, {\n currentColumn: -1,\n direction: 'none'\n });\n\n // Capture the table's pre-transform width once so calculateTableWidth\n // can use it as a floor. Persisted as a data attribute (like\n // data-sortable-arrived) so it survives ChatPane's destroy/init\n // cycle — re-reading on every mount would pick up the inline\n // width left behind by the previous calculation, not the\n // natural width the user originally saw.\n if (!table.hasAttribute('data-original-width')) {\n table.setAttribute('data-original-width', table.getBoundingClientRect().width);\n }\n\n this.applyTableStyles(table);\n\n // Store original column order\n this.originalColumnOrder.set(tableIndex, Array.from(headers).map((_, index) => index));\n\n // Make each header sortable\n headers.forEach((header, columnIndex) => {\n if (this.options.excludeColumns.includes(columnIndex)) {\n return;\n }\n\n this.makeHeaderSortable(header, table, tableIndex, columnIndex);\n });\n\n // Replace exponential values in all cells with full numbers\n this.replaceExponentialValues(table);\n\n // Mark this table as initialized\n initializedTables.add(table);\n }\n\n /**\n * Replace exponential values in table cells with full numbers\n * @param {HTMLElement} table - The table to process\n */\n replaceExponentialValues(table) {\n const tbody = table.querySelector('tbody');\n if (!tbody) return;\n\n const rows = tbody.querySelectorAll('tr');\n rows.forEach(row => {\n const cells = row.querySelectorAll('td, th');\n cells.forEach(cell => {\n const text = cell.textContent.trim();\n const exponentialMatch = text.match(/^([\\d,]+\\.?\\d*)[eE][+-]?(\\d+)$/);\n\n if (exponentialMatch) {\n const base = parseFloat(exponentialMatch[1].replace(/,/g, ''));\n const exponent = parseInt(exponentialMatch[2]);\n const fullNumber = base * Math.pow(10, exponent);\n\n // Format the number with commas for readability\n const formattedNumber = this.formatNumber(fullNumber);\n cell.textContent = formattedNumber;\n }\n });\n });\n }\n\n /**\n * Format a number with commas for readability\n * @param {number} num - The number to format\n * @returns {string} The formatted number\n */\n formatNumber(num) {\n if (num === 0) return '0';\n\n // Handle very large or very small numbers\n if (Math.abs(num) >= 1e12) {\n return (num / 1e12).toFixed(2) + 'T';\n } else if (Math.abs(num) >= 1e9) {\n return (num / 1e9).toFixed(2) + 'B';\n } else if (Math.abs(num) >= 1e6) {\n return (num / 1e6).toFixed(2) + 'M';\n } else if (Math.abs(num) >= 1e3) {\n return (num / 1e3).toFixed(2) + 'K';\n } else if (Math.abs(num) < 0.01 && num !== 0) {\n return num.toExponential(2);\n } else {\n return num.toLocaleString();\n }\n }\n\n /**\n * Convert the first row to a header row\n * @param {HTMLElement} firstRow - The first row to convert\n * @param {HTMLElement} thead - The thead element to append to\n * @param {HTMLElement} tbody - The tbody element to remove from\n * @returns {HTMLElement} The converted header row\n */\n convertRowToHeader(firstRow, thead, tbody) {\n try {\n // Clone the row\n const headerRow = firstRow.cloneNode(true);\n\n // Convert all td elements to th elements\n const cells = headerRow.querySelectorAll('td');\n cells.forEach(td => {\n const th = document.createElement('th');\n\n // Copy all attributes\n Array.from(td.attributes).forEach(attr => {\n th.setAttribute(attr.name, attr.value);\n });\n\n // Copy content\n th.innerHTML = td.innerHTML;\n\n // Copy styles\n th.style.cssText = td.style.cssText;\n\n // Replace td with th\n td.parentNode.replaceChild(th, td);\n });\n\n // Remove the original first row from tbody\n if (tbody && tbody.contains(firstRow)) {\n tbody.removeChild(firstRow);\n } else if (firstRow.parentNode) {\n firstRow.parentNode.removeChild(firstRow);\n }\n\n // Add the header row to thead\n thead.appendChild(headerRow);\n\n return headerRow;\n\n } catch (error) {\n console.error('Error converting row to header:', error);\n return null;\n }\n }\n\n /**\n * Make a specific header sortable\n */\n makeHeaderSortable(header, table, tableIndex, columnIndex) {\n // Add sortable class\n header.classList.add(this.options.sortableClass);\n\n // Add cursor pointer\n header.style.cursor = 'pointer';\n\n // Add sort icon if not preserving existing icons\n if (!this.options.preserveExistingIcons || !header.querySelector('.material-icons')) {\n this.addSortIcon(header);\n }\n\n // Add resizing functionality\n if (this.options.enableResizing) {\n this.addResizing(header, table, tableIndex, columnIndex);\n }\n\n // Add drag and drop functionality\n if (this.options.enableReordering) {\n this.addDragAndDrop(header, table, tableIndex, columnIndex);\n // Note: We rely on header drop targets only for better reliability\n }\n\n const clickListener = (e) => {\n e.preventDefault();\n this.sortTable(table, tableIndex, columnIndex);\n }\n\n const mouseEnterListener = (e) => {\n if (!header.classList.contains(this.options.activeSortClass)) {\n header.style.background = this.options.theme.palette.surface.hover;\n }\n }\n\n const mouseLeaveListener = (e) => {\n if (!header.classList.contains(this.options.activeSortClass)) {\n header.style.background = '';\n }\n }\n\n header.removeEventListener('click', clickListener);\n const resp = header.addEventListener('click', clickListener);\n header.removeEventListener('mouseenter', mouseEnterListener);\n header.addEventListener('mouseenter', mouseEnterListener);\n header.removeEventListener('mouseleave', mouseLeaveListener);\n header.addEventListener('mouseleave', mouseLeaveListener);\n }\n\n /**\n * Add sort icon to header\n */\n addSortIcon(header) {\n if (header.querySelector('.sortable-table-icon')) {\n return;\n }\n\n const icon = document.createElement('i');\n icon.id = 'sortable-table-icon';\n icon.className = 'material-icons';\n icon.textContent = this.options.unsortedIcon;\n icon.style.marginRight = '2px';\n icon.style.fontSize = '12px';\n icon.style.verticalAlign = 'middle';\n // Start invisible, then animate to the resting opacity on a\n // later frame so the existing `.sortable-header .material-icons\n // { transition: opacity 0.2s ease }` rule fades in instead of\n // popping in alongside the rest of the table transformation.\n // Double-rAF guarantees the browser paints the 0 state first;\n // a single rAF can be coalesced into the insertion frame in\n // some engines and skip the transition.\n icon.style.opacity = '0';\n\n const existingIcon = header.querySelector('.material-icons');\n if (!existingIcon) {\n header.insertBefore(icon, header.firstChild);\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n icon.style.opacity = '0.6';\n });\n });\n }\n }\n\n /**\n * Sort table by column\n */\n sortTable(table, tableIndex, columnIndex) {\n const tbody = table.querySelector('tbody');\n if (!tbody) {\n console.warn('Table has no tbody element');\n return;\n }\n\n const rows = Array.from(tbody.querySelectorAll('tr'));\n if (rows.length === 0) {\n console.warn('Table has no data rows');\n return;\n }\n\n const sortState = this.sortStates.get(tableIndex);\n const header = table.querySelector(`thead tr th:nth-child(${columnIndex + 1})`);\n\n // Determine sort direction\n let newDirection;\n if (this.options.sortOnFirstClick) {\n newDirection = sortState.currentColumn === columnIndex && sortState.direction === 'asc' ? 'desc' : 'asc';\n } else {\n if (sortState.currentColumn !== columnIndex) {\n newDirection = 'asc';\n } else {\n newDirection = sortState.direction === 'none' ? 'asc' :\n sortState.direction === 'asc' ? 'desc' : 'none';\n }\n }\n\n // Update sort state\n sortState.currentColumn = columnIndex;\n sortState.direction = newDirection;\n this.sortStates.set(tableIndex, sortState);\n\n // Update visual indicators\n this.updateSortIndicators(table, tableIndex, columnIndex, newDirection);\n\n // If direction is 'none', restore original order\n if (newDirection === 'none') {\n this.restoreOriginalOrder(table, rows);\n return;\n }\n\n // Sort the rows\n const sortedRows = this.sortRows(rows, columnIndex, newDirection);\n\n // Re-append sorted rows\n sortedRows.forEach(row => tbody.appendChild(row));\n }\n\n /**\n * Sort rows based on column data\n */\n sortRows(rows, columnIndex, direction) {\n return rows.sort((a, b) => {\n const cellA = a.cells[columnIndex];\n const cellB = b.cells[columnIndex];\n\n if (!cellA || !cellB) return 0;\n\n const valueA = this.extractValue(cellA);\n const valueB = this.extractValue(cellB);\n\n // Use custom sorter if available\n if (this.options.customSorters[columnIndex]) {\n return this.options.customSorters[columnIndex](valueA, valueB, direction);\n }\n\n // Default sorting logic\n const comparison = this.compareValues(valueA, valueB);\n return direction === 'asc' ? comparison : -comparison;\n });\n }\n\n /**\n * Extract sortable value from cell\n */\n extractValue(cell) {\n let text = cell.textContent.trim();\n\n let number = parseRawNumber(text);\n if (!isNaN(number)) {\n console.log(number);\n return number;\n }\n\n // Remove all material icons and common symbols from the text\n text = text.replace(/arrow_upward|arrow_downward|remove|keyboard_arrow_up|keyboard_arrow_down|unfold_more|expand_more|expand_less|trending_up|trending_down|↗|↘|↑|↓|→|←/g, '').trim();\n\n // Handle N/A, N/D, ND, blank and variants as -1\n const naVariants = /^(N\\/A|N\\/D|ND|N\\/A|n\\/a|n\\/d|nd|N\\/A|N\\/D|ND|\\s*)$/i;\n if (naVariants.test(text)) {\n return -1;\n }\n\n // Try to parse as percentage\n const percentageMatch = text.match(/^([\\d,]+\\.?\\d*)\\s*%$/);\n if (percentageMatch) {\n return parseFloat(percentageMatch[1].replace(/,/g, ''));\n }\n\n // Try to parse as exponential notation (scientific notation)\n const exponentialMatch = text.match(/^([\\d,]+\\.?\\d*)[eE][+-]?(\\d+)$/);\n if (exponentialMatch) {\n const base = parseFloat(exponentialMatch[1].replace(/,/g, ''));\n const exponent = parseInt(exponentialMatch[2]);\n return base * Math.pow(10, exponent);\n }\n\n // Try to parse as number\n const numberMatch = text.match(/^[\\d,]+\\.?\\d*[KMB]?$/);\n if (numberMatch) {\n return this.parseNumber(text);\n }\n\n // Try to parse as currency\n const currencyMatch = text.match(/^R\\$\\s*([\\d,]+\\.?\\d*)$/);\n if (currencyMatch) {\n return this.parseNumber(currencyMatch[1]);\n }\n\n // Try to parse as date\n const date = new Date(text);\n if (!isNaN(date.getTime())) {\n return date.getTime();\n }\n\n // Return as string (case-insensitive)\n return text.toLowerCase();\n }\n\n /**\n * Compare two values for sorting\n */\n compareValues(a, b) {\n // Handle null/undefined values\n if (a == null && b == null) return 0;\n if (a == null) return -1;\n if (b == null) return 1;\n\n // Handle different types\n if (typeof a !== typeof b) {\n return String(a).localeCompare(String(b));\n }\n\n // Handle numbers\n if (typeof a === 'number') {\n return a - b;\n }\n\n // Handle dates\n if (a instanceof Date) {\n return a.getTime() - b.getTime();\n }\n\n // Handle strings\n return a.localeCompare(b);\n }\n\n /**\n * Update visual indicators for sort state\n */\n updateSortIndicators(table, tableIndex, columnIndex, direction) {\n const headers = table.querySelectorAll('thead tr th');\n\n // Reset all headers\n headers.forEach((header, index) => {\n header.classList.remove(this.options.activeSortClass, this.options.ascendingClass, this.options.descendingClass);\n const icon = header.querySelector('.material-icons');\n if (icon) {\n icon.textContent = this.options.unsortedIcon;\n icon.style.opacity = '0.6';\n }\n });\n\n // Update active header\n if (direction !== 'none') {\n const activeHeader = headers[columnIndex];\n activeHeader.classList.add(this.options.activeSortClass);\n\n const icon = activeHeader.querySelector('.material-icons');\n if (icon) {\n if (direction === 'asc') {\n activeHeader.classList.add(this.options.ascendingClass);\n icon.textContent = this.options.ascendingIcon;\n } else {\n activeHeader.classList.add(this.options.descendingClass);\n icon.textContent = this.options.descendingIcon;\n }\n icon.style.opacity = '1';\n }\n }\n }\n\n /**\n * Restore original order (when sort direction is 'none')\n */\n restoreOriginalOrder(table, rows) {\n // This is a simplified implementation\n // In a real scenario, you might want to store the original order\n const tbody = table.querySelector('tbody');\n rows.forEach(row => tbody.appendChild(row));\n }\n\n /**\n * Add resizing functionality to a header\n */\n addResizing(header, table, tableIndex, columnIndex) {\n header.classList.add(this.options.resizableClass);\n header.style.position = 'relative';\n\n\n if (header.querySelector('.resize-handle')) {\n return;\n }\n\n const resizeHandle = document.createElement('div');\n resizeHandle.className = 'resize-handle';\n resizeHandle.style.cssText = `\n position: absolute;\n top: 0;\n right: 0;\n width: 4px;\n height: 100%;\n background: transparent;\n cursor: col-resize;\n z-index: 10;\n `;\n\n header.appendChild(resizeHandle);\n\n let isResizing = false;\n let startX = 0;\n let startWidth = 0;\n\n resizeHandle.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation(); // Prevent sort from triggering\n isResizing = true;\n startX = e.clientX;\n startWidth = header.offsetWidth;\n\n // Add visual feedback\n header.style.borderRight = '2px solid var(--primary-main, #2196F3)';\n header.style.background = 'var(--background-active, rgba(255, 255, 255, 0.1))';\n\n document.addEventListener('mousemove', handleResize);\n document.addEventListener('mouseup', stopResize);\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n });\n\n const handleResize = (e) => {\n if (!isResizing) return;\n const newWidth = startWidth + (e.clientX - startX);\n if (newWidth > 30) { // Minimum width\n header.style.width = newWidth + 'px';\n\n // Set the same width on all cells in this column\n const columnIndex = Array.from(header.parentNode.children).indexOf(header);\n const tbody = table.querySelector('tbody');\n if (tbody) {\n const rows = tbody.querySelectorAll('tr');\n rows.forEach(row => {\n const cell = row.children[columnIndex];\n if (cell) {\n cell.style.width = newWidth + 'px';\n }\n });\n }\n\n // Update table width if column width increased\n this.updateTableWidth(table);\n }\n };\n\n const stopResize = () => {\n isResizing = false;\n\n // Remove visual feedback\n header.style.borderRight = '';\n header.style.background = '';\n\n document.removeEventListener('mousemove', handleResize);\n document.removeEventListener('mouseup', stopResize);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n };\n }\n\n /**\n * Add drag and drop functionality to a header\n */\n addDragAndDrop(header, table, tableIndex, columnIndex) {\n if (header.querySelector('.drag-handle')) {\n return;\n }\n\n header.classList.add(this.options.draggableClass);\n header.draggable = true;\n\n const thead = table.querySelector('thead tr');\n\n header.addEventListener('dragstart', (e) => {\n this.isDragging = true;\n // Store the current DOM position, not the original column index\n const currentPosition = Array.from(thead.children).indexOf(header);\n this.dragSource = { table, tableIndex, columnIndex: currentPosition };\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/html', header.outerHTML);\n const headerContent = header.outerHTML;\n header.style.opacity = '0.5';\n\n // Create a custom drag image\n this.createCustomDragImage(e, header, headerContent);\n });\n\n header.addEventListener('dragend', (e) => {\n this.isDragging = false;\n this.dragSource = null;\n header.style.opacity = '';\n // Remove all column highlights\n this.clearAllColumnHighlights(table);\n });\n\n header.addEventListener('dragover', (e) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n });\n\n header.addEventListener('dragenter', (e) => {\n e.preventDefault();\n if (this.dragSource && this.dragSource.tableIndex === tableIndex) {\n const currentColumnIndex = Array.from(thead.children).indexOf(header);\n if (this.dragSource.columnIndex !== currentColumnIndex) {\n // Add visual feedback to the entire column\n this.highlightColumn(table, currentColumnIndex, true);\n }\n }\n });\n\n header.addEventListener('dragleave', (e) => {\n // Only remove highlight if we're leaving the entire column\n if (!header.contains(e.relatedTarget)) {\n const currentColumnIndex = Array.from(thead.children).indexOf(header);\n this.highlightColumn(table, currentColumnIndex, false);\n }\n });\n\n header.addEventListener('drop', (e) => {\n e.preventDefault();\n\n if (this.dragSource && this.dragSource.tableIndex === tableIndex) {\n const currentColumnIndex = Array.from(thead.children).indexOf(header);\n if (this.dragSource.columnIndex !== currentColumnIndex) {\n this.reorderColumns(table, tableIndex, this.dragSource.columnIndex, currentColumnIndex);\n }\n }\n\n // Remove all column highlights\n this.clearAllColumnHighlights(table);\n });\n }\n\n /**\n * Create a custom drag image for better UX\n */\n createCustomDragImage(e, header, headerContent) {\n // Create a temporary element for the drag image\n const dragImage = document.createElement('div');\n dragImage.style.cssText = `\n position: absolute;\n top: -1000px;\n left: -1000px;\n background: var(--background-elevated, #333);\n border: 2px solid var(--primary-main, #2196F3);\n border-radius: 4px;\n padding: 8px 12px;\n font-size: 12px;\n font-weight: bold;\n color: var(--text-primary, #fff);\n white-space: nowrap;\n max-width: 150px;\n min-width: 60px;\n overflow: hidden;\n text-overflow: ellipsis;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n z-index: 10000;\n pointer-events: none;\n min-height: 50px;\n display: flex;\n align-items: center;\n `;\n\n // Get the header text without icons and create a compact representation\n const headerText = headerContent;\n dragImage.innerHTML = `\n <div style=\"display: flex; align-items: center; gap: 5px; align-content: center;color:white;\">\n <span style=\"overflow: hidden; text-overflow: ellipsis\">${headerText}</span>\n <svg style=\"fill: grey; font-size: 10px\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" ><defs><path id=\"a\" d=\"M0 0h24v24H0V0z\"/></defs><clipPath id=\"b\"><use xlink:href=\"#a\" overflow=\"visible\"/></clipPath><path clip-path=\"url(#b)\" d=\"M9.01 14H2v2h7.01v3L13 15l-3.99-4v3zm5.98-1v-3H22V8h-7.01V5L11 9l3.99 4z\"/></svg>\n </div> \n `;\n\n // Add to document temporarily\n document.body.appendChild(dragImage);\n\n // Set as drag image with centered offset\n e.dataTransfer.setDragImage(dragImage, 50, 12);\n\n // Clean up after a short delay\n setTimeout(() => {\n if (document.body.contains(dragImage)) {\n document.body.removeChild(dragImage);\n }\n }, 100);\n }\n\n\n\n /**\n * Highlight an entire column during drag operations\n */\n highlightColumn(table, columnIndex, highlight) {\n const thead = table.querySelector('thead tr');\n const tbody = table.querySelector('tbody');\n\n if (!thead || !tbody) return;\n\n const header = thead.children[columnIndex];\n if (!header) return;\n\n if (highlight) {\n header.classList.add(this.options.dragOverClass);\n // Highlight all cells in this column\n const rows = tbody.children;\n for (let i = 0; i < rows.length; i++) {\n const cell = rows[i].children[columnIndex];\n if (cell) {\n cell.classList.add(this.options.dragOverClass);\n }\n }\n } else {\n header.classList.remove(this.options.dragOverClass);\n // Remove highlight from all cells in this column\n const rows = tbody.children;\n for (let i = 0; i < rows.length; i++) {\n const cell = rows[i].children[columnIndex];\n if (cell) {\n cell.classList.remove(this.options.dragOverClass);\n }\n }\n }\n }\n\n /**\n * Clear all column highlights\n */\n clearAllColumnHighlights(table) {\n const thead = table.querySelector('thead tr');\n const tbody = table.querySelector('tbody');\n\n if (!thead || !tbody) return;\n\n // Clear header highlights\n const headers = thead.children;\n for (let i = 0; i < headers.length; i++) {\n headers[i].classList.remove(this.options.dragOverClass);\n }\n\n // Clear cell highlights\n const rows = tbody.children;\n for (let i = 0; i < rows.length; i++) {\n const cells = rows[i].children;\n for (let j = 0; j < cells.length; j++) {\n cells[j].classList.remove(this.options.dragOverClass);\n }\n }\n }\n\n /**\n * Reorder columns in a table\n */\n reorderColumns(table, tableIndex, fromIndex, toIndex) {\n const thead = table.querySelector('thead tr');\n const tbody = table.querySelector('tbody');\n\n if (!thead || !tbody) return;\n\n const headers = Array.from(thead.children);\n const rows = Array.from(tbody.children);\n\n // Validate indices\n if (fromIndex < 0 || fromIndex >= headers.length || toIndex < 0 || toIndex >= headers.length) {\n console.warn('Invalid column indices for reordering');\n return;\n }\n\n // Don't do anything if dropping on the same position\n if (fromIndex === toIndex) {\n return;\n }\n\n // Move the header element directly in the DOM\n const headerToMove = headers[fromIndex];\n const targetHeader = headers[toIndex];\n\n if (fromIndex < toIndex) {\n // Moving right: insert after target\n thead.insertBefore(headerToMove, targetHeader.nextSibling);\n } else {\n // Moving left: insert before target\n thead.insertBefore(headerToMove, targetHeader);\n }\n\n // Move cells in each row\n rows.forEach((row, rowIndex) => {\n const cells = Array.from(row.children);\n const cellToMove = cells[fromIndex];\n const targetCell = cells[toIndex];\n\n if (fromIndex < toIndex) {\n // Moving right: insert after target\n row.insertBefore(cellToMove, targetCell.nextSibling);\n } else {\n // Moving left: insert before target\n row.insertBefore(cellToMove, targetCell);\n }\n });\n\n // Update column order tracking\n const currentOrder = this.originalColumnOrder.get(tableIndex);\n if (currentOrder) {\n const newOrder = [...currentOrder];\n const columnToMove = newOrder[fromIndex];\n newOrder.splice(fromIndex, 1);\n newOrder.splice(toIndex, 0, columnToMove);\n this.originalColumnOrder.set(tableIndex, newOrder);\n }\n\n // Reapply inline styles after reordering\n this.applyTableStyles(table);\n\n // Refresh drag and drop listeners for the reordered columns\n this.refreshDragAndDropListeners(table, tableIndex);\n }\n\n /**\n * Refresh drag and drop listeners after column reordering\n */\n refreshDragAndDropListeners(table, tableIndex) {\n const thead = table.querySelector('thead tr');\n if (!thead) return;\n\n const headers = Array.from(thead.children);\n\n // Remove existing listeners by cloning headers and re-adding all functionality\n headers.forEach((header, columnIndex) => {\n if (header.classList.contains(this.options.draggableClass)) {\n // Clear any drag-related inline styles before cloning\n header.style.opacity = '';\n header.style.background = '';\n header.style.borderRight = '';\n\n const newHeader = header.cloneNode(true);\n header.parentNode.replaceChild(newHeader, header);\n\n // Re-add all functionality (sorting, resizing, drag and drop)\n this.makeHeaderSortable(newHeader, table, tableIndex, columnIndex);\n }\n });\n }\n\n /**\n * Update table width based on current column widths\n */\n updateTableWidth(table) {\n const headers = table.querySelectorAll('th');\n let totalWidth = 0;\n\n headers.forEach(header => {\n const width = header.style.width;\n if (width) {\n const widthValue = parseInt(width.replace('px', ''));\n totalWidth += widthValue;\n } else {\n // Fallback to estimated width if no explicit width set\n const text = header.textContent.replace(/[📊🔍]/g, '').trim();\n totalWidth += text.length;\n }\n });\n\n // Convert to percentage\n table.style.width = `${totalWidth}px`;\n }\n\n /**\n * Calculate intelligent table width based on header text length\n */\n calculateTableWidth(table) {\n const originalWidthAttr = table.getAttribute('data-original-width');\n const originalWidth = originalWidthAttr ? parseFloat(originalWidthAttr) : 0;\n const headers = table.querySelectorAll('th');\n let totalWidth = 0;\n\n const parentWidth = table.parentElement.clientWidth\n\n const headersWidth = [];\n headers.forEach(header => {\n // Get text content without icons\n const text = header.textContent.replace(/[📊🔍]/g, '').trim();\n\n let estimatedWidth = text.length * this.charWidth + 15;\n\n headersWidth.push(estimatedWidth);\n\n totalWidth += estimatedWidth;\n });\n\n const rows = table.querySelectorAll('tr');\n\n const containerWidth = table.parentElement?.getBoundingClientRect().width ?? totalWidth;\n\n var maxRowWidth = 0;\n for (const row of rows) {\n const cells = row.querySelectorAll('td');\n\n cells.forEach((cell, index) => {\n // Get text content without icons\n const text = cell.textContent;\n\n const cellWidth = text.length * this.charWidth + 15;\n if (cellWidth > headersWidth[index] && index < headersWidth.length)\n headersWidth[index] = cellWidth;\n });\n };\n\n maxRowWidth = headersWidth.reduce((prev, current) => prev += current, 0);\n\n headers.forEach((header, index) => {\n if (maxRowWidth > containerWidth) {\n const factor = headersWidth[index] / maxRowWidth;\n header.style.width = `${containerWidth * factor}px`\n }\n else {\n header.style.width = `${headersWidth[index]}px`\n }\n });\n\n // Convert to percentage or pixel value\n let finalWidth = 0\n if (maxRowWidth > containerWidth) {\n finalWidth = `100%`\n }\n else {\n // If the calculated width would shrink the table below its\n // pre-transform rendered width, preserve the original.\n const effectiveWidth = Math.max(maxRowWidth, originalWidth);\n finalWidth = `${effectiveWidth}px`;\n }\n\n return finalWidth;\n }\n\n /**\n * Apply inline styles to ensure text clipping and horizontal scroll work\n */\n applyTableStyles(table) {\n // Force table styles\n const calculatedWidth = this.calculateTableWidth(table);\n // The \"fits comfortably\" branch of calculateTableWidth used\n // to force width: 100%, which made every chat table stretch\n // edge-to-edge regardless of content. Instead, let the table\n // be content-fit (auto) but floor it at 60% of the container\n // so very narrow tables don't look orphaned next to the\n // chat gutter, and cap it at 100% so wider data still fits.\n // The overflow branch still uses the calculated pixel width\n // because it's already wider than the container would allow.\n table.style.width = calculatedWidth;\n table.style.maxWidth = '100%';\n // if (calculatedWidth === '100%') {\n // table.style.width = 'auto';\n // table.style.minWidth = '60%';\n // table.style.maxWidth = '100%';\n // } else {\n // table.style.width = `${calculatedWidth}`;\n // table.style.minWidth = 'auto';\n // table.style.maxWidth = 'auto';\n // }\n // table.style.tableLayout = 'fixed'; // Use fixed layout to respect manual widths\n }\n\n getCharWidth(char, font, mono) {\n // Create a temporary canvas element\n const canvas = document.createElement(\"canvas\");\n const context = canvas.getContext(\"2d\");\n\n // Set the font (e.g., \"16px Arial\")\n context.fontFamily = font;\n context.fontMono = mono;\n\n // Measure the specific character\n const metrics = context.measureText(\"A \");\n return metrics.width; // Returns width in pixels\n }\n\n /**\n * Add CSS styles for sortable tables\n */\n addStyles() {\n if (document.getElementById('sortable-table-styles')) {\n return; // Styles already added\n }\n\n const style = document.createElement('style');\n style.id = 'sortable-table-styles';\n style.textContent = ` \n .${this.options.sortableClass} {\n position: relative;\n user-select: none;\n transition: background-color 0.2s ease;\n }\n \n .${this.options.sortableClass}:hover {\n background-color: ${this.options.theme.palette.surface.hover} !important;\n }\n \n .${this.options.activeSortClass} {\n background-color: ${this.options.theme.palette.surface.raised} !important;\n font-weight: bold;\n }\n \n .${this.options.ascendingClass} {\n border-bottom: 2px solid var(${this.options.theme.palette.primary.main}, #3a3a3a);\n }\n \n .${this.options.descendingClass} {\n border-bottom: 2px solid var(${this.options.theme.palette.primary.main}, #3a3a3a);\n }\n \n .${this.options.sortableClass} .material-icons {\n transition: opacity 0.2s ease, transform 0.2s ease;\n }\n \n .${this.options.activeSortClass} .material-icons {\n color: var(${this.options.theme.palette.primary.main}, #3a3a3a);\n }\n \n .${this.options.resizableClass} .resize-handle:hover {\n background-color: var(${this.options.theme.palette.primary.light}, #64B5F6);\n }\n \n .${this.options.draggableClass} {\n cursor: move;\n position: relative;\n }\n \n .${this.options.draggableClass}::before {\n content: '';\n position: absolute;\n top: 0;\n left: -5px;\n right: -5px;\n bottom: 0;\n z-index: 1;\n pointer-events: none;\n }\n \n .${this.options.dragOverClass} {\n background-color: rgba(128, 128, 128, 0.2) !important;\n border: 2px dashed rgba(128, 128, 128, 0.8);\n }\n \n .${this.options.draggableClass}:hover {\n background-color: var(${this.options.theme.palette.surface.raised}, rgba(100, 181, 246, 0.1)) !important;\n }\n\n .sortable-table tbody td {\n width: auto\n } \n\n .sortable-table {\n background-color: 'inherit';\n /* Cross-fade bg/row stripes when the .sortable-table\n * class flip lands on a freshly-streamed markdown\n * table. Width is NOT animated: column widths set\n * by calculateTableWidth can be narrower than the\n * content currently fills, so animating them down\n * causes mid-transition cell wrap. Snap widths,\n * animate only colours. */\n transition: background-color 280ms ease-out;\n }\n\n .sortable-table th {\n transition: background-color 280ms ease-out;\n }\n\n /* Zebra striping for table rows */\n .sortable-table tbody tr:nth-child(odd) {\n background-color: ${this.options.theme.palette.background.defalt};\n color: ${this.options.theme.palette.text.primary};\n }\n\n .sortable-table tbody tr:nth-child(even) {\n background-color: ${this.options.theme.palette.background.defalt};\n color: ${this.options.theme.palette.text.primary};\n }\n\n /* One-shot arrival animation. Applied via a transient\n * class (added by makeTableSortable on first mount only)\n * so it does NOT re-fire on every destroy/init cycle.\n * scaleX with origin top-left gives the \"right edge\n * grows outward\" feel the user asked for; the 0.96\n * start is subtle enough that text compression isn't\n * obvious. */\n @keyframes sortable-table-arrive {\n from {\n opacity: 0.35;\n transform: scaleX(0.96);\n transform-origin: top left;\n }\n to {\n opacity: 1;\n transform: scaleX(1);\n }\n }\n\n .sortable-table-arriving {\n animation: sortable-table-arrive 320ms cubic-bezier(0.16, 1, 0.3, 1) both;\n }\n \n /* Ensure hover effects work with zebra striping */\n .sortable-table tbody tr:hover {\n background-color: ${this.options.theme.palette.surface.hover} !important;\n }\n \n /* Fix table-container overflow issue */\n .table-container {\n overflow: auto !important;\n overflow-x: auto !important;\n overflow-y: auto !important;\n }\n `;\n\n const existingStyle = document.getElementById('sortable-table-styles');\n if (!existingStyle) {\n document.head.appendChild(style);\n }\n }\n\n /**\n * Destroy the sortable functionality\n */\n destroy() {\n this.tables.forEach(table => {\n const headers = table.querySelectorAll(`.${this.options.sortableClass}`);\n headers.forEach(header => {\n header.classList.remove(\n this.options.sortableClass,\n this.options.activeSortClass,\n this.options.ascendingClass,\n this.options.descendingClass\n );\n header.style.cursor = '';\n header.style.background = '';\n\n // Remove event listeners by cloning the element\n const newHeader = header.cloneNode(true);\n header.parentNode.replaceChild(newHeader, header);\n });\n });\n\n // Remove styles\n const styleElement = document.getElementById('sortable-table-styles');\n if (styleElement) {\n styleElement.remove();\n }\n\n this.tables = [];\n this.sortStates.clear();\n initializedTables.clear();\n }\n\n /**\n * Refresh the library (useful after DOM changes)\n */\n refresh() {\n this.destroy();\n this.init();\n }\n}\n\n// // Create global instance but don't auto-initialize\n// Guard the global assignment so this module is import-safe outside the\n// browser (Node/SSR/tests). Importing it for the class export alone — as the\n// session-replay decode path does transitively — must not throw on `window`.\nif (typeof window !== 'undefined') {\n window.SortableTable = SortableTable;\n}\n\n// Export for module systems\nexport default SortableTable;\n","// Shared prompt-overlay helpers used by both the chat composer (PromptV2) and the home composer (obtapp's\n// PromptComposer): tokenize a draft into chip/plain runs, and chip server-mapped locations inline like \"@\" mentions.\n\nexport type HighlightToken = { type: 'plain' | 'slash' | 'at' | 'hash'; text: string };\n\nconst TRIGGER_CHARS: ReadonlySet<string> = new Set(['/', '@', '#']);\nconst triggerTypeFor = (ch: string): 'slash' | 'at' | 'hash' =>\n ch === '/' ? 'slash' : ch === '@' ? 'at' : 'hash';\n// A token boundary is ASCII whitespace only — NOT the non-breaking space (U+00A0). Hosts join a multi-word\n// \"@mention\" (e.g. \"@São Paulo\") with NBSPs so the whole name stays a single chip; a regular space separates tokens.\nconst HIGHLIGHT_WS = /[ \\t\\r\\n\\f\\v]/;\n\n/**\n * Splits `text` into a flat list of runs so the overlay can paint chip styling around `/cmd` / `@user` / `#date`\n * tokens while keeping surrounding text plain. Boundary rule mirrors the autocomplete trigger detection (trigger\n * char at line start or after whitespace), so a `/` inside `http://` or `@` inside an email stays plain.\n */\nexport const tokenizeForHighlight = (text: string): HighlightToken[] => {\n if (!text) return [];\n const tokens: HighlightToken[] = [];\n let i = 0;\n while (i < text.length) {\n const ch = text[i];\n const atBoundary = i === 0 || HIGHLIGHT_WS.test(text[i - 1]);\n if (atBoundary && TRIGGER_CHARS.has(ch)) {\n let end = i + 1;\n while (end < text.length && !HIGHLIGHT_WS.test(text[end])) end += 1;\n tokens.push({ type: triggerTypeFor(ch), text: text.slice(i, end) });\n i = end;\n } else {\n let end = i + 1;\n while (end < text.length) {\n const c = text[end];\n const prevIsWs = HIGHLIGHT_WS.test(text[end - 1]);\n if (TRIGGER_CHARS.has(c) && prevIsWs) break;\n end += 1;\n }\n tokens.push({ type: 'plain', text: text.slice(i, end) });\n i = end;\n }\n }\n return tokens;\n};\n\n/**\n * Second pass: chip the locations the slow pass mapped (pasted / dictated, no typed \"@\") as if they were \"@\"\n * mentions — same inline chip style. Only PLAIN runs are scanned (real \"@\" mentions are already their own chips);\n * longest names win so \"São Paulo\" beats \"São\".\n */\nexport const chipLocations = (tokens: HighlightToken[], locTexts: readonly string[]): HighlightToken[] => {\n const needles = locTexts.filter((t) => t.trim().length > 0).sort((a, b) => b.length - a.length);\n if (needles.length === 0) return tokens;\n const out: HighlightToken[] = [];\n for (const tok of tokens) {\n if (tok.type !== 'plain') { out.push(tok); continue; }\n let rest = tok.text;\n while (rest.length > 0) {\n let at = -1;\n let len = 0;\n for (const n of needles) {\n const idx = rest.indexOf(n);\n if (idx >= 0 && (at === -1 || idx < at)) { at = idx; len = n.length; }\n }\n if (at === -1) { out.push({ type: 'plain', text: rest }); break; }\n if (at > 0) out.push({ type: 'plain', text: rest.slice(0, at) });\n out.push({ type: 'at', text: rest.slice(at, at + len) });\n rest = rest.slice(at + len);\n }\n }\n return out;\n};\n"],"names":["parseAndValidateArtifactUrl","__name","url","urlParts","lastPart","removedUrlParams","extractLinkAction","link","sessionId","content","action","question","parameter","firstDash","firstPart","chunkArray","char","size","_v","i","splitBigLinesWithSpaces","limit","whiteSpaceBreak","allWords","hadOne","word","charArray","chunkedWord","chunk","parseRawNumber","text","number","finalNumber","ratio","parseKnownNumbers","knownChars","currencySymbol","prefix","suffix","match","replacedChar","UUID_WITH_DASHES_REGEX","UUID_WITHOUT_DASHES_REGEX","startsWithInteractionId","str","interactionId","extractInteractionId","withDashesMatch","withoutDashesMatch","prettiffyFileName","fileName","withNoExtension","withNoInteractionId","extractNameFromStringWithInteractionId","prettiffyPythonFunctionName","functionName","prettyName","isValidInteractionId","initializedTables","_SortableTable","options","container","tables","table","tableIndex","thead","headerRow","headers","isFirstSortableMount","_","index","header","columnIndex","tbody","row","cell","exponentialMatch","base","exponent","fullNumber","formattedNumber","num","firstRow","td","th","attr","error","clickListener","e","mouseEnterListener","mouseLeaveListener","icon","rows","sortState","newDirection","direction","a","b","cellA","cellB","valueA","valueB","comparison","percentageMatch","currencyMatch","date","activeHeader","resizeHandle","isResizing","startX","startWidth","handleResize","stopResize","newWidth","currentPosition","headerContent","currentColumnIndex","dragImage","headerText","highlight","cells","j","fromIndex","toIndex","headerToMove","targetHeader","rowIndex","cellToMove","targetCell","currentOrder","newOrder","columnToMove","newHeader","totalWidth","width","widthValue","_a","originalWidthAttr","originalWidth","headersWidth","estimatedWidth","containerWidth","maxRowWidth","cellWidth","prev","current","factor","finalWidth","calculatedWidth","font","mono","context","style","styleElement","SortableTable","TRIGGER_CHARS","triggerTypeFor","ch","HIGHLIGHT_WS","tokenizeForHighlight","tokens","end","c","prevIsWs","chipLocations","locTexts","needles","t","out","tok","rest","at","len","n","idx"],"mappings":"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"}
package/dist/services.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as a, a as r, E as s, H as o, I as c, L as n, W as i } from "./httpArtifactService-BAR60Gu1.js";
1
+ import { A as a, a as r, E as s, H as o, I as c, L as n, W as i } from "./httpArtifactService-Dh9LGQ9a.js";
2
2
  import { A as v } from "./artifactHtmlHandler-CMQJf1cX.js";
3
3
  import { H, d as f } from "./httpSessionService-5Kr__oQL.js";
4
4
  export {
@@ -1,19 +1,22 @@
1
- import { ComponentType } from 'react';
1
+ import { ComponentType, ReactNode } from 'react';
2
2
  import { AgentGatewayService } from '../../services/servers/AgentGatewayService';
3
3
  import { EventBusService } from '../../services/eventBusService';
4
4
  import { IArtifactService } from '../../services/interfaces/artifactService';
5
+ import { HttpPromptAssistService } from '../../services/httpPromptAssistService';
5
6
  import { IStorageService } from '../../services/storageService';
6
7
  import { INotificationPort } from '../../interfaces/INotificationPort';
7
8
  import { AiChatState, AiChatStore } from './stateConfiguration';
8
9
  import { SessionStateManagerService } from './sessionStateManagerService';
9
10
  import { PartRendererMap, UiToolRegistry } from './ChatPane/parts';
10
11
  import { Interaction } from '../../models/Interaction';
11
- import { SendMessageOptions, UserMessageRendererProps } from './AiChatTypes';
12
+ import { AuthPromptContext, SendMessageOptions, UserMessageRendererProps } from './AiChatTypes';
12
13
  import { SendMessageResponse } from '../../models/SendMessageResponse';
13
14
  export interface AiChatContextState {
14
15
  agentGatewayService: AgentGatewayService;
15
16
  eventBusService: EventBusService;
16
17
  artifactService: IArtifactService;
18
+ /** Prompt-assist client for PromptV2 (auto-@ locations, date hints, resolved-date chips). */
19
+ promptAssistService?: HttpPromptAssistService;
17
20
  storageService: IStorageService;
18
21
  notificationPort: INotificationPort;
19
22
  sessionStateManagerService: SessionStateManagerService;
@@ -35,6 +38,15 @@ export interface AiChatContextState {
35
38
  currentModel: string | undefined;
36
39
  setCurrentModel: (modelId: string) => void;
37
40
  onVisibleQuestionChange?: (question: string | null) => void;
41
+ /**
42
+ * Host-supplied sign-in used by the built-in `AskAuthPart` (the `askauth` tool). Invoked when
43
+ * the user clicks "sign in" on the inline card; must resolve to a freshly-signed access token
44
+ * (or `null` if the user cancels). The library then sends it back via `answerHumanTool` — it
45
+ * stays IdP-agnostic, so the host owns the actual login (popup, redirect, …).
46
+ */
47
+ onRequestAuth?: () => Promise<string | null>;
48
+ /** Richer host-supplied `askauth` prompt body; see {@link AiChatProps.renderAuthPrompt}. */
49
+ renderAuthPrompt?: (ctx: AuthPromptContext) => ReactNode;
38
50
  onRenderPrompt?: (message: string) => {
39
51
  promptAsString?: string;
40
52
  json?: any;
@@ -74,6 +74,18 @@ export interface ConnectionInformation {
74
74
  loadingError?: string | null;
75
75
  sesssionActive: boolean;
76
76
  }
77
+ /**
78
+ * Context handed to a host-supplied `renderAuthPrompt` (the `askauth` prompt body). The host renders
79
+ * whatever sign-in UI it wants and calls `onToken` with the freshly-signed access token, or `onCancel`.
80
+ */
81
+ export interface AuthPromptContext {
82
+ /** Optional reason the agent gave for requiring sign-in (the tool's `reason` argument). */
83
+ reason?: string;
84
+ /** Deliver the signed token — the library sends it to the agent via `answerHumanTool`. */
85
+ onToken: (token: string) => void;
86
+ /** The user backed out; the library resets the prompt so they can retry. */
87
+ onCancel: () => void;
88
+ }
77
89
  export interface AiChatProps extends AiChatStyleProps {
78
90
  agentContext: AgentContext;
79
91
  serverBaseUrl: string;
@@ -187,6 +199,22 @@ export interface AiChatProps extends AiChatStyleProps {
187
199
  onGatewayReady?: (gateway: AgentGatewayService) => void;
188
200
  onVisibleQuestionChange?: (question: string | null) => void;
189
201
  onFirstToken?: (details: FirstTokenEventDetails) => void;
202
+ /**
203
+ * Host-supplied sign-in for the built-in `askauth` tool. The inline AskAuthPart calls this when
204
+ * the user chooses to sign in; it must resolve to a freshly-signed access token (or `null` if the
205
+ * user cancels), which the library sends back to the agent via `answerHumanTool`. The library is
206
+ * IdP-agnostic — the host implements the actual flow (a popup keeps the chat WebSocket alive).
207
+ */
208
+ onRequestAuth?: () => Promise<string | null>;
209
+ /**
210
+ * Richer host-supplied sign-in body for the built-in `askauth` tool. When provided, the inline
211
+ * AskAuthPart renders this INSTEAD of the default button — letting the host collect first-party
212
+ * details (e.g. email / provider) directly in the drawer, then hand back the signed token. The
213
+ * library keeps owning the card chrome, the locked "done" state, and the `answerHumanTool` wiring:
214
+ * the host just calls `onToken(signedToken)` (or `onCancel()`). Takes precedence over
215
+ * `onRequestAuth` (the simple-button fallback). Library stays IdP-agnostic.
216
+ */
217
+ renderAuthPrompt?: (ctx: AuthPromptContext) => React.ReactNode;
190
218
  onToolEvent?: (eventName: string, eventData: string) => void;
191
219
  onRenderPrompt?: (prompt: string) => {
192
220
  promptAsString?: string;
@@ -4,7 +4,8 @@ interface AskUserSheetProps {
4
4
  promptHeight: number;
5
5
  }
6
6
  /**
7
- * Pane-scoped bottom sheet for a PARKED ask_user prompt.
7
+ * Pane-scoped bottom sheet for a PARKED human-input prompt — ask_user (questionnaire) or askauth
8
+ * (sign-in). Both park a turn awaiting the user; this surfaces whichever is pending in the docked drawer.
8
9
  *
9
10
  * A turn blocked on ask_user goes idle (no tokens stream), so the trailing
10
11
  * "..." waiting dots disappear and the inline transcript form reads as a
@@ -0,0 +1,8 @@
1
+ import { default as React } from 'react';
2
+ import { PartRendererProps } from './types';
3
+ type AskAuthPartProps = Partial<PartRendererProps> & {
4
+ part: PartRendererProps['part'];
5
+ embedded?: boolean;
6
+ };
7
+ declare const AskAuthPart: React.FC<AskAuthPartProps>;
8
+ export default AskAuthPart;
@@ -1,7 +1,7 @@
1
1
  import { default as React } from 'react';
2
2
  import { InteractionPart } from '../../../../models/InteractionPart';
3
3
  import { Interaction } from '../../../../models/Interaction';
4
- export type PartKind = 'text' | 'thought' | 'function' | 'waiting' | 'suspended' | 'boxed' | 'uiTool' | 'askUser';
4
+ export type PartKind = 'text' | 'thought' | 'function' | 'waiting' | 'suspended' | 'boxed' | 'uiTool' | 'askUser' | 'askAuth';
5
5
  export interface PartRendererProps {
6
6
  part: InteractionPart;
7
7
  message: Interaction;
@@ -20,3 +20,8 @@ export type PartRendererMap = Partial<Record<PartKind, PartRenderer>>;
20
20
  * literal `=== 'ask_user'` misses real-model calls.
21
21
  */
22
22
  export declare const isAskUser: (name?: string | null) => boolean;
23
+ /**
24
+ * Match the askauth tool by function name across connectors. The programmed path emits the
25
+ * bare `askauth`; live LLM connectors qualify it as `{Plugin}-askauth` / `{Plugin}_askauth`.
26
+ */
27
+ export declare const isAskAuth: (name?: string | null) => boolean;
@@ -5,7 +5,7 @@ export { AiChatDrawer } from './AiChat/AiChatDrawer';
5
5
  export { AiChatFloating } from './AiChat/AiChatFloating';
6
6
  export { AiChatServiceContext, useAiChatServices, useAiChatSessionStore, } from './AiChat/AiChatContext';
7
7
  export type { AiChatContextState as AiChatServices } from './AiChat/AiChatContext';
8
- export type { AiChatProps, AiChatHandle, AiChatStyleProps, AiChatDrawerProps, AiChatFloatingProps, ConnectionInformation, } from './AiChat/AiChatTypes';
8
+ export type { AiChatProps, AiChatHandle, AiChatStyleProps, AiChatDrawerProps, AiChatFloatingProps, ConnectionInformation, AuthPromptContext, } from './AiChat/AiChatTypes';
9
9
  export type { AiChatState, AiChatStore, SubAgentState } from './AiChat/stateConfiguration';
10
10
  export { createAiChatStore } from './AiChat/stateConfiguration';
11
11
  export { createAiChatSessionStore } from './AiChat/AiChatSessionStore';
@@ -0,0 +1,15 @@
1
+ export type PromptDateMarker = {
2
+ text: string;
3
+ display: string;
4
+ top: number;
5
+ left: number;
6
+ };
7
+ /**
8
+ * Resolved-date markers shared by both composers: a subtle underline floated after each date phrase, with a tooltip
9
+ * "amanhã → terça 7 de julho" that auto-opens on a fresh resolution (`forceTooltipText`) and on hover. The marker
10
+ * coords are viewport-fixed (host measures the caret); positioning matches PromptV2 exactly.
11
+ */
12
+ export declare function PromptDateMarkers({ markers, forceTooltipText, }: {
13
+ markers: PromptDateMarker[];
14
+ forceTooltipText: string;
15
+ }): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,5 @@
1
1
  import { default as React } from 'react';
2
+ import { PromptAnalysis, PromptResolution, SuggestItem } from '../../services/httpPromptAssistService';
2
3
  /**
3
4
  * Autocomplete item returned by `onSlashQuery` / `onAtQuery`. The
4
5
  * `value` is spliced verbatim into the textarea, replacing the entire
@@ -124,6 +125,25 @@ interface PromptV2Props {
124
125
  * don't have to branch internally.
125
126
  */
126
127
  onAtQuery?: (query: string) => Promise<PromptTriggerItem[]>;
128
+ /**
129
+ * Live prompt-assist quick path (debounced ~300ms). Given the text + caret, the server
130
+ * (Qwen next-word + NER) categorizes what's coming so the composer can auto-open the `@`
131
+ * location picker and toggle the date hint. Wire to HttpPromptAssistService.analyze.
132
+ */
133
+ onAnalyzePrompt?: (text: string, caret: number) => Promise<PromptAnalysis>;
134
+ /**
135
+ * Live prompt-assist slow path (trailing debounce). Returns DeepSeek-resolved dates with char
136
+ * spans + display strings ("quarta 8 de Jul") for the inline chips. Wire to resolveDates.
137
+ * `sessionId` scopes the prompt-composition session; `signal` cancels a superseded call.
138
+ */
139
+ onResolveDates?: (text: string, sessionId?: string, signal?: AbortSignal) => Promise<PromptResolution>;
140
+ /**
141
+ * Unified prompt-assist typeahead source (TripApi `/air/prompt/suggest`). Given the trailing query + the
142
+ * predicted kind, returns location / date suggestions (tenant-learned merged with global). The predictions
143
+ * dropdown searches against this as the user types — no `@` required — pre-filled by `onAnalyzePrompt`'s fast
144
+ * suggestions. Host-provided (it hits TripApi, not the agent server), mirroring `onAtQuery`.
145
+ */
146
+ onSuggest?: (q: string, kind: 'location' | 'date' | 'both', signal?: AbortSignal, exclude?: string[]) => Promise<SuggestItem[]>;
127
147
  /**
128
148
  * When set, `/command` tokens inside the prompt render as a chip
129
149
  * (soft tinted background + 1px inset border + matching text)
@@ -158,6 +178,11 @@ interface PromptV2Props {
158
178
  * display can pass e.g. `'DD/MM/YYYY'`.
159
179
  */
160
180
  hashDateFormat?: string;
181
+ /**
182
+ * Localized date quick-picks shown in the combined predictions dropdown. Defaults to pt-BR. The server-side
183
+ * date *rules* are language-independent (cat/offset/value), so only these display labels need locale.
184
+ */
185
+ datePresets?: string[];
161
186
  borderRadius?: number;
162
187
  }
163
188
  export declare const PromptV2: React.ForwardRefExoticComponent<PromptV2Props & React.RefAttributes<HTMLDivElement>>;
@@ -19,6 +19,8 @@ export { AiChatV2Pane } from './AiChatV2Pane';
19
19
  export type { AiChatV2PaneProps } from './AiChatV2Pane';
20
20
  export { PromptV2 } from './PromptV2';
21
21
  export type { PromptTriggerItem } from './PromptV2';
22
+ export { PromptDateMarkers } from './PromptDateMarkers';
23
+ export type { PromptDateMarker } from './PromptDateMarkers';
22
24
  export { LastPromptsV2 } from './LastPromptsV2';
23
25
  export type { LastPromptsV2Props } from './LastPromptsV2';
24
26
  export { ChatsHistoryV2 } from './ChatsHistoryV2';
@@ -2,3 +2,5 @@ export { default as useInterval } from './useIntervalHook';
2
2
  export { useContainerWidth, useContainerRectangle } from './useContainerWidth';
3
3
  export { useChatSessions } from './useChatSessions';
4
4
  export type { UseChatSessionsOptions, UseChatSessionsResult, ChatSessionListItem, ChatSessionGroup, } from './useChatSessions';
5
+ export { usePromptAssist } from './usePromptAssist';
6
+ export type { PredictionItem, ResolvedDateItem, PromptAssistAdapter, PromptAssistFetchers, PromptAssistOptions, } from './usePromptAssist';
@@ -0,0 +1,64 @@
1
+ import { KeyboardEvent } from 'react';
2
+ import { PromptAnalysis, PromptResolution, SuggestItem } from '../services/httpPromptAssistService';
3
+ /** A dropdown item. `namedLocation` inserts `@Name` directly; `location`/`calendar` insert `@`/`#` and open the picker. */
4
+ export type PredictionItem = {
5
+ key: string;
6
+ label: string;
7
+ kind: 'location' | 'namedLocation' | 'date' | 'calendar';
8
+ insert?: string;
9
+ /** Secondary line (e.g. "GRU · SP · Brasil") — parity with the `@` picker's hint. Optional. */
10
+ hint?: string;
11
+ /** Non-pickable (already in the prompt, same place/city) — rendered greyed and skipped by nav/apply. */
12
+ disabled?: boolean;
13
+ };
14
+ export type ResolvedDateItem = {
15
+ text: string;
16
+ display: string;
17
+ };
18
+ /** The DOM operations the hook needs from its host composer — so the same logic drives PromptV2 and PromptComposer. */
19
+ export interface PromptAssistAdapter {
20
+ getTextarea: () => HTMLTextAreaElement | null;
21
+ /** Replace the draft value (host owns the React state). */
22
+ setDraft: (next: string) => void;
23
+ /** After a programmatic edit, focus the textarea and place the caret (host defers a frame if needed). */
24
+ focusCaret: (pos: number) => void;
25
+ /** Re-detect the `@`/`#` trigger at the caret and open the matching picker (host's existing flow). */
26
+ syncTrigger: (ta: HTMLTextAreaElement) => void;
27
+ /** Is a location/date picker already open? (suppresses the predictions dropdown / auto-`@`) */
28
+ isPickerOpen: () => boolean;
29
+ /** The trigger char of any open picker, or null — used to avoid re-inserting `@`. */
30
+ currentTriggerChar: () => string | null;
31
+ /** Whether the `@` location fetcher is wired (else no auto-`@` / generic "Local…"). */
32
+ hasAtQuery: boolean;
33
+ }
34
+ export interface PromptAssistFetchers {
35
+ analyze?: (text: string, caret: number) => Promise<PromptAnalysis>;
36
+ resolveDates?: (text: string, sessionId?: string, signal?: AbortSignal) => Promise<PromptResolution>;
37
+ commitIntent?: (text: string, sessionId?: string) => void;
38
+ suggest?: (q: string, kind: 'location' | 'date' | 'both', signal?: AbortSignal, exclude?: string[]) => Promise<SuggestItem[]>;
39
+ }
40
+ export interface PromptAssistOptions {
41
+ enableHashDatePicker?: boolean;
42
+ datePresets?: string[];
43
+ }
44
+ /**
45
+ * Headless prompt-assist logic shared by the chat composer (PromptV2) and the home composer (obtapp PromptComposer):
46
+ * the analyze quick pass (auto-`@` + combined predictions dropdown), the resolve slow pass (date resolution +
47
+ * mapped-location chips), commit-on-send learning, and keyboard nav — all with NO rendering/anchoring assumptions.
48
+ * The host provides its DOM ops via {@link PromptAssistAdapter} and renders the returned `predictions` however it wants.
49
+ */
50
+ export declare function usePromptAssist(adapter: PromptAssistAdapter, fetchers: PromptAssistFetchers, options?: PromptAssistOptions): {
51
+ predictions: PredictionItem[] | null;
52
+ predictionsRecents: boolean;
53
+ predictionHighlight: number;
54
+ setPredictionHighlight: import('react').Dispatch<import('react').SetStateAction<number>>;
55
+ applyPrediction: (p: PredictionItem) => void;
56
+ clearPredictions: () => void;
57
+ resolvedLocations: string[];
58
+ resolvedDates: ResolvedDateItem[];
59
+ forceTooltipText: string;
60
+ scheduleAssist: (value: string, caret: number, isDeletion: boolean) => void;
61
+ commit: (finalText: string) => void;
62
+ onKeyDown: (e: KeyboardEvent<HTMLTextAreaElement>) => boolean;
63
+ resetSession: () => void;
64
+ };
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Client for the AgentsServer prompt-assist endpoints (POST /prompt/analyze and
3
+ * /prompt/resolve-dates). Powers PromptV2's live behaviors: auto-inserting `@` when a location is
4
+ * expected, showing date hints, and rendering resolved-date chips. Mirrors HttpArtifactService
5
+ * (baseUrl + bearer). The heavy Qwen/NER models run server-side; this is a thin fetch client.
6
+ */
7
+ /** A personalized dropdown suggestion learned from the customer's history. */
8
+ export interface AnalyzeSuggestion {
9
+ kind: string;
10
+ label: string;
11
+ value: string;
12
+ }
13
+ /**
14
+ * A unified suggest item from the host-provided search source (matches the TripApi `/air/prompt/suggest`
15
+ * response item shape). The HTTP call itself is host-provided, so only the TYPE lives here.
16
+ */
17
+ export interface SuggestItem {
18
+ kind: 'location' | 'date';
19
+ iata?: string;
20
+ label: string;
21
+ insert: string;
22
+ score: number;
23
+ region?: string;
24
+ country?: string;
25
+ /** Location can't be picked — already in the prompt (same place or same city). Shown greyed, not selectable. */
26
+ disabled?: boolean;
27
+ }
28
+ /** Quick-path result — drives auto-`@`, date-hint visibility, and the combined predictions dropdown. */
29
+ export interface PromptAnalysis {
30
+ locationExpected: boolean;
31
+ locationPartialEmpty: boolean;
32
+ dateExpected: boolean;
33
+ locationCount: number;
34
+ category: string;
35
+ suggestions?: AnalyzeSuggestion[];
36
+ /** The free-form location text being typed (search query for the combined dropdown), "@"-mentions stripped.
37
+ * Server-owned (LocationCueDetector) — the client uses it verbatim instead of re-guessing from whitespace.
38
+ * Optional for back-compat with an older server (falls back to the trailing-word heuristic). */
39
+ locationPartial?: string;
40
+ }
41
+ /** Slow-path resolved date — `start`/`length` anchor the chip; `display` is e.g. "quarta 8 de Jul". */
42
+ export interface ResolvedDate {
43
+ start: number;
44
+ length: number;
45
+ text: string;
46
+ resolvedIso: string;
47
+ display: string;
48
+ }
49
+ /** A location the NER mapped in the slow pass — lets the client format locations pasted/dictated without a `@`. */
50
+ export interface ResolvedLocation {
51
+ start: number;
52
+ length: number;
53
+ text: string;
54
+ }
55
+ /** Slow-path result: resolved dates + mapped locations. */
56
+ export interface PromptResolution {
57
+ dates: ResolvedDate[];
58
+ locations: ResolvedLocation[];
59
+ }
60
+ export declare class HttpPromptAssistService {
61
+ private baseUrl;
62
+ private accessToken;
63
+ constructor(serverBaseUrl: string, accessToken: string);
64
+ private get headers();
65
+ /** Quick path (debounce ~300ms). `signal` lets the caller cancel a superseded keystroke. */
66
+ analyze(text: string, caret: number, signal?: AbortSignal): Promise<PromptAnalysis>;
67
+ /**
68
+ * Slow path (trailing debounce). `sessionId` scopes the current prompt-composition session so the server
69
+ * only persists a template when a new entity appears for it. Returns the resolved dates (empty on none/error).
70
+ */
71
+ resolveDates(text: string, sessionId?: string, signal?: AbortSignal): Promise<PromptResolution>;
72
+ /**
73
+ * Fire-and-forget on SEND: tells the server to LEARN from the final prompt (commit=true). Learning only on
74
+ * commit means in-progress `@`-query partials typed while composing never get recorded as places.
75
+ */
76
+ commitIntent(text: string, sessionId?: string): Promise<void>;
77
+ }
@@ -15,3 +15,5 @@ export { default as materialIcons, getIconByName, searchIcons, iconCategories, }
15
15
  export type { MaterialIcon } from './materialIconsList';
16
16
  export { GOOGLE_CLIENT_ID, ALLOWED_DOMAINS, ALLOWED_EMAILS, AUTH_CONFIG } from './auth';
17
17
  export { default as SortableTable } from './sortable-table';
18
+ export { tokenizeForHighlight, chipLocations } from './promptHighlight';
19
+ export type { HighlightToken } from './promptHighlight';
@@ -0,0 +1,16 @@
1
+ export type HighlightToken = {
2
+ type: 'plain' | 'slash' | 'at' | 'hash';
3
+ text: string;
4
+ };
5
+ /**
6
+ * Splits `text` into a flat list of runs so the overlay can paint chip styling around `/cmd` / `@user` / `#date`
7
+ * tokens while keeping surrounding text plain. Boundary rule mirrors the autocomplete trigger detection (trigger
8
+ * char at line start or after whitespace), so a `/` inside `http://` or `@` inside an email stays plain.
9
+ */
10
+ export declare const tokenizeForHighlight: (text: string) => HighlightToken[];
11
+ /**
12
+ * Second pass: chip the locations the slow pass mapped (pasted / dictated, no typed "@") as if they were "@"
13
+ * mentions — same inline chip style. Only PLAIN runs are scanned (real "@" mentions are already their own chips);
14
+ * longest names win so "São Paulo" beats "São".
15
+ */
16
+ export declare const chipLocations: (tokens: HighlightToken[], locTexts: readonly string[]) => HighlightToken[];