@ensembleapp/client-sdk 0.0.46 → 0.0.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -27,11 +27,11 @@ function styleInject(css, { insertAt } = {}) {
27
27
  }
28
28
 
29
29
  // lib/chat/ChatWidget.css
30
- styleInject(':root[data-chat-widget],\n[data-chat-widget] {\n --chat-primary: #3b82f6;\n --chat-primary-text: #ffffff;\n --chat-primary-hover: #2563eb;\n --chat-primary-subtle: rgba(59, 130, 246, 0.1);\n --chat-background: #ffffff;\n --chat-background-secondary: #f9fafb;\n --chat-background-tertiary: #f3f4f6;\n --chat-border: #e5e7eb;\n --chat-border-light: #f3f4f6;\n --chat-widget-border-width: 1px;\n --chat-text: #111827;\n --chat-text-secondary: #4b5563;\n --chat-text-muted: #6b7280;\n --chat-text-disabled: #9ca3af;\n --chat-link: #2563eb;\n --chat-link-hover: #1d4ed8;\n --chat-success: #22c55e;\n --chat-success-bg: rgba(34, 197, 94, 0.1);\n --chat-error: #ef4444;\n --chat-error-bg: rgba(239, 68, 68, 0.1);\n --chat-header-text: #ffffff;\n --chat-user-text: #ffffff;\n --chat-assistant-bg: transparent;\n --chat-assistant-text: var(--chat-text);\n --chat-input-bg: var(--chat-background);\n --chat-input-text: var(--chat-text);\n --chat-input-placeholder: var(--chat-text-muted);\n --chat-thought-border: var(--chat-border);\n --chat-font-family:\n "Inter",\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n sans-serif;\n --chat-radius: 0.75rem;\n --chat-font-size: 0.925rem;\n --chat-thought-font-size: 0.75rem;\n --chat-shadow: 0 20px 45px rgba(0, 0, 0, 0.12);\n --chat-shadow-sm: 0 4px 12px rgba(0, 0, 0, 0.1);\n --chat-overlay-bg: rgba(0, 0, 0, 0.3);\n}\n.chat-widget {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 24rem;\n background: var(--chat-background);\n border: var(--chat-widget-border-width) solid var(--chat-border);\n border-radius: 0;\n box-shadow: var(--chat-shadow);\n overflow: hidden;\n font-family: var(--chat-font-family);\n color: var(--chat-assistant-text);\n}\n.chat-widget--popup-content {\n border: 0;\n border-radius: inherit;\n box-shadow: none;\n min-height: 0;\n}\n.chat-widget__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 40px;\n padding: 0.75rem 1rem;\n background: var(--chat-primary);\n color: var(--chat-header-text);\n}\n.chat-widget__title {\n margin: 0;\n font-size: 0.875rem;\n font-weight: 600;\n}\n.chat-widget__messages {\n flex: 1;\n overflow-y: auto;\n padding: 1rem;\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n.chat-widget__message {\n display: flex;\n flex-direction: column;\n gap: 0;\n}\n.chat-widget__message-row {\n display: flex;\n}\n.chat-widget__message-row--user {\n justify-content: flex-end;\n}\n.chat-widget__message-row--assistant {\n justify-content: flex-start;\n}\n.chat-widget__bubble {\n max-width: 90%;\n padding: 0.5rem 0.25rem;\n border-radius: calc(var(--chat-radius) * 0.65);\n font-size: var(--chat-font-size);\n}\n.chat-widget__bubble--user {\n background: var(--chat-primary);\n color: var(--chat-user-text);\n border-bottom-right-radius: 0.35rem;\n padding-left: 0.375rem;\n padding-right: 0.375rem;\n}\n.chat-widget__bubble--assistant {\n width: 90%;\n background: var(--chat-assistant-bg);\n color: var(--chat-assistant-text);\n border-bottom-left-radius: 0.35rem;\n}\n.chat-widget__widget {\n width: 100%;\n}\n.chat-widget__markdown {\n white-space: normal;\n font-size: var(--chat-font-size);\n}\n.chat-widget__markdown h1 {\n font-size: calc(var(--chat-font-size) * 1.4);\n}\n.chat-widget__markdown h2 {\n font-size: calc(var(--chat-font-size) * 1.25);\n}\n.chat-widget__markdown h3 {\n font-size: calc(var(--chat-font-size) * 1.1);\n}\n.chat-widget__markdown h4 {\n font-size: calc(var(--chat-font-size) * 1.05);\n}\n.chat-widget__markdown h5 {\n font-size: calc(var(--chat-font-size) * 1);\n}\n.chat-widget__markdown h6 {\n font-size: calc(var(--chat-font-size) * 0.95);\n}\n.chat-widget__anchor-button {\n position: fixed;\n bottom: 20px;\n right: 20px;\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.65rem 0.85rem;\n background: var(--chat-primary);\n color: var(--chat-primary-text);\n border: none;\n border-radius: 999px;\n box-shadow: var(--chat-shadow);\n cursor: pointer;\n font-weight: 600;\n z-index: 99999;\n}\n.chat-widget__anchor-button:hover {\n background: var(--chat-primary-hover);\n}\n.chat-widget__anchor--left {\n right: auto;\n left: 20px;\n}\n.chat-widget__anchor-icon {\n width: 1.1rem;\n height: 1.1rem;\n}\n.chat-widget__popup {\n position: fixed;\n bottom: 80px;\n right: 20px;\n z-index: 99998;\n}\n.chat-widget__anchor--left.chat-widget__popup {\n right: auto;\n left: 20px;\n}\n.chat-widget__popup-inner {\n width: 384px;\n max-width: calc(100vw - 40px);\n height: 500px;\n max-height: calc(100vh - 140px);\n box-shadow: var(--chat-shadow);\n border-radius: 12px;\n overflow: hidden;\n}\n.chat-widget__markdown a {\n color: var(--chat-link);\n text-decoration: underline;\n}\n.chat-widget__markdown a:hover {\n color: var(--chat-link-hover);\n}\n.chat-widget__markdown table {\n width: 100%;\n border-collapse: collapse;\n margin: 0.5rem 0;\n}\n.chat-widget__markdown th,\n.chat-widget__markdown td {\n border: 1px solid var(--chat-border);\n padding: 0.5rem;\n text-align: left;\n vertical-align: top;\n}\n.chat-widget__markdown thead th {\n background: var(--chat-assistant-bg);\n color: var(--chat-assistant-text);\n font-weight: 600;\n}\n.chat-widget__thoughts {\n min-width: 0;\n --chat-font-size: var(--chat-thought-font-size);\n}\n.chat-widget__details {\n border: 0;\n}\n.chat-widget__thoughts-summary {\n list-style: none;\n display: flex;\n align-items: center;\n gap: 0.35rem;\n cursor: pointer;\n color: var(--chat-text-muted);\n font-size: 0.8125rem;\n}\n.chat-widget__thoughts-summary:hover {\n color: var(--chat-assistant-text);\n}\n.chat-widget__thoughts-icon-container {\n display: flex;\n border: 1px solid var(--chat-border);\n border-radius: 999px;\n align-items: center;\n justify-content: center;\n width: 1rem;\n height: 1rem;\n}\n.chat-widget__thoughts-icon {\n width: 0.75rem;\n height: 0.75rem;\n transition: transform 0.2s ease;\n}\n.chat-widget__details[open] .chat-widget__thoughts-icon {\n transform: rotate(90deg);\n}\n.chat-widget__thoughts-content {\n margin-top: 0.5rem;\n margin-left: 0.4rem;\n padding: 0.75rem;\n border-left: 2px solid var(--chat-thought-border);\n border-color: var(--chat-primary);\n max-width: 100%;\n overflow-x: auto;\n}\n.chat-widget__thoughts-text {\n margin: 0;\n line-height: 1.5;\n color: var(--chat-text-secondary);\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: anywhere;\n display: block;\n}\n.chat-widget__loading {\n display: flex;\n justify-content: flex-start;\n}\n.chat-widget__loading-bubble {\n background: var(--chat-assistant-bg);\n color: var(--chat-assistant-text);\n border-radius: calc(var(--chat-radius) * 0.65);\n border-bottom-left-radius: 0.35rem;\n padding: 0.5rem 0.75rem;\n}\n.chat-widget__loading-dots {\n display: flex;\n gap: 0.35rem;\n}\n.chat-widget__loading-dot {\n width: 0.5rem;\n height: 0.5rem;\n border-radius: 999px;\n background: var(--chat-text-disabled);\n animation: chat-widget-bounce 1s infinite ease-in-out;\n}\n.chat-widget__loading-dot[data-delay="1"] {\n animation-delay: 0.1s;\n}\n.chat-widget__loading-dot[data-delay="2"] {\n animation-delay: 0.2s;\n}\n@keyframes chat-widget-bounce {\n 0%, 80%, 100% {\n transform: scale(0.6);\n opacity: 0.4;\n }\n 40% {\n transform: scale(1);\n opacity: 1;\n }\n}\n.chat-widget__input {\n border-top: 1px solid var(--chat-border);\n padding: 0.25rem 0 0.75rem;\n background: var(--chat-input-bg);\n}\n.chat-widget__form {\n position: relative;\n}\n.chat-widget__textarea {\n width: 100%;\n border: 0;\n padding: 0.75rem 5.25rem 0.75rem 0.75rem;\n background: transparent;\n font-size: 0.925rem;\n resize: none;\n color: var(--chat-input-text);\n font-family: inherit;\n}\n.chat-widget__textarea::-moz-placeholder {\n color: var(--chat-input-placeholder);\n}\n.chat-widget__textarea::placeholder {\n color: var(--chat-input-placeholder);\n}\n.chat-widget__textarea:focus-visible {\n outline: none;\n}\n.chat-widget__textarea:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.chat-widget__toolbar {\n position: absolute;\n top: 0;\n right: 3.75rem;\n height: 100%;\n display: flex;\n align-items: center;\n padding: 0 0.5rem;\n border-right: 1px solid var(--chat-border);\n}\n.chat-widget__submit {\n position: absolute;\n top: 50%;\n right: 0.75rem;\n transform: translateY(-50%);\n background: transparent;\n border: 0;\n width: 2.5rem;\n height: 2.5rem;\n display: grid;\n place-items: center;\n color: var(--chat-primary);\n cursor: pointer;\n}\n.chat-widget__submit:disabled {\n color: var(--chat-text-disabled);\n cursor: not-allowed;\n}\n.chat-widget__submit:not(:disabled):hover {\n color: var(--chat-primary-hover);\n}\n.chat-widget__send-icon {\n width: 1.2rem;\n height: 1.2rem;\n}\n.chat-widget__mic-button {\n position: relative;\n border: none;\n background: transparent;\n width: 2.25rem;\n height: 2.25rem;\n display: grid;\n place-items: center;\n color: var(--chat-primary);\n cursor: pointer;\n border-radius: 999px;\n}\n.chat-widget__mic-button:disabled {\n color: var(--chat-text-disabled);\n cursor: not-allowed;\n}\n.chat-widget__mic-button--active {\n color: var(--chat-primary-hover);\n background: var(--chat-primary-subtle);\n}\n.chat-widget__mic-icon {\n width: 1rem;\n height: 1rem;\n}\n.chat-widget__mic-bar {\n position: absolute;\n bottom: 0.1rem;\n left: 50%;\n width: 16px;\n height: 2px;\n border-radius: 999px;\n background: var(--chat-border);\n overflow: hidden;\n display: block;\n transform: translateX(-50%);\n pointer-events: none;\n}\n.chat-widget__mic-bar-fill {\n display: block;\n width: 100%;\n height: 100%;\n background: currentColor;\n transform-origin: left;\n transition: transform 0.12s linear;\n}\n.chat-widget__voice {\n display: flex;\n margin-top: 0.25rem;\n}\n.chat-widget__voice-button {\n border: none;\n background: none;\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.1rem 0;\n font-size: 0.8rem;\n font-weight: 500;\n color: var(--chat-primary);\n cursor: pointer;\n}\n.chat-widget__voice-button:disabled {\n color: var(--chat-text-disabled);\n cursor: not-allowed;\n}\n.chat-widget__voice-button--active {\n color: var(--chat-primary-hover);\n}\n.chat-widget__voice-icon {\n width: 0.95rem;\n height: 0.95rem;\n}\n.chat-widget__voice-icon--spin {\n animation: chat-widget-spin 1s linear infinite;\n}\n@keyframes chat-widget-spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n.chat-widget__collapsed {\n position: relative;\n margin-bottom: 0.25rem;\n}\n.chat-widget__collapsed-content {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows 300ms ease-out;\n}\n.chat-widget__collapsed-content--expanded {\n grid-template-rows: 1fr;\n}\n.chat-widget__collapsed-content-inner {\n overflow: hidden;\n}\n.chat-widget__collapsed-preview {\n position: relative;\n max-height: 1.5em;\n overflow: hidden;\n opacity: 0.6;\n pointer-events: none;\n transition: opacity 300ms ease-out, max-height 300ms ease-out;\n}\n.chat-widget__collapsed-preview--hidden {\n opacity: 0;\n max-height: 0;\n pointer-events: none;\n}\n.chat-widget__collapsed-gradient {\n position: absolute;\n top: 0;\n right: 0;\n width: 70%;\n height: 100%;\n background:\n linear-gradient(\n to right,\n transparent 0%,\n var(--chat-background) 90%);\n pointer-events: none;\n}\n.chat-widget__collapsed-toggle {\n display: inline-block;\n padding: 0;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--chat-primary);\n background: transparent;\n border: none;\n cursor: pointer;\n}\n.chat-widget__collapsed-toggle:hover {\n text-decoration: underline;\n}\n@keyframes chat-widget-slide-up {\n from {\n opacity: 1;\n transform: translateY(0);\n max-height: 200px;\n }\n to {\n opacity: 0.6;\n transform: translateY(-8px);\n max-height: 1.5em;\n }\n}\n.chat-widget__collapsed--animating .chat-widget__collapsed-preview {\n animation: chat-widget-slide-up 300ms ease-out forwards;\n}\n');
30
+ styleInject(':root[data-chat-widget],\n[data-chat-widget] {\n --chat-primary: #3b82f6;\n --chat-primary-text: #ffffff;\n --chat-primary-hover: #2563eb;\n --chat-primary-subtle: rgba(59, 130, 246, 0.1);\n --chat-background: #ffffff;\n --chat-background-secondary: #f9fafb;\n --chat-background-tertiary: #f3f4f6;\n --chat-border: #e5e7eb;\n --chat-border-light: #f3f4f6;\n --chat-widget-border-width: 1px;\n --chat-text: #111827;\n --chat-text-secondary: #4b5563;\n --chat-text-muted: #6b7280;\n --chat-text-disabled: #9ca3af;\n --chat-link: #2563eb;\n --chat-link-hover: #1d4ed8;\n --chat-success: #22c55e;\n --chat-success-bg: rgba(34, 197, 94, 0.1);\n --chat-error: #ef4444;\n --chat-error-bg: rgba(239, 68, 68, 0.1);\n --chat-header-text: #ffffff;\n --chat-user-text: #ffffff;\n --chat-assistant-bg: transparent;\n --chat-assistant-text: var(--chat-text);\n --chat-input-bg: var(--chat-background);\n --chat-input-text: var(--chat-text);\n --chat-input-placeholder: var(--chat-text-muted);\n --chat-thought-border: var(--chat-border);\n --chat-font-family:\n "Inter",\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n sans-serif;\n --chat-radius: 0.75rem;\n --chat-font-size: 0.925rem;\n --chat-thought-font-size: 0.75rem;\n --chat-shadow: 0 20px 45px rgba(0, 0, 0, 0.12);\n --chat-shadow-sm: 0 4px 12px rgba(0, 0, 0, 0.1);\n --chat-overlay-bg: rgba(0, 0, 0, 0.3);\n}\n.chat-widget {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 24rem;\n background: var(--chat-background);\n border: var(--chat-widget-border-width) solid var(--chat-border);\n border-radius: 0;\n box-shadow: var(--chat-shadow);\n overflow: hidden;\n font-family: var(--chat-font-family);\n color: var(--chat-assistant-text);\n}\n.chat-widget--popup-content {\n border: 0;\n border-radius: inherit;\n box-shadow: none;\n min-height: 0;\n}\n.chat-widget__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: 40px;\n padding: 0.75rem 1rem;\n background: var(--chat-primary);\n color: var(--chat-header-text);\n}\n.chat-widget__title {\n margin: 0;\n font-size: 0.875rem;\n font-weight: 600;\n}\n.chat-widget__messages {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 1rem;\n display: flex;\n flex-direction: column;\n gap: 1rem;\n min-width: 0;\n}\n.chat-widget__message {\n display: flex;\n flex-direction: column;\n gap: 0;\n min-width: 0;\n}\n.chat-widget__message-row {\n display: flex;\n min-width: 0;\n}\n.chat-widget__message-row--user {\n justify-content: flex-end;\n}\n.chat-widget__message-row--assistant {\n justify-content: flex-start;\n}\n.chat-widget__bubble {\n max-width: 90%;\n padding: 0.5rem 0.25rem;\n border-radius: calc(var(--chat-radius) * 0.65);\n font-size: var(--chat-font-size);\n min-width: 0;\n overflow-x: hidden;\n}\n.chat-widget__bubble--user {\n background: var(--chat-primary);\n color: var(--chat-user-text);\n border-bottom-right-radius: 0.35rem;\n padding-left: 0.375rem;\n padding-right: 0.375rem;\n}\n.chat-widget__bubble--assistant {\n width: 90%;\n max-width: 90%;\n background: var(--chat-assistant-bg);\n color: var(--chat-assistant-text);\n border-bottom-left-radius: 0.35rem;\n}\n.chat-widget__widget {\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow-x: hidden;\n}\n.widget-customer-root {\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow-x: hidden;\n}\n.chat-widget__markdown {\n white-space: normal;\n font-size: var(--chat-font-size);\n}\n.chat-widget__markdown h1 {\n font-size: calc(var(--chat-font-size) * 1.4);\n}\n.chat-widget__markdown h2 {\n font-size: calc(var(--chat-font-size) * 1.25);\n}\n.chat-widget__markdown h3 {\n font-size: calc(var(--chat-font-size) * 1.1);\n}\n.chat-widget__markdown h4 {\n font-size: calc(var(--chat-font-size) * 1.05);\n}\n.chat-widget__markdown h5 {\n font-size: calc(var(--chat-font-size) * 1);\n}\n.chat-widget__markdown h6 {\n font-size: calc(var(--chat-font-size) * 0.95);\n}\n.chat-widget__anchor-button {\n position: fixed;\n bottom: 20px;\n right: 20px;\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.65rem 0.85rem;\n background: var(--chat-primary);\n color: var(--chat-primary-text);\n border: none;\n border-radius: 999px;\n box-shadow: var(--chat-shadow);\n cursor: pointer;\n font-weight: 600;\n z-index: 99999;\n}\n.chat-widget__anchor-button:hover {\n background: var(--chat-primary-hover);\n}\n.chat-widget__anchor--left {\n right: auto;\n left: 20px;\n}\n.chat-widget__anchor-icon {\n width: 1.1rem;\n height: 1.1rem;\n}\n.chat-widget__popup {\n position: fixed;\n bottom: 80px;\n right: 20px;\n z-index: 99998;\n}\n.chat-widget__anchor--left.chat-widget__popup {\n right: auto;\n left: 20px;\n}\n.chat-widget__popup-inner {\n width: 384px;\n max-width: calc(100vw - 40px);\n height: 500px;\n max-height: calc(100vh - 140px);\n box-shadow: var(--chat-shadow);\n border-radius: 12px;\n overflow: hidden;\n}\n.chat-widget__markdown a {\n color: var(--chat-link);\n text-decoration: underline;\n}\n.chat-widget__markdown a:hover {\n color: var(--chat-link-hover);\n}\n.chat-widget__markdown table {\n width: 100%;\n border-collapse: collapse;\n margin: 0.5rem 0;\n}\n.chat-widget__markdown th,\n.chat-widget__markdown td {\n border: 1px solid var(--chat-border);\n padding: 0.5rem;\n text-align: left;\n vertical-align: top;\n}\n.chat-widget__markdown thead th {\n background: var(--chat-assistant-bg);\n color: var(--chat-assistant-text);\n font-weight: 600;\n}\n.chat-widget__thoughts {\n min-width: 0;\n --chat-font-size: var(--chat-thought-font-size);\n}\n.chat-widget__details {\n border: 0;\n}\n.chat-widget__thoughts-summary {\n list-style: none;\n display: flex;\n align-items: center;\n gap: 0.35rem;\n cursor: pointer;\n color: var(--chat-text-muted);\n font-size: 0.8125rem;\n}\n.chat-widget__thoughts-summary:hover {\n color: var(--chat-assistant-text);\n}\n.chat-widget__thoughts-icon-container {\n display: flex;\n border: 1px solid var(--chat-border);\n border-radius: 999px;\n align-items: center;\n justify-content: center;\n width: 1rem;\n height: 1rem;\n}\n.chat-widget__thoughts-icon {\n width: 0.75rem;\n height: 0.75rem;\n transition: transform 0.2s ease;\n}\n.chat-widget__details[open] .chat-widget__thoughts-icon {\n transform: rotate(90deg);\n}\n.chat-widget__thoughts-content {\n margin-top: 0.5rem;\n margin-left: 0.4rem;\n padding: 0.75rem;\n border-left: 2px solid var(--chat-thought-border);\n border-color: var(--chat-primary);\n max-width: 100%;\n overflow-x: auto;\n}\n.chat-widget__thoughts-text {\n margin: 0;\n line-height: 1.5;\n color: var(--chat-text-secondary);\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: anywhere;\n display: block;\n}\n.chat-widget__loading {\n display: flex;\n justify-content: flex-start;\n}\n.chat-widget__loading-bubble {\n background: var(--chat-assistant-bg);\n color: var(--chat-assistant-text);\n border-radius: calc(var(--chat-radius) * 0.65);\n border-bottom-left-radius: 0.35rem;\n padding: 0.5rem 0.75rem;\n}\n.chat-widget__loading-dots {\n display: flex;\n gap: 0.35rem;\n}\n.chat-widget__loading-dot {\n width: 0.5rem;\n height: 0.5rem;\n border-radius: 999px;\n background: var(--chat-text-disabled);\n animation: chat-widget-bounce 1s infinite ease-in-out;\n}\n.chat-widget__loading-dot[data-delay="1"] {\n animation-delay: 0.1s;\n}\n.chat-widget__loading-dot[data-delay="2"] {\n animation-delay: 0.2s;\n}\n@keyframes chat-widget-bounce {\n 0%, 80%, 100% {\n transform: scale(0.6);\n opacity: 0.4;\n }\n 40% {\n transform: scale(1);\n opacity: 1;\n }\n}\n.chat-widget__input {\n border-top: 1px solid var(--chat-border);\n padding: 0.25rem 0 0.75rem;\n background: var(--chat-input-bg);\n}\n.chat-widget__form {\n position: relative;\n}\n.chat-widget__textarea {\n width: 100%;\n border: 0;\n padding: 0.75rem 5.25rem 0.75rem 0.75rem;\n background: transparent;\n font-size: 0.925rem;\n resize: none;\n color: var(--chat-input-text);\n font-family: inherit;\n}\n.chat-widget__textarea::-moz-placeholder {\n color: var(--chat-input-placeholder);\n}\n.chat-widget__textarea::placeholder {\n color: var(--chat-input-placeholder);\n}\n.chat-widget__textarea:focus-visible {\n outline: none;\n}\n.chat-widget__textarea:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.chat-widget__toolbar {\n position: absolute;\n top: 0;\n right: 3.75rem;\n height: 100%;\n display: flex;\n align-items: center;\n padding: 0 0.5rem;\n border-right: 1px solid var(--chat-border);\n}\n.chat-widget__submit {\n position: absolute;\n top: 50%;\n right: 0.75rem;\n transform: translateY(-50%);\n background: transparent;\n border: 0;\n width: 2.5rem;\n height: 2.5rem;\n display: grid;\n place-items: center;\n color: var(--chat-primary);\n cursor: pointer;\n}\n.chat-widget__submit:disabled {\n color: var(--chat-text-disabled);\n cursor: not-allowed;\n}\n.chat-widget__submit:not(:disabled):hover {\n color: var(--chat-primary-hover);\n}\n.chat-widget__send-icon {\n width: 1.2rem;\n height: 1.2rem;\n}\n.chat-widget__mic-button {\n position: relative;\n border: none;\n background: transparent;\n width: 2.25rem;\n height: 2.25rem;\n display: grid;\n place-items: center;\n color: var(--chat-primary);\n cursor: pointer;\n border-radius: 999px;\n}\n.chat-widget__mic-button:disabled {\n color: var(--chat-text-disabled);\n cursor: not-allowed;\n}\n.chat-widget__mic-button--active {\n color: var(--chat-primary-hover);\n background: var(--chat-primary-subtle);\n}\n.chat-widget__mic-icon {\n width: 1rem;\n height: 1rem;\n}\n.chat-widget__mic-bar {\n position: absolute;\n bottom: 0.1rem;\n left: 50%;\n width: 16px;\n height: 2px;\n border-radius: 999px;\n background: var(--chat-border);\n overflow: hidden;\n display: block;\n transform: translateX(-50%);\n pointer-events: none;\n}\n.chat-widget__mic-bar-fill {\n display: block;\n width: 100%;\n height: 100%;\n background: currentColor;\n transform-origin: left;\n transition: transform 0.12s linear;\n}\n.chat-widget__voice {\n display: flex;\n margin-top: 0.25rem;\n}\n.chat-widget__voice-button {\n border: none;\n background: none;\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.1rem 0;\n font-size: 0.8rem;\n font-weight: 500;\n color: var(--chat-primary);\n cursor: pointer;\n}\n.chat-widget__voice-button:disabled {\n color: var(--chat-text-disabled);\n cursor: not-allowed;\n}\n.chat-widget__voice-button--active {\n color: var(--chat-primary-hover);\n}\n.chat-widget__voice-icon {\n width: 0.95rem;\n height: 0.95rem;\n}\n.chat-widget__voice-icon--spin {\n animation: chat-widget-spin 1s linear infinite;\n}\n@keyframes chat-widget-spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n}\n.chat-widget__collapsed {\n position: relative;\n margin-bottom: 0.25rem;\n}\n.chat-widget__collapsed-content {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows 300ms ease-out;\n}\n.chat-widget__collapsed-content--expanded {\n grid-template-rows: 1fr;\n}\n.chat-widget__collapsed-content-inner {\n overflow: hidden;\n}\n.chat-widget__collapsed-preview {\n position: relative;\n max-height: 1.5em;\n overflow: hidden;\n opacity: 0.6;\n pointer-events: none;\n transition: opacity 300ms ease-out, max-height 300ms ease-out;\n}\n.chat-widget__collapsed-preview--hidden {\n opacity: 0;\n max-height: 0;\n pointer-events: none;\n}\n.chat-widget__collapsed-gradient {\n position: absolute;\n top: 0;\n right: 0;\n width: 70%;\n height: 100%;\n background:\n linear-gradient(\n to right,\n transparent 0%,\n var(--chat-background) 90%);\n pointer-events: none;\n}\n.chat-widget__collapsed-toggle {\n display: inline-block;\n padding: 0;\n font-size: 0.75rem;\n font-weight: 500;\n color: var(--chat-primary);\n background: transparent;\n border: none;\n cursor: pointer;\n}\n.chat-widget__collapsed-toggle:hover {\n text-decoration: underline;\n}\n@keyframes chat-widget-slide-up {\n from {\n opacity: 1;\n transform: translateY(0);\n max-height: 200px;\n }\n to {\n opacity: 0.6;\n transform: translateY(-8px);\n max-height: 1.5em;\n }\n}\n.chat-widget__collapsed--animating .chat-widget__collapsed-preview {\n animation: chat-widget-slide-up 300ms ease-out forwards;\n}\n');
31
31
 
32
32
  // lib/chat/ChatWidget.tsx
33
33
  import { Send, StopCircle } from "lucide-react";
34
- import { forwardRef, useCallback as useCallback6, useEffect as useEffect6, useImperativeHandle, useMemo as useMemo5, useRef as useRef5, useState as useState9 } from "react";
34
+ import { forwardRef, useCallback as useCallback7, useEffect as useEffect6, useImperativeHandle, useMemo as useMemo5, useRef as useRef5, useState as useState9 } from "react";
35
35
 
36
36
  // lib/api/fetchApprovalConfig.ts
37
37
  async function fetchApprovalConfig(options) {
@@ -21534,7 +21534,7 @@ function lastAssistantMessageIsCompleteWithToolCalls({
21534
21534
  }
21535
21535
 
21536
21536
  // lib/hooks/useChat.ts
21537
- import { useEffect, useMemo, useRef, useState } from "react";
21537
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
21538
21538
 
21539
21539
  // lib/hooks/transform.ts
21540
21540
  function transformMessage(msg) {
@@ -21574,7 +21574,7 @@ function transformMessage(msg) {
21574
21574
  }
21575
21575
  return;
21576
21576
  }
21577
- if (part.type === "data-thoughts" || part.type === "data-transfer") {
21577
+ if (part.type === "data-thoughts" || part.type === "data-transfer" || part.type === "data-structured-input") {
21578
21578
  return;
21579
21579
  }
21580
21580
  if (groupStack.length > 0) {
@@ -21694,6 +21694,22 @@ function useChat({
21694
21694
  onData?.(dataPart);
21695
21695
  }
21696
21696
  });
21697
+ const sendStructuredMessage = useCallback(
21698
+ async (text4, payload) => {
21699
+ const trimmed = text4.trim();
21700
+ if (!trimmed) return;
21701
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
21702
+ throw new Error("Structured message payload must be a JSON object");
21703
+ }
21704
+ await sendMessage({
21705
+ parts: [
21706
+ { type: "text", text: trimmed },
21707
+ { type: "data-structured-input", data: payload }
21708
+ ]
21709
+ });
21710
+ },
21711
+ [sendMessage]
21712
+ );
21697
21713
  const [isLoadingInitial, setIsLoadingInitial] = useState(true);
21698
21714
  useEffect(() => {
21699
21715
  const fetchInitialMessages = async () => {
@@ -21770,11 +21786,14 @@ function useChat({
21770
21786
  }
21771
21787
  return null;
21772
21788
  }, [messages]);
21789
+ const canSendMessage = status === "ready" && !pendingToolOutput && !pendingToolApproval;
21773
21790
  return {
21774
21791
  messages: rtnMessages,
21775
21792
  status,
21776
21793
  isLoadingInitial,
21794
+ canSendMessage,
21777
21795
  sendMessage,
21796
+ sendStructuredMessage,
21778
21797
  stop,
21779
21798
  setMessages,
21780
21799
  addToolOutput,
@@ -21785,7 +21804,7 @@ function useChat({
21785
21804
  }
21786
21805
 
21787
21806
  // lib/hooks/useFeedback.ts
21788
- import { useCallback, useState as useState2 } from "react";
21807
+ import { useCallback as useCallback2, useState as useState2 } from "react";
21789
21808
  function useFeedback({
21790
21809
  api,
21791
21810
  threadId,
@@ -21796,7 +21815,7 @@ function useFeedback({
21796
21815
  const [submittedFeedback, setSubmittedFeedback] = useState2({});
21797
21816
  const [isSubmitting, setIsSubmitting] = useState2(null);
21798
21817
  const [error48, setError] = useState2(null);
21799
- const submitFeedback = useCallback(
21818
+ const submitFeedback = useCallback2(
21800
21819
  async (messageId, { rating, improvementText, notes }) => {
21801
21820
  setIsSubmitting(messageId);
21802
21821
  setError(null);
@@ -21852,13 +21871,13 @@ function useFeedback({
21852
21871
  },
21853
21872
  [baseUrl, token, threadId, agentId, agentVersion]
21854
21873
  );
21855
- const getFeedbackForMessage = useCallback(
21874
+ const getFeedbackForMessage = useCallback2(
21856
21875
  (messageId) => {
21857
21876
  return submittedFeedback[messageId];
21858
21877
  },
21859
21878
  [submittedFeedback]
21860
21879
  );
21861
- const hasFeedback = useCallback(
21880
+ const hasFeedback = useCallback2(
21862
21881
  (messageId) => {
21863
21882
  return messageId in submittedFeedback;
21864
21883
  },
@@ -21880,8 +21899,11 @@ function cn(...inputs) {
21880
21899
  return twMerge(clsx(inputs));
21881
21900
  }
21882
21901
 
21902
+ // lib/chat/components/input-fields/InputFields.css
21903
+ styleInject(".input-field {\n margin-bottom: 1rem;\n}\n.input-field__label {\n display: block;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--chat-assistant-text);\n margin-bottom: 0.375rem;\n}\n.input-field__required {\n color: var(--chat-error);\n margin-left: 0.125rem;\n}\n.input-field__input,\n.input-field__textarea {\n width: 100%;\n padding: 0.5rem 0.75rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: var(--chat-input-text);\n background-color: var(--chat-input-bg);\n border: 1px solid var(--chat-border);\n border-radius: calc(var(--chat-radius) * 0.5);\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n font-family: var(--chat-font-family);\n}\n.input-field__input:focus,\n.input-field__textarea:focus {\n outline: none;\n border-color: var(--chat-primary);\n box-shadow: 0 0 0 3px var(--chat-primary-subtle);\n}\n.input-field__textarea {\n resize: vertical;\n min-height: 5rem;\n}\n.input-field__options {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n.input-field__option {\n display: flex;\n align-items: flex-start;\n gap: 0.5rem;\n cursor: pointer;\n padding: 0.5rem;\n border-radius: calc(var(--chat-radius) * 0.5);\n transition: background-color 0.15s ease-in-out;\n}\n.input-field__option:hover {\n background-color: var(--chat-border);\n}\n.input-field__radio,\n.input-field__checkbox {\n flex-shrink: 0;\n margin-top: 0.125rem;\n width: 1rem;\n height: 1rem;\n cursor: pointer;\n accent-color: var(--chat-primary);\n}\n.input-field__option-content {\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n}\n.input-field__option-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--chat-assistant-text);\n}\n.input-field__option-description {\n font-size: 0.75rem;\n color: var(--chat-input-placeholder);\n}\n.input-field--checkbox .input-field__checkbox-wrapper {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n padding: 0.5rem 0;\n}\n.input-field--checkbox .input-field__checkbox-label {\n font-size: 0.875rem;\n color: var(--chat-assistant-text);\n}\n.input-field--number .input-field__input {\n -moz-appearance: textfield;\n}\n.input-field--number .input-field__input::-webkit-outer-spin-button,\n.input-field--number .input-field__input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n.input-field--date .input-field__input {\n cursor: pointer;\n}\n");
21904
+
21883
21905
  // lib/chat/components/InputFormOverlay.css
21884
- styleInject('@import "./input-fields/InputFields.css";\n.input-form-overlay {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n top: 0;\n z-index: 10;\n display: flex;\n flex-direction: column;\n justify-content: flex-end;\n pointer-events: none;\n}\n@keyframes slideUp {\n from {\n transform: translateY(100%);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n.input-form-overlay__content {\n pointer-events: auto;\n animation: slideUp 0.2s ease-out;\n display: flex;\n flex-direction: column;\n background-color: var(--chat-background);\n border-top: 1px solid var(--chat-border);\n border-radius: var(--chat-radius) var(--chat-radius) 0 0;\n box-shadow: var(--chat-shadow-sm);\n max-height: 80%;\n font-family: var(--chat-font-family);\n}\n.input-form-overlay__title {\n font-size: 1rem;\n font-weight: 600;\n color: var(--chat-assistant-text);\n margin: 0 0 0.375rem 0;\n}\n.input-form-overlay__description {\n font-size: 0.8125rem;\n color: var(--chat-input-placeholder);\n margin: 0 0 1rem 0;\n line-height: 1.4;\n}\n.input-form-overlay__form {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n.input-form-overlay__scrollable {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n padding: 1rem 1.25rem;\n}\n.input-form-overlay__fields {\n}\n.input-form-overlay__footer {\n flex-shrink: 0;\n padding: 0.5rem 1.25rem;\n border-top: 1px solid var(--chat-border);\n}\n.input-form-overlay__actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n justify-content: flex-start;\n}\n.input-form-overlay__button {\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n font-weight: 500;\n border-radius: calc(var(--chat-radius) * 0.5);\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n border: none;\n}\n.input-form-overlay__button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.input-form-overlay__button--primary {\n background-color: var(--chat-primary);\n color: var(--chat-primary-text);\n}\n.input-form-overlay__button--primary:hover:not(:disabled) {\n background-color: var(--chat-primary-hover);\n}\n.input-form-overlay__button--secondary {\n background-color: var(--chat-border);\n color: var(--chat-assistant-text);\n}\n.input-form-overlay__button--secondary:hover:not(:disabled) {\n opacity: 0.8;\n}\n.input-form-overlay__freeform-toggle {\n padding: 0.5rem 0;\n font-size: 0.75rem;\n color: var(--chat-input-placeholder);\n background: none;\n border: none;\n cursor: pointer;\n transition: color 0.15s ease-in-out;\n white-space: nowrap;\n}\n.input-form-overlay__freeform-toggle:hover {\n color: var(--chat-primary);\n text-decoration: underline;\n}\n.input-form-overlay__freeform {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n.input-form-overlay__freeform-body {\n padding: 1rem 1.25rem;\n}\n.input-form-overlay__freeform-input {\n flex: 1;\n width: 100%;\n padding: 0.625rem;\n font-size: var(--chat-font-size);\n line-height: 1.4;\n color: var(--chat-input-text);\n background-color: var(--chat-input-bg);\n border: 1px solid var(--chat-border);\n border-radius: calc(var(--chat-radius) * 0.5);\n resize: vertical;\n min-height: 5rem;\n font-family: var(--chat-font-family);\n}\n.input-form-overlay__freeform-input:focus {\n outline: none;\n border-color: var(--chat-primary);\n box-shadow: 0 0 0 2px var(--chat-primary-subtle);\n}\n');
21906
+ styleInject("@import .input-form-overlay { position: absolute; bottom: 0; left: 0; right: 0; top: 0; z-index: 10; display: flex; flex-direction: column; justify-content: flex-end; pointer-events: none; }\n@keyframes slideUp {\n from {\n transform: translateY(100%);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n.input-form-overlay__content {\n pointer-events: auto;\n animation: slideUp 0.2s ease-out;\n display: flex;\n flex-direction: column;\n background-color: var(--chat-background);\n border-top: 1px solid var(--chat-border);\n border-radius: var(--chat-radius) var(--chat-radius) 0 0;\n box-shadow: var(--chat-shadow-sm);\n max-height: 80%;\n font-family: var(--chat-font-family);\n}\n.input-form-overlay__title {\n font-size: 1rem;\n font-weight: 600;\n color: var(--chat-assistant-text);\n margin: 0 0 0.375rem 0;\n}\n.input-form-overlay__description {\n font-size: 0.8125rem;\n color: var(--chat-input-placeholder);\n margin: 0 0 1rem 0;\n line-height: 1.4;\n}\n.input-form-overlay__form {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n.input-form-overlay__scrollable {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n padding: 1rem 1.25rem;\n}\n.input-form-overlay__fields {\n}\n.input-form-overlay__footer {\n flex-shrink: 0;\n padding: 0.5rem 1.25rem;\n border-top: 1px solid var(--chat-border);\n}\n.input-form-overlay__actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n justify-content: flex-start;\n}\n.input-form-overlay__button {\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n font-weight: 500;\n border-radius: calc(var(--chat-radius) * 0.5);\n cursor: pointer;\n transition: all 0.15s ease-in-out;\n border: none;\n}\n.input-form-overlay__button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.input-form-overlay__button--primary {\n background-color: var(--chat-primary);\n color: var(--chat-primary-text);\n}\n.input-form-overlay__button--primary:hover:not(:disabled) {\n background-color: var(--chat-primary-hover);\n}\n.input-form-overlay__button--secondary {\n background-color: var(--chat-border);\n color: var(--chat-assistant-text);\n}\n.input-form-overlay__button--secondary:hover:not(:disabled) {\n opacity: 0.8;\n}\n.input-form-overlay__freeform-toggle {\n padding: 0.5rem 0;\n font-size: 0.75rem;\n color: var(--chat-input-placeholder);\n background: none;\n border: none;\n cursor: pointer;\n transition: color 0.15s ease-in-out;\n white-space: nowrap;\n}\n.input-form-overlay__freeform-toggle:hover {\n color: var(--chat-primary);\n text-decoration: underline;\n}\n.input-form-overlay__freeform {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n.input-form-overlay__freeform-body {\n padding: 1rem 1.25rem;\n}\n.input-form-overlay__freeform-input {\n flex: 1;\n width: 100%;\n padding: 0.625rem;\n font-size: var(--chat-font-size);\n line-height: 1.4;\n color: var(--chat-input-text);\n background-color: var(--chat-input-bg);\n border: 1px solid var(--chat-border);\n border-radius: calc(var(--chat-radius) * 0.5);\n resize: vertical;\n min-height: 5rem;\n font-family: var(--chat-font-family);\n}\n.input-form-overlay__freeform-input:focus {\n outline: none;\n border-color: var(--chat-primary);\n box-shadow: 0 0 0 2px var(--chat-primary-subtle);\n}\n");
21885
21907
 
21886
21908
  // lib/chat/components/InputFormOverlay.tsx
21887
21909
  import { useState as useState3 } from "react";
@@ -22244,7 +22266,7 @@ function InputFormOverlay({ args, onComplete }) {
22244
22266
  // lib/chat/components/SpeechToTextButton.tsx
22245
22267
  import { Mic, MicOff } from "lucide-react";
22246
22268
  import {
22247
- useCallback as useCallback2,
22269
+ useCallback as useCallback3,
22248
22270
  useEffect as useEffect2,
22249
22271
  useRef as useRef2,
22250
22272
  useState as useState4
@@ -22279,25 +22301,25 @@ function SpeechToTextButton({
22279
22301
  const countdownFrameRef = useRef2(null);
22280
22302
  const countdownEndRef = useRef2(0);
22281
22303
  const recognitionLanguage = language ?? "en-US";
22282
- const clearSilenceTimer = useCallback2(() => {
22304
+ const clearSilenceTimer = useCallback3(() => {
22283
22305
  if (silenceTimer.current) {
22284
22306
  clearTimeout(silenceTimer.current);
22285
22307
  silenceTimer.current = null;
22286
22308
  }
22287
22309
  }, []);
22288
- const clearCountdownFrame = useCallback2(() => {
22310
+ const clearCountdownFrame = useCallback3(() => {
22289
22311
  if (countdownFrameRef.current) {
22290
22312
  cancelAnimationFrame(countdownFrameRef.current);
22291
22313
  countdownFrameRef.current = null;
22292
22314
  }
22293
22315
  }, []);
22294
- const clearFinalTimer = useCallback2(() => {
22316
+ const clearFinalTimer = useCallback3(() => {
22295
22317
  if (finalTimer.current) {
22296
22318
  clearTimeout(finalTimer.current);
22297
22319
  finalTimer.current = null;
22298
22320
  }
22299
22321
  }, []);
22300
- const stopListening = useCallback2(() => {
22322
+ const stopListening = useCallback3(() => {
22301
22323
  clearSilenceTimer();
22302
22324
  clearFinalTimer();
22303
22325
  clearCountdownFrame();
@@ -22306,26 +22328,26 @@ function SpeechToTextButton({
22306
22328
  countdownEndRef.current = 0;
22307
22329
  recognitionRef.current?.stop();
22308
22330
  }, [clearSilenceTimer, clearFinalTimer, clearCountdownFrame]);
22309
- const handleRecognitionError = useCallback2((message) => {
22331
+ const handleRecognitionError = useCallback3((message) => {
22310
22332
  console.error("Speech recognition error:", message);
22311
22333
  onError?.(message);
22312
22334
  }, [onError]);
22313
- const resetSilenceTimer = useCallback2(() => {
22335
+ const resetSilenceTimer = useCallback3(() => {
22314
22336
  if (!silenceTimeout) return;
22315
22337
  clearSilenceTimer();
22316
22338
  silenceTimer.current = setTimeout(stopListening, silenceTimeout);
22317
22339
  }, [silenceTimeout, clearSilenceTimer, stopListening]);
22318
- const dispatchInterim = useCallback2((text4) => {
22340
+ const dispatchInterim = useCallback3((text4) => {
22319
22341
  if (text4) {
22320
22342
  onInterim?.(text4);
22321
22343
  }
22322
22344
  }, [onInterim]);
22323
- const dispatchFinal = useCallback2((text4) => {
22345
+ const dispatchFinal = useCallback3((text4) => {
22324
22346
  if (text4) {
22325
22347
  onFinal?.(text4);
22326
22348
  }
22327
22349
  }, [onFinal]);
22328
- const flushFinalText = useCallback2(() => {
22350
+ const flushFinalText = useCallback3(() => {
22329
22351
  const buffered = finalTextRef.current.trim();
22330
22352
  if (buffered) {
22331
22353
  dispatchFinal(buffered);
@@ -22333,7 +22355,7 @@ function SpeechToTextButton({
22333
22355
  finalTextRef.current = "";
22334
22356
  clearFinalTimer();
22335
22357
  }, [dispatchFinal, clearFinalTimer]);
22336
- const updateCountdown = useCallback2(() => {
22358
+ const updateCountdown = useCallback3(() => {
22337
22359
  if (!countdownEndRef.current || !finalDelay) {
22338
22360
  setCountdown(0);
22339
22361
  setCountdownActive(false);
@@ -22350,7 +22372,7 @@ function SpeechToTextButton({
22350
22372
  }
22351
22373
  countdownFrameRef.current = requestAnimationFrame(updateCountdown);
22352
22374
  }, [finalDelay]);
22353
- const startCountdown = useCallback2(() => {
22375
+ const startCountdown = useCallback3(() => {
22354
22376
  if (!finalDelay) {
22355
22377
  setCountdown(0);
22356
22378
  setCountdownActive(false);
@@ -22362,7 +22384,7 @@ function SpeechToTextButton({
22362
22384
  clearCountdownFrame();
22363
22385
  countdownFrameRef.current = requestAnimationFrame(updateCountdown);
22364
22386
  }, [finalDelay, clearCountdownFrame, updateCountdown]);
22365
- const scheduleFinalFlush = useCallback2(() => {
22387
+ const scheduleFinalFlush = useCallback3(() => {
22366
22388
  clearFinalTimer();
22367
22389
  if (!finalDelay) {
22368
22390
  flushFinalText();
@@ -22371,7 +22393,7 @@ function SpeechToTextButton({
22371
22393
  startCountdown();
22372
22394
  finalTimer.current = setTimeout(flushFinalText, finalDelay);
22373
22395
  }, [clearFinalTimer, finalDelay, flushFinalText, startCountdown]);
22374
- const attachRecognitionHandlers = useCallback2((recognition) => {
22396
+ const attachRecognitionHandlers = useCallback3((recognition) => {
22375
22397
  recognition.continuous = true;
22376
22398
  recognition.interimResults = true;
22377
22399
  recognition.lang = recognitionLanguage;
@@ -22429,7 +22451,7 @@ function SpeechToTextButton({
22429
22451
  }
22430
22452
  };
22431
22453
  }, [recognitionLanguage, resetSilenceTimer, startCountdown, dispatchInterim, scheduleFinalFlush, handleRecognitionError, onListeningChange, clearSilenceTimer, flushFinalText, countdownActive]);
22432
- const ensureRecognition = useCallback2(() => {
22454
+ const ensureRecognition = useCallback3(() => {
22433
22455
  if (typeof window === "undefined") {
22434
22456
  return null;
22435
22457
  }
@@ -22444,7 +22466,7 @@ function SpeechToTextButton({
22444
22466
  attachRecognitionHandlers(recognitionRef.current);
22445
22467
  return recognitionRef.current;
22446
22468
  }, [attachRecognitionHandlers, handleRecognitionError]);
22447
- const toggleListening = useCallback2(() => {
22469
+ const toggleListening = useCallback3(() => {
22448
22470
  if (disabled) {
22449
22471
  return;
22450
22472
  }
@@ -22608,7 +22630,7 @@ function ToolApprovalOverlay({ approval, config: config2, configLoading, onAppro
22608
22630
  }
22609
22631
 
22610
22632
  // lib/chat/display-modes/BriefDisplayMode.tsx
22611
- import React2, { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3, useState as useState6 } from "react";
22633
+ import React2, { useCallback as useCallback4, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3, useState as useState6 } from "react";
22612
22634
  import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
22613
22635
  function CollapsedDisplay({
22614
22636
  collapsed,
@@ -22627,7 +22649,7 @@ function CollapsedDisplay({
22627
22649
  }
22628
22650
  partsCountRef.current = collapsed.parts.length;
22629
22651
  }, [collapsed.parts.length, isExpanded]);
22630
- const handleToggle = useCallback3(() => {
22652
+ const handleToggle = useCallback4(() => {
22631
22653
  setIsExpanded((prev) => !prev);
22632
22654
  }, []);
22633
22655
  const collapsedClasses = [
@@ -22798,7 +22820,7 @@ function FullDisplayMode({
22798
22820
  }
22799
22821
 
22800
22822
  // lib/chat/renderers/MessageRenderer.tsx
22801
- import React5, { useCallback as useCallback5, useMemo as useMemo4 } from "react";
22823
+ import React5, { useCallback as useCallback6, useMemo as useMemo4 } from "react";
22802
22824
  import ReactMarkdown from "react-markdown";
22803
22825
 
22804
22826
  // ../../node_modules/.pnpm/ccount@2.0.1/node_modules/ccount/index.js
@@ -26265,7 +26287,7 @@ styleInject(".chat-widget__feedback {\n display: flex;\n align-items: center;\
26265
26287
 
26266
26288
  // lib/chat/components/MessageFeedback.tsx
26267
26289
  import { MessageSquare, MessageSquareText, ThumbsDown, ThumbsUp } from "lucide-react";
26268
- import { useCallback as useCallback4, useEffect as useEffect4, useState as useState7 } from "react";
26290
+ import { useCallback as useCallback5, useEffect as useEffect4, useState as useState7 } from "react";
26269
26291
  import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
26270
26292
  var classNames = {
26271
26293
  wrapper: "chat-widget__feedback-wrapper",
@@ -26308,7 +26330,7 @@ var MessageFeedback = ({
26308
26330
  setCommentText(existingComment);
26309
26331
  }
26310
26332
  }, [existingRating, existingComment]);
26311
- const handlePositiveClick = useCallback4(() => {
26333
+ const handlePositiveClick = useCallback5(() => {
26312
26334
  if (savedRating === "positive") {
26313
26335
  setSavedRating(null);
26314
26336
  setSavedComment("");
@@ -26321,7 +26343,7 @@ var MessageFeedback = ({
26321
26343
  onSubmit(messageId, { rating: "positive" });
26322
26344
  }
26323
26345
  }, [messageId, savedRating, onSubmit]);
26324
- const handleNegativeClick = useCallback4(() => {
26346
+ const handleNegativeClick = useCallback5(() => {
26325
26347
  if (savedRating === "negative") {
26326
26348
  setSavedRating(null);
26327
26349
  setSavedComment("");
@@ -26337,7 +26359,7 @@ var MessageFeedback = ({
26337
26359
  onSubmit(messageId, { rating: "negative" });
26338
26360
  }
26339
26361
  }, [messageId, savedRating, requireCommentForNegative, onSubmit]);
26340
- const handleCommentToggle = useCallback4(() => {
26362
+ const handleCommentToggle = useCallback5(() => {
26341
26363
  if (showCommentBox) {
26342
26364
  setShowCommentBox(false);
26343
26365
  if (pendingRating === "negative" && requireCommentForNegative) {
@@ -26348,14 +26370,14 @@ var MessageFeedback = ({
26348
26370
  setShowCommentBox(true);
26349
26371
  }
26350
26372
  }, [showCommentBox, pendingRating, requireCommentForNegative, savedComment]);
26351
- const handleCommentCancel = useCallback4(() => {
26373
+ const handleCommentCancel = useCallback5(() => {
26352
26374
  setShowCommentBox(false);
26353
26375
  setCommentText(savedComment);
26354
26376
  if (pendingRating === "negative" && requireCommentForNegative) {
26355
26377
  setPendingRating(null);
26356
26378
  }
26357
26379
  }, [pendingRating, requireCommentForNegative, savedComment]);
26358
- const handleCommentSubmit = useCallback4(() => {
26380
+ const handleCommentSubmit = useCallback5(() => {
26359
26381
  const ratingToSubmit = pendingRating ?? savedRating;
26360
26382
  if (ratingToSubmit === "negative" && requireCommentForNegative && !commentText.trim()) {
26361
26383
  return;
@@ -26609,7 +26631,16 @@ function renderError(container, message) {
26609
26631
  errorDiv.textContent = message;
26610
26632
  container.appendChild(errorDiv);
26611
26633
  }
26612
- function WidgetRenderer({ widget, payload, enriched, messageContext, invokeTool }) {
26634
+ function WidgetRenderer({
26635
+ widget,
26636
+ payload,
26637
+ enriched,
26638
+ messageContext,
26639
+ invokeTool,
26640
+ canSendMessage,
26641
+ sendMessage,
26642
+ sendStructuredMessage
26643
+ }) {
26613
26644
  const containerRef = useRef4(null);
26614
26645
  const rootRef = useRef4(null);
26615
26646
  const pendingRootUnmountRef = useRef4(null);
@@ -26661,7 +26692,13 @@ function WidgetRenderer({ widget, payload, enriched, messageContext, invokeTool
26661
26692
  }
26662
26693
  let element;
26663
26694
  try {
26664
- element = widget.render(payload, enriched, { messageContext, invokeTool });
26695
+ element = widget.render(payload, enriched, {
26696
+ messageContext,
26697
+ invokeTool,
26698
+ canSendMessage,
26699
+ sendMessage,
26700
+ sendStructuredMessage
26701
+ });
26665
26702
  } catch (error48) {
26666
26703
  console.error(`Widget "${widget.widgetType}" render function threw:`, error48);
26667
26704
  renderError(containerRef.current, `Widget render error: ${widget.widgetType}`);
@@ -26722,10 +26759,28 @@ To fix, add your ReactDOM to the widget config:
26722
26759
  renderError(containerRef.current, `Widget system error: ${widget.widgetType}`);
26723
26760
  }
26724
26761
  }
26725
- }, [isSdk, widget, payload, enriched, payloadHash, enrichedHash, messageContext, invokeTool]);
26762
+ }, [
26763
+ isSdk,
26764
+ widget,
26765
+ payload,
26766
+ enriched,
26767
+ payloadHash,
26768
+ enrichedHash,
26769
+ messageContext,
26770
+ invokeTool,
26771
+ canSendMessage,
26772
+ sendMessage,
26773
+ sendStructuredMessage
26774
+ ]);
26726
26775
  if (isSdk) {
26727
26776
  try {
26728
- const element = widget.render(payload, enriched, { messageContext, invokeTool });
26777
+ const element = widget.render(payload, enriched, {
26778
+ messageContext,
26779
+ invokeTool,
26780
+ canSendMessage,
26781
+ sendMessage,
26782
+ sendStructuredMessage
26783
+ });
26729
26784
  return /* @__PURE__ */ jsx15(Fragment4, { children: element });
26730
26785
  } catch (error48) {
26731
26786
  console.error(`SDK widget "${widget.widgetType}" render threw:`, error48);
@@ -26763,7 +26818,10 @@ function MessageRenderer({
26763
26818
  tagExpansion,
26764
26819
  className,
26765
26820
  feedback,
26766
- invokeTool
26821
+ invokeTool,
26822
+ canSendMessage,
26823
+ sendMessage,
26824
+ sendStructuredMessage
26767
26825
  }) {
26768
26826
  const messageContext = useMemo4(() => {
26769
26827
  if (!feedback) return void 0;
@@ -26777,7 +26835,7 @@ function MessageRenderer({
26777
26835
  () => feedback?.getFeedback() ?? null,
26778
26836
  [feedback]
26779
26837
  );
26780
- const renderPart = useCallback5(
26838
+ const renderPart = useCallback6(
26781
26839
  (part, key) => {
26782
26840
  if (part == null) {
26783
26841
  return null;
@@ -26822,7 +26880,10 @@ function MessageRenderer({
26822
26880
  payload: widget.payload,
26823
26881
  enriched: widget.enriched ?? {},
26824
26882
  messageContext: messageContext ?? void 0,
26825
- invokeTool
26883
+ invokeTool,
26884
+ canSendMessage,
26885
+ sendMessage,
26886
+ sendStructuredMessage
26826
26887
  }
26827
26888
  )
26828
26889
  },
@@ -26832,9 +26893,9 @@ function MessageRenderer({
26832
26893
  }
26833
26894
  return null;
26834
26895
  },
26835
- [widgets, readonly2, messageContext]
26896
+ [widgets, readonly2, messageContext, invokeTool, canSendMessage, sendMessage, sendStructuredMessage]
26836
26897
  );
26837
- const renderGroup = useCallback5(
26898
+ const renderGroup = useCallback6(
26838
26899
  (groupName, key, children) => {
26839
26900
  const isExpanded = tagExpansion?.state.get(key) ?? true;
26840
26901
  return /* @__PURE__ */ jsx16(
@@ -27084,11 +27145,14 @@ var ChatWidget = forwardRef(function ChatWidget2({
27084
27145
  const isAtBottomRef = useRef5(true);
27085
27146
  const textareaRef = useRef5(null);
27086
27147
  const suppressScrollRef = useRef5(false);
27148
+ const hasScrolledInitialHistoryRef = useRef5(false);
27087
27149
  const {
27088
27150
  messages,
27089
27151
  status,
27090
27152
  isLoadingInitial,
27153
+ canSendMessage,
27091
27154
  sendMessage,
27155
+ sendStructuredMessage,
27092
27156
  stop,
27093
27157
  setMessages,
27094
27158
  addToolOutput,
@@ -27107,7 +27171,7 @@ var ChatWidget = forwardRef(function ChatWidget2({
27107
27171
  onFinish,
27108
27172
  onMessage
27109
27173
  });
27110
- const handleToolOutput = useCallback6((result) => {
27174
+ const handleToolOutput = useCallback7((result) => {
27111
27175
  if (pendingToolOutput && addToolOutput) {
27112
27176
  addToolOutput({
27113
27177
  tool: "collect_user_input",
@@ -27116,7 +27180,7 @@ var ChatWidget = forwardRef(function ChatWidget2({
27116
27180
  });
27117
27181
  }
27118
27182
  }, [pendingToolOutput, addToolOutput]);
27119
- const handleToolApproval = useCallback6((approved, reason) => {
27183
+ const handleToolApproval = useCallback7((approved, reason) => {
27120
27184
  if (!pendingToolApproval) return;
27121
27185
  addToolApprovalResponse({
27122
27186
  id: pendingToolApproval.approvalId,
@@ -27124,14 +27188,19 @@ var ChatWidget = forwardRef(function ChatWidget2({
27124
27188
  reason
27125
27189
  });
27126
27190
  }, [pendingToolApproval, addToolApprovalResponse]);
27127
- const isInputDisabled = status !== "ready" || !!pendingToolOutput || !!pendingToolApproval;
27191
+ const isInputDisabled = !canSendMessage;
27128
27192
  useImperativeHandle(ref, () => ({
27129
27193
  sendMessage: (message) => {
27130
27194
  if (message.trim() && status === "ready") {
27131
27195
  sendMessage({ text: message });
27132
27196
  }
27197
+ },
27198
+ sendStructuredMessage: (message, payload) => {
27199
+ if (message.trim() && status === "ready") {
27200
+ void sendStructuredMessage(message, payload);
27201
+ }
27133
27202
  }
27134
- }), [sendMessage, status]);
27203
+ }), [sendMessage, sendStructuredMessage, status]);
27135
27204
  const feedbackEnabled = feedback?.enabled !== false;
27136
27205
  const {
27137
27206
  submitFeedback,
@@ -27173,7 +27242,7 @@ var ChatWidget = forwardRef(function ChatWidget2({
27173
27242
  setApprovalConfigLoading(false);
27174
27243
  });
27175
27244
  }, [pendingToolApproval, api, agentId, agentVersion, onAuthError]);
27176
- const handleTagToggle = useCallback6((messageId, tagId, currentlyExpanded) => {
27245
+ const handleTagToggle = useCallback7((messageId, tagId, currentlyExpanded) => {
27177
27246
  suppressScrollRef.current = true;
27178
27247
  setTagExpansionState((prev) => {
27179
27248
  const next = new Map(prev);
@@ -27222,12 +27291,31 @@ var ChatWidget = forwardRef(function ChatWidget2({
27222
27291
  sendMessage({ text: initialUserMessage });
27223
27292
  }
27224
27293
  }, [initialUserMessage, isLoadingInitial, status, messages.length, sendMessage]);
27225
- const handleScroll = useCallback6(() => {
27294
+ const handleScroll = useCallback7(() => {
27226
27295
  if (!scrollContainerRef.current) return;
27227
27296
  const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current;
27228
27297
  const distanceToBottom = scrollHeight - scrollTop - clientHeight;
27229
27298
  isAtBottomRef.current = distanceToBottom < 100;
27230
27299
  }, []);
27300
+ const scrollToBottom = useCallback7((behavior = "smooth") => {
27301
+ if (!scrollContainerRef.current) return;
27302
+ scrollContainerRef.current.scrollTo({
27303
+ top: scrollContainerRef.current.scrollHeight,
27304
+ behavior
27305
+ });
27306
+ isAtBottomRef.current = true;
27307
+ }, []);
27308
+ useEffect6(() => {
27309
+ if (isLoadingInitial || hasScrolledInitialHistoryRef.current) return;
27310
+ hasScrolledInitialHistoryRef.current = true;
27311
+ scrollToBottom("auto");
27312
+ const frameId = requestAnimationFrame(() => scrollToBottom("auto"));
27313
+ const timeoutId = window.setTimeout(() => scrollToBottom("auto"), 100);
27314
+ return () => {
27315
+ cancelAnimationFrame(frameId);
27316
+ window.clearTimeout(timeoutId);
27317
+ };
27318
+ }, [isLoadingInitial, scrollToBottom]);
27231
27319
  useEffect6(() => {
27232
27320
  if (suppressScrollRef.current) {
27233
27321
  suppressScrollRef.current = false;
@@ -27236,9 +27324,9 @@ var ChatWidget = forwardRef(function ChatWidget2({
27236
27324
  const lastMessage = messages[messages.length - 1];
27237
27325
  const isUserMessage = lastMessage?.role === "user";
27238
27326
  if (isAtBottomRef.current || isUserMessage) {
27239
- messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
27327
+ scrollToBottom("smooth");
27240
27328
  }
27241
- }, [messages, status]);
27329
+ }, [messages, status, scrollToBottom]);
27242
27330
  useEffect6(() => {
27243
27331
  const timer = setTimeout(() => {
27244
27332
  textareaRef.current?.focus();
@@ -27253,7 +27341,7 @@ var ChatWidget = forwardRef(function ChatWidget2({
27253
27341
  setIsSpeechPending(false);
27254
27342
  }
27255
27343
  }, [status]);
27256
- const sendText = useCallback6((raw) => {
27344
+ const sendText = useCallback7((raw) => {
27257
27345
  const text4 = (raw ?? input).trim();
27258
27346
  if (!text4 || isInputDisabled) return false;
27259
27347
  sendMessage({ text: text4 });
@@ -27274,10 +27362,10 @@ var ChatWidget = forwardRef(function ChatWidget2({
27274
27362
  }
27275
27363
  };
27276
27364
  const speechEnabled = speechToText?.enabled !== false;
27277
- const handleSpeechInterim = useCallback6((text4) => {
27365
+ const handleSpeechInterim = useCallback7((text4) => {
27278
27366
  setInput(text4);
27279
27367
  }, [setInput]);
27280
- const handleSpeechFinal = useCallback6((text4) => {
27368
+ const handleSpeechFinal = useCallback7((text4) => {
27281
27369
  const finalText = text4?.trim();
27282
27370
  if (!finalText || isSpeechPending) return;
27283
27371
  setInput(finalText);
@@ -27354,7 +27442,18 @@ var ChatWidget = forwardRef(function ChatWidget2({
27354
27442
  getFeedback: () => getFeedback(message.id),
27355
27443
  submitFeedback: (params) => submitFeedback(message.id, params)
27356
27444
  } : void 0,
27357
- invokeTool
27445
+ invokeTool,
27446
+ canSendMessage,
27447
+ sendMessage: (text4) => {
27448
+ if (canSendMessage) {
27449
+ sendMessage({ text: text4 });
27450
+ }
27451
+ },
27452
+ sendStructuredMessage: (text4, payload) => {
27453
+ if (canSendMessage) {
27454
+ void sendStructuredMessage(text4, payload);
27455
+ }
27456
+ }
27358
27457
  }
27359
27458
  )
27360
27459
  }