@ensembleapp/client-sdk 0.0.38 → 0.0.40

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,77 @@ 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-background: #ffffff;\n --chat-border: #e5e7eb;\n --chat-header-text: #ffffff;\n --chat-user-text: #ffffff;\n --chat-assistant-bg: transparent;\n --chat-assistant-text: #111827;\n --chat-font-family:\n "Inter",\n system-ui,\n -apple-system,\n BlinkMacSystemFont,\n sans-serif;\n --chat-radius: 0.75rem;\n --chat-input-bg: #ffffff;\n --chat-input-text: #111827;\n --chat-input-placeholder: #6b7280;\n --chat-thought-border: #d1d5db;\n --chat-font-size: 0.925rem;\n --chat-thought-font-size: 0.75rem;\n}\n.chat-widget {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n min-height: 24rem;\n background: var(--chat-background);\n border: 1px solid var(--chat-border);\n border-radius: var(--chat-radius);\n box-shadow: 0 20px 45px rgba(15, 23, 42, 0.12);\n overflow: hidden;\n font-family: var(--chat-font-family);\n color: var(--chat-assistant-text);\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}\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: 0 10px 25px rgba(15, 23, 42, 0.2);\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: 0 20px 45px rgba(15, 23, 42, 0.12);\n border-radius: 12px;\n overflow: hidden;\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: #6b7280;\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 #d1d5db;\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: #4b5563;\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: #9ca3af;\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: #9ca3af;\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: #9ca3af;\n cursor: not-allowed;\n}\n.chat-widget__mic-button--active {\n color: var(--chat-primary-hover);\n background: rgba(59, 130, 246, 0.08);\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: rgba(148, 163, 184, 0.4);\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: #9ca3af;\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-text: #111827;\n --chat-text-secondary: #4b5563;\n --chat-text-muted: #6b7280;\n --chat-text-disabled: #9ca3af;\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: 1px solid var(--chat-border);\n border-radius: var(--chat-radius);\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__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}\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-primary);\n text-decoration: underline;\n}\n.chat-widget__markdown a:hover {\n color: var(--chat-primary-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 useState7 } from "react";
34
+ import { forwardRef, useCallback as useCallback6, useEffect as useEffect6, useImperativeHandle, useMemo as useMemo5, useRef as useRef5, useState as useState9 } from "react";
35
+
36
+ // lib/api/fetchApprovalConfig.ts
37
+ async function fetchApprovalConfig(options) {
38
+ const { api, agentId, agentVersion, toolName, args = {}, onAuthError } = options;
39
+ const { baseUrl, headers: customHeaders = {} } = api;
40
+ const doFetch = (token) => fetch(`${baseUrl}/chat/tools/${encodeURIComponent(toolName)}/approval-config`, {
41
+ method: "POST",
42
+ headers: {
43
+ "Content-Type": "application/json",
44
+ Authorization: `Bearer ${token}`,
45
+ "agent-id": agentId,
46
+ ...agentVersion !== void 0 ? { version: String(agentVersion) } : {},
47
+ ...customHeaders
48
+ },
49
+ body: JSON.stringify({ args })
50
+ });
51
+ let response = await doFetch(api.token);
52
+ if (response.status === 401 && onAuthError) {
53
+ const newToken = await onAuthError();
54
+ if (newToken) {
55
+ response = await doFetch(newToken);
56
+ }
57
+ }
58
+ if (!response.ok) {
59
+ console.error(
60
+ `[fetchApprovalConfig] Failed to fetch approval config for ${toolName}:`,
61
+ response.status
62
+ );
63
+ return null;
64
+ }
65
+ return response.json();
66
+ }
67
+
68
+ // lib/api/invokeTool.ts
69
+ function createInvokeTool(api, onAuthError) {
70
+ return async (toolId, request = {}) => {
71
+ const { baseUrl, headers: customHeaders = {} } = api;
72
+ const doFetch = (token) => fetch(`${baseUrl}/api/tools/${toolId}/invoke`, {
73
+ method: "POST",
74
+ headers: {
75
+ "Content-Type": "application/json",
76
+ Authorization: `Bearer ${token}`,
77
+ ...customHeaders
78
+ },
79
+ body: JSON.stringify(request)
80
+ });
81
+ let response = await doFetch(api.token);
82
+ if (response.status === 401 && onAuthError) {
83
+ const newToken = await onAuthError();
84
+ if (newToken) {
85
+ response = await doFetch(newToken);
86
+ }
87
+ }
88
+ if (!response.ok) {
89
+ return {
90
+ success: false,
91
+ error: {
92
+ message: `HTTP ${response.status}`,
93
+ details: [await response.text().catch(() => response.statusText)],
94
+ code: "HTTP_ERROR"
95
+ }
96
+ };
97
+ }
98
+ return response.json();
99
+ };
100
+ }
35
101
 
36
102
  // ../../node_modules/.pnpm/@ai-sdk+provider@3.0.8/node_modules/@ai-sdk/provider/dist/index.mjs
37
103
  var marker = "vercel.ai.error";
@@ -20998,6 +21064,15 @@ var uiMessageChunkSchema = lazySchema(
20998
21064
  ])
20999
21065
  )
21000
21066
  );
21067
+ function isStaticToolUIPart(part) {
21068
+ return part.type.startsWith("tool-");
21069
+ }
21070
+ function isDynamicToolUIPart(part) {
21071
+ return part.type === "dynamic-tool";
21072
+ }
21073
+ function isToolUIPart(part) {
21074
+ return isStaticToolUIPart(part) || isDynamicToolUIPart(part);
21075
+ }
21001
21076
  var originalGenerateId2 = createIdGenerator({
21002
21077
  prefix: "aitxt",
21003
21078
  size: 24
@@ -21417,6 +21492,46 @@ var DefaultChatTransport = class extends HttpChatTransport {
21417
21492
  );
21418
21493
  }
21419
21494
  };
21495
+ function lastAssistantMessageIsCompleteWithApprovalResponses({
21496
+ messages
21497
+ }) {
21498
+ const message = messages[messages.length - 1];
21499
+ if (!message) {
21500
+ return false;
21501
+ }
21502
+ if (message.role !== "assistant") {
21503
+ return false;
21504
+ }
21505
+ const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => {
21506
+ return part.type === "step-start" ? index : lastIndex;
21507
+ }, -1);
21508
+ const lastStepToolInvocations = message.parts.slice(lastStepStartIndex + 1).filter(isToolUIPart).filter((part) => !part.providerExecuted);
21509
+ return (
21510
+ // has at least one tool approval response
21511
+ lastStepToolInvocations.filter((part) => part.state === "approval-responded").length > 0 && // all tool approvals must have a response
21512
+ lastStepToolInvocations.every(
21513
+ (part) => part.state === "output-available" || part.state === "output-error" || part.state === "approval-responded"
21514
+ )
21515
+ );
21516
+ }
21517
+ function lastAssistantMessageIsCompleteWithToolCalls({
21518
+ messages
21519
+ }) {
21520
+ const message = messages[messages.length - 1];
21521
+ if (!message) {
21522
+ return false;
21523
+ }
21524
+ if (message.role !== "assistant") {
21525
+ return false;
21526
+ }
21527
+ const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => {
21528
+ return part.type === "step-start" ? index : lastIndex;
21529
+ }, -1);
21530
+ const lastStepToolInvocations = message.parts.slice(lastStepStartIndex + 1).filter(isToolUIPart).filter((part) => !part.providerExecuted);
21531
+ return lastStepToolInvocations.length > 0 && lastStepToolInvocations.every(
21532
+ (part) => part.state === "output-available" || part.state === "output-error"
21533
+ );
21534
+ }
21420
21535
 
21421
21536
  // lib/hooks/useChat.ts
21422
21537
  import { useEffect, useMemo, useRef, useState } from "react";
@@ -21486,6 +21601,7 @@ function transformMessage(msg) {
21486
21601
  }
21487
21602
 
21488
21603
  // lib/hooks/useChat.ts
21604
+ var COLLECT_USER_INPUT_TOOL = "collect_user_input";
21489
21605
  function createAuthAwareFetch(tokenRef, onAuthError) {
21490
21606
  return async (input, init) => {
21491
21607
  const doFetch = (token) => fetch(input, {
@@ -21557,10 +21673,16 @@ function useChat({
21557
21673
  status,
21558
21674
  sendMessage,
21559
21675
  stop,
21560
- setMessages
21676
+ setMessages,
21677
+ addToolOutput,
21678
+ addToolApprovalResponse
21561
21679
  } = useAIChat({
21562
21680
  id: threadId,
21563
21681
  transport,
21682
+ // Automatically resubmit when:
21683
+ // 1. Tool result is populated (collect_user_input use case)
21684
+ // 2. Tool approval responses are complete (human-in-the-loop approval)
21685
+ sendAutomaticallyWhen: ({ messages: messages2 }) => lastAssistantMessageIsCompleteWithToolCalls({ messages: messages2 }) || lastAssistantMessageIsCompleteWithApprovalResponses({ messages: messages2 }),
21564
21686
  onError: (error48) => {
21565
21687
  console.error("Chat error:", error48);
21566
21688
  onError?.(error48);
@@ -21609,13 +21731,56 @@ function useChat({
21609
21731
  const rtnMessages = useMemo(() => {
21610
21732
  return messages.map((msg) => transformMessage(msg));
21611
21733
  }, [messages]);
21734
+ const pendingToolOutput = useMemo(() => {
21735
+ const lastMessage = messages[messages.length - 1];
21736
+ if (!lastMessage || lastMessage.role !== "assistant") return null;
21737
+ for (const part of lastMessage.parts ?? []) {
21738
+ const isToolPart = part.type.startsWith("tool-") || part.type === "dynamic-tool";
21739
+ if (!isToolPart) continue;
21740
+ const toolName = "toolName" in part ? part.toolName : part.type.replace("tool-", "");
21741
+ if (toolName !== COLLECT_USER_INPUT_TOOL) continue;
21742
+ const state = "state" in part ? part.state : void 0;
21743
+ if (state === "input-available") {
21744
+ return {
21745
+ toolCallId: part.toolCallId,
21746
+ args: part.input
21747
+ };
21748
+ }
21749
+ }
21750
+ return null;
21751
+ }, [messages]);
21752
+ const pendingToolApproval = useMemo(() => {
21753
+ const lastMessage = messages[messages.length - 1];
21754
+ if (!lastMessage || lastMessage.role !== "assistant") return null;
21755
+ for (const part of lastMessage.parts ?? []) {
21756
+ const isToolPart = part.type.startsWith("tool-") || part.type === "dynamic-tool";
21757
+ if (!isToolPart) continue;
21758
+ const state = "state" in part ? part.state : void 0;
21759
+ if (state === "approval-requested") {
21760
+ const toolName = "toolName" in part ? part.toolName : part.type.replace("tool-", "");
21761
+ const approval = "approval" in part ? part.approval : null;
21762
+ if (!approval?.id) continue;
21763
+ return {
21764
+ toolCallId: part.toolCallId,
21765
+ toolName,
21766
+ args: part.input ?? {},
21767
+ approvalId: approval.id
21768
+ };
21769
+ }
21770
+ }
21771
+ return null;
21772
+ }, [messages]);
21612
21773
  return {
21613
21774
  messages: rtnMessages,
21614
21775
  status,
21615
21776
  isLoadingInitial,
21616
21777
  sendMessage,
21617
21778
  stop,
21618
- setMessages
21779
+ setMessages,
21780
+ addToolOutput,
21781
+ addToolApprovalResponse,
21782
+ pendingToolOutput,
21783
+ pendingToolApproval
21619
21784
  };
21620
21785
  }
21621
21786
 
@@ -21715,15 +21880,376 @@ function cn(...inputs) {
21715
21880
  return twMerge(clsx(inputs));
21716
21881
  }
21717
21882
 
21883
+ // 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');
21885
+
21886
+ // lib/chat/components/InputFormOverlay.tsx
21887
+ import { useState as useState3 } from "react";
21888
+
21889
+ // lib/chat/components/input-fields/CheckboxField.tsx
21890
+ import { jsx, jsxs } from "react/jsx-runtime";
21891
+ function CheckboxField({ field, value, onChange }) {
21892
+ const { name: name21, label } = field;
21893
+ return /* @__PURE__ */ jsx("div", { className: "input-field input-field--checkbox", children: /* @__PURE__ */ jsxs("label", { className: "input-field__checkbox-wrapper", children: [
21894
+ /* @__PURE__ */ jsx(
21895
+ "input",
21896
+ {
21897
+ type: "checkbox",
21898
+ name: name21,
21899
+ checked: value ?? false,
21900
+ onChange: (e) => onChange(e.target.checked),
21901
+ className: "input-field__checkbox"
21902
+ }
21903
+ ),
21904
+ /* @__PURE__ */ jsx("span", { className: "input-field__checkbox-label", children: label })
21905
+ ] }) });
21906
+ }
21907
+
21908
+ // lib/chat/components/input-fields/ChoicesField.tsx
21909
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
21910
+ function ChoicesField({ field, value, onChange }) {
21911
+ const { name: name21, label, options, multiSelect, required: required2 } = field;
21912
+ if (multiSelect) {
21913
+ const selectedValues = Array.isArray(value) ? value : value ? [value] : [];
21914
+ const handleCheckboxChange = (optionValue, checked) => {
21915
+ if (checked) {
21916
+ onChange([...selectedValues, optionValue]);
21917
+ } else {
21918
+ onChange(selectedValues.filter((v) => v !== optionValue));
21919
+ }
21920
+ };
21921
+ return /* @__PURE__ */ jsxs2("div", { className: "input-field input-field--choices", children: [
21922
+ /* @__PURE__ */ jsxs2("label", { className: "input-field__label", children: [
21923
+ label,
21924
+ required2 && /* @__PURE__ */ jsx2("span", { className: "input-field__required", children: "*" })
21925
+ ] }),
21926
+ /* @__PURE__ */ jsx2("div", { className: "input-field__options input-field__options--checkbox", children: options.map((option) => /* @__PURE__ */ jsxs2("label", { className: "input-field__option", children: [
21927
+ /* @__PURE__ */ jsx2(
21928
+ "input",
21929
+ {
21930
+ type: "checkbox",
21931
+ name: name21,
21932
+ value: option.value,
21933
+ checked: selectedValues.includes(option.value),
21934
+ onChange: (e) => handleCheckboxChange(option.value, e.target.checked),
21935
+ className: "input-field__checkbox"
21936
+ }
21937
+ ),
21938
+ /* @__PURE__ */ jsxs2("span", { className: "input-field__option-content", children: [
21939
+ /* @__PURE__ */ jsx2("span", { className: "input-field__option-label", children: option.label }),
21940
+ option.description && /* @__PURE__ */ jsx2("span", { className: "input-field__option-description", children: option.description })
21941
+ ] })
21942
+ ] }, option.value)) })
21943
+ ] });
21944
+ }
21945
+ const selectedValue = Array.isArray(value) ? value[0] : value;
21946
+ return /* @__PURE__ */ jsxs2("div", { className: "input-field input-field--choices", children: [
21947
+ /* @__PURE__ */ jsxs2("label", { className: "input-field__label", children: [
21948
+ label,
21949
+ required2 && /* @__PURE__ */ jsx2("span", { className: "input-field__required", children: "*" })
21950
+ ] }),
21951
+ /* @__PURE__ */ jsx2("div", { className: "input-field__options input-field__options--radio", children: options.map((option) => /* @__PURE__ */ jsxs2("label", { className: "input-field__option", children: [
21952
+ /* @__PURE__ */ jsx2(
21953
+ "input",
21954
+ {
21955
+ type: "radio",
21956
+ name: name21,
21957
+ value: option.value,
21958
+ checked: selectedValue === option.value,
21959
+ onChange: () => onChange(option.value),
21960
+ className: "input-field__radio"
21961
+ }
21962
+ ),
21963
+ /* @__PURE__ */ jsxs2("span", { className: "input-field__option-content", children: [
21964
+ /* @__PURE__ */ jsx2("span", { className: "input-field__option-label", children: option.label }),
21965
+ option.description && /* @__PURE__ */ jsx2("span", { className: "input-field__option-description", children: option.description })
21966
+ ] })
21967
+ ] }, option.value)) })
21968
+ ] });
21969
+ }
21970
+
21971
+ // lib/chat/components/input-fields/DateField.tsx
21972
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
21973
+ function DateField({ field, value, onChange }) {
21974
+ const { label, required: required2 } = field;
21975
+ return /* @__PURE__ */ jsxs3("div", { className: "input-field input-field--date", children: [
21976
+ /* @__PURE__ */ jsxs3("label", { className: "input-field__label", children: [
21977
+ label,
21978
+ required2 && /* @__PURE__ */ jsx3("span", { className: "input-field__required", children: "*" })
21979
+ ] }),
21980
+ /* @__PURE__ */ jsx3(
21981
+ "input",
21982
+ {
21983
+ type: "date",
21984
+ value: value ?? "",
21985
+ onChange: (e) => onChange(e.target.value),
21986
+ className: "input-field__input"
21987
+ }
21988
+ )
21989
+ ] });
21990
+ }
21991
+
21992
+ // lib/chat/components/input-fields/NumberField.tsx
21993
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
21994
+ function NumberField({ field, value, onChange }) {
21995
+ const { label, min, max, required: required2 } = field;
21996
+ const handleChange = (e) => {
21997
+ const val = e.target.value;
21998
+ if (val === "") {
21999
+ onChange(void 0);
22000
+ } else {
22001
+ const num = parseFloat(val);
22002
+ if (!isNaN(num)) {
22003
+ onChange(num);
22004
+ }
22005
+ }
22006
+ };
22007
+ return /* @__PURE__ */ jsxs4("div", { className: "input-field input-field--number", children: [
22008
+ /* @__PURE__ */ jsxs4("label", { className: "input-field__label", children: [
22009
+ label,
22010
+ required2 && /* @__PURE__ */ jsx4("span", { className: "input-field__required", children: "*" })
22011
+ ] }),
22012
+ /* @__PURE__ */ jsx4(
22013
+ "input",
22014
+ {
22015
+ type: "number",
22016
+ value: value ?? "",
22017
+ onChange: handleChange,
22018
+ min,
22019
+ max,
22020
+ className: "input-field__input"
22021
+ }
22022
+ )
22023
+ ] });
22024
+ }
22025
+
22026
+ // lib/chat/components/input-fields/TextField.tsx
22027
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
22028
+ function TextField({ field, value, onChange }) {
22029
+ const { label, placeholder, multiline, required: required2 } = field;
22030
+ if (multiline) {
22031
+ return /* @__PURE__ */ jsxs5("div", { className: "input-field input-field--text", children: [
22032
+ /* @__PURE__ */ jsxs5("label", { className: "input-field__label", children: [
22033
+ label,
22034
+ required2 && /* @__PURE__ */ jsx5("span", { className: "input-field__required", children: "*" })
22035
+ ] }),
22036
+ /* @__PURE__ */ jsx5(
22037
+ "textarea",
22038
+ {
22039
+ value: value ?? "",
22040
+ onChange: (e) => onChange(e.target.value),
22041
+ placeholder,
22042
+ className: "input-field__textarea",
22043
+ rows: 4
22044
+ }
22045
+ )
22046
+ ] });
22047
+ }
22048
+ return /* @__PURE__ */ jsxs5("div", { className: "input-field input-field--text", children: [
22049
+ /* @__PURE__ */ jsxs5("label", { className: "input-field__label", children: [
22050
+ label,
22051
+ required2 && /* @__PURE__ */ jsx5("span", { className: "input-field__required", children: "*" })
22052
+ ] }),
22053
+ /* @__PURE__ */ jsx5(
22054
+ "input",
22055
+ {
22056
+ type: "text",
22057
+ value: value ?? "",
22058
+ onChange: (e) => onChange(e.target.value),
22059
+ placeholder,
22060
+ className: "input-field__input"
22061
+ }
22062
+ )
22063
+ ] });
22064
+ }
22065
+
22066
+ // lib/chat/components/input-fields/FieldRenderer.tsx
22067
+ import { jsx as jsx6 } from "react/jsx-runtime";
22068
+ function FieldRenderer({ field, value, onChange }) {
22069
+ switch (field.type) {
22070
+ case "choices":
22071
+ return /* @__PURE__ */ jsx6(
22072
+ ChoicesField,
22073
+ {
22074
+ field,
22075
+ value,
22076
+ onChange
22077
+ }
22078
+ );
22079
+ case "text":
22080
+ return /* @__PURE__ */ jsx6(
22081
+ TextField,
22082
+ {
22083
+ field,
22084
+ value,
22085
+ onChange
22086
+ }
22087
+ );
22088
+ case "number":
22089
+ return /* @__PURE__ */ jsx6(
22090
+ NumberField,
22091
+ {
22092
+ field,
22093
+ value,
22094
+ onChange
22095
+ }
22096
+ );
22097
+ case "checkbox":
22098
+ return /* @__PURE__ */ jsx6(
22099
+ CheckboxField,
22100
+ {
22101
+ field,
22102
+ value,
22103
+ onChange
22104
+ }
22105
+ );
22106
+ case "date":
22107
+ return /* @__PURE__ */ jsx6(
22108
+ DateField,
22109
+ {
22110
+ field,
22111
+ value,
22112
+ onChange
22113
+ }
22114
+ );
22115
+ default:
22116
+ const _exhaustive = field;
22117
+ return null;
22118
+ }
22119
+ }
22120
+
22121
+ // lib/chat/components/InputFormOverlay.tsx
22122
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
22123
+ function InputFormOverlay({ args, onComplete }) {
22124
+ const {
22125
+ title,
22126
+ description,
22127
+ fields,
22128
+ submitLabel = "Submit",
22129
+ cancelLabel = "Cancel",
22130
+ allowFreeformResponse = true
22131
+ } = args;
22132
+ const [values, setValues] = useState3(() => {
22133
+ const initial = {};
22134
+ for (const field of fields) {
22135
+ if (field.defaultValue !== void 0) {
22136
+ initial[field.name] = field.defaultValue;
22137
+ }
22138
+ }
22139
+ return initial;
22140
+ });
22141
+ const [freeformText, setFreeformText] = useState3("");
22142
+ const [showFreeform, setShowFreeform] = useState3(false);
22143
+ const handleFieldChange = (name21, value) => {
22144
+ setValues((prev) => ({ ...prev, [name21]: value }));
22145
+ };
22146
+ const handleSubmit = (e) => {
22147
+ e.preventDefault();
22148
+ onComplete({ values });
22149
+ };
22150
+ const handleCancel = () => {
22151
+ onComplete({ cancelled: true });
22152
+ };
22153
+ const handleFreeformSubmit = () => {
22154
+ if (freeformText.trim()) {
22155
+ onComplete({ freeformResponse: freeformText.trim() });
22156
+ }
22157
+ };
22158
+ const isFormValid = fields.every((field) => {
22159
+ if (!("required" in field) || !field.required) return true;
22160
+ const value = values[field.name];
22161
+ if (value === void 0 || value === null || value === "") return false;
22162
+ if (Array.isArray(value) && value.length === 0) return false;
22163
+ return true;
22164
+ });
22165
+ return /* @__PURE__ */ jsx7("div", { className: "input-form-overlay", children: /* @__PURE__ */ jsx7("div", { className: "input-form-overlay__content", children: !showFreeform ? /* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, className: "input-form-overlay__form", children: [
22166
+ /* @__PURE__ */ jsxs6("div", { className: "input-form-overlay__scrollable", children: [
22167
+ title && /* @__PURE__ */ jsx7("h3", { className: "input-form-overlay__title", children: title }),
22168
+ description && /* @__PURE__ */ jsx7("p", { className: "input-form-overlay__description", children: description }),
22169
+ /* @__PURE__ */ jsx7("div", { className: "input-form-overlay__fields", children: fields.map((field) => /* @__PURE__ */ jsx7(
22170
+ FieldRenderer,
22171
+ {
22172
+ field,
22173
+ value: values[field.name],
22174
+ onChange: (v) => handleFieldChange(field.name, v)
22175
+ },
22176
+ field.name
22177
+ )) })
22178
+ ] }),
22179
+ /* @__PURE__ */ jsx7("div", { className: "input-form-overlay__footer", children: /* @__PURE__ */ jsxs6("div", { className: "input-form-overlay__actions", children: [
22180
+ /* @__PURE__ */ jsx7(
22181
+ "button",
22182
+ {
22183
+ type: "submit",
22184
+ disabled: !isFormValid,
22185
+ className: "input-form-overlay__button input-form-overlay__button--primary",
22186
+ children: submitLabel
22187
+ }
22188
+ ),
22189
+ /* @__PURE__ */ jsx7(
22190
+ "button",
22191
+ {
22192
+ type: "button",
22193
+ onClick: handleCancel,
22194
+ className: "input-form-overlay__button input-form-overlay__button--secondary",
22195
+ children: cancelLabel
22196
+ }
22197
+ ),
22198
+ allowFreeformResponse && /* @__PURE__ */ jsx7(
22199
+ "button",
22200
+ {
22201
+ type: "button",
22202
+ className: "input-form-overlay__freeform-toggle",
22203
+ onClick: () => setShowFreeform(true),
22204
+ children: "Or type a response instead..."
22205
+ }
22206
+ )
22207
+ ] }) })
22208
+ ] }) : /* @__PURE__ */ jsxs6("div", { className: "input-form-overlay__freeform", children: [
22209
+ /* @__PURE__ */ jsx7("div", { className: "input-form-overlay__freeform-body", children: /* @__PURE__ */ jsx7(
22210
+ "textarea",
22211
+ {
22212
+ value: freeformText,
22213
+ onChange: (e) => setFreeformText(e.target.value),
22214
+ placeholder: "Type your response...",
22215
+ className: "input-form-overlay__freeform-input",
22216
+ autoFocus: true,
22217
+ rows: 4
22218
+ }
22219
+ ) }),
22220
+ /* @__PURE__ */ jsx7("div", { className: "input-form-overlay__footer", children: /* @__PURE__ */ jsxs6("div", { className: "input-form-overlay__actions", children: [
22221
+ /* @__PURE__ */ jsx7(
22222
+ "button",
22223
+ {
22224
+ type: "button",
22225
+ onClick: handleFreeformSubmit,
22226
+ disabled: !freeformText.trim(),
22227
+ className: "input-form-overlay__button input-form-overlay__button--primary",
22228
+ children: "Send"
22229
+ }
22230
+ ),
22231
+ /* @__PURE__ */ jsx7(
22232
+ "button",
22233
+ {
22234
+ type: "button",
22235
+ onClick: () => setShowFreeform(false),
22236
+ className: "input-form-overlay__button input-form-overlay__button--secondary",
22237
+ children: "Back to form"
22238
+ }
22239
+ )
22240
+ ] }) })
22241
+ ] }) }) });
22242
+ }
22243
+
21718
22244
  // lib/chat/components/SpeechToTextButton.tsx
21719
22245
  import { Mic, MicOff } from "lucide-react";
21720
22246
  import {
21721
22247
  useCallback as useCallback2,
21722
22248
  useEffect as useEffect2,
21723
22249
  useRef as useRef2,
21724
- useState as useState3
22250
+ useState as useState4
21725
22251
  } from "react";
21726
- import { jsx, jsxs } from "react/jsx-runtime";
22252
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
21727
22253
  var getSpeechRecognitionCtor = () => {
21728
22254
  if (typeof window === "undefined") return null;
21729
22255
  const win = window;
@@ -21742,11 +22268,11 @@ function SpeechToTextButton({
21742
22268
  disabled,
21743
22269
  className
21744
22270
  }) {
21745
- const [isListening, setIsListening] = useState3(false);
21746
- const [isSupported, setIsSupported] = useState3(false);
21747
- const [countdown, setCountdown] = useState3(0);
22271
+ const [isListening, setIsListening] = useState4(false);
22272
+ const [isSupported, setIsSupported] = useState4(false);
22273
+ const [countdown, setCountdown] = useState4(0);
21748
22274
  const recognitionRef = useRef2(null);
21749
- const [countdownActive, setCountdownActive] = useState3(false);
22275
+ const [countdownActive, setCountdownActive] = useState4(false);
21750
22276
  const silenceTimer = useRef2(null);
21751
22277
  const finalTimer = useRef2(null);
21752
22278
  const finalTextRef = useRef2("");
@@ -21956,7 +22482,7 @@ function SpeechToTextButton({
21956
22482
  if (!isSupported) {
21957
22483
  return null;
21958
22484
  }
21959
- return /* @__PURE__ */ jsxs(
22485
+ return /* @__PURE__ */ jsxs7(
21960
22486
  "button",
21961
22487
  {
21962
22488
  type: "button",
@@ -21970,8 +22496,8 @@ function SpeechToTextButton({
21970
22496
  "aria-pressed": isListening,
21971
22497
  "aria-label": "Toggle microphone",
21972
22498
  children: [
21973
- isListening ? /* @__PURE__ */ jsx(Mic, { className: "chat-widget__mic-icon" }) : /* @__PURE__ */ jsx(MicOff, { className: "chat-widget__mic-icon" }),
21974
- finalDelay > 0 && isListening && countdownActive && /* @__PURE__ */ jsx("span", { className: "chat-widget__mic-bar", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
22499
+ isListening ? /* @__PURE__ */ jsx8(Mic, { className: "chat-widget__mic-icon" }) : /* @__PURE__ */ jsx8(MicOff, { className: "chat-widget__mic-icon" }),
22500
+ finalDelay > 0 && isListening && countdownActive && /* @__PURE__ */ jsx8("span", { className: "chat-widget__mic-bar", "aria-hidden": "true", children: /* @__PURE__ */ jsx8(
21975
22501
  "span",
21976
22502
  {
21977
22503
  className: "chat-widget__mic-bar-fill",
@@ -21983,16 +22509,114 @@ function SpeechToTextButton({
21983
22509
  );
21984
22510
  }
21985
22511
 
22512
+ // lib/chat/components/ToolApprovalOverlay.css
22513
+ styleInject(".tool-approval-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 background-color: var(--chat-overlay-bg);\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.tool-approval-overlay__content {\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 transition: max-height 0.2s ease-out;\n}\n.tool-approval-overlay__content--loading {\n max-height: 160px;\n}\n.tool-approval-overlay__scrollable {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n padding: 1rem 1.25rem;\n}\n.tool-approval-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.tool-approval-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.tool-approval-overlay__tool-name {\n background-color: var(--chat-border);\n padding: 0.125rem 0.375rem;\n border-radius: 0.25rem;\n font-size: 0.8125rem;\n}\n.tool-approval-overlay__args {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n.tool-approval-overlay__arg {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n.tool-approval-overlay__arg-label {\n font-size: 0.6875rem;\n font-weight: 500;\n color: var(--chat-input-placeholder);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n.tool-approval-overlay__arg-value {\n font-size: 0.875rem;\n color: var(--chat-assistant-text);\n white-space: pre-wrap;\n word-break: break-word;\n}\n.tool-approval-overlay__no-args {\n font-size: 0.8125rem;\n color: var(--chat-input-placeholder);\n font-style: italic;\n}\n.tool-approval-overlay__footer {\n flex-shrink: 0;\n padding: 0.5rem 1.25rem;\n border-top: 1px solid var(--chat-border);\n}\n.tool-approval-overlay__actions {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n justify-content: flex-start;\n}\n.tool-approval-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.tool-approval-overlay__button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.tool-approval-overlay__button--primary {\n background-color: var(--chat-primary);\n color: var(--chat-primary-text);\n}\n.tool-approval-overlay__button--primary:hover:not(:disabled) {\n background-color: var(--chat-primary-hover);\n}\n.tool-approval-overlay__button--secondary {\n background-color: var(--chat-border);\n color: var(--chat-assistant-text);\n}\n.tool-approval-overlay__button--secondary:hover:not(:disabled) {\n opacity: 0.8;\n}\n.tool-approval-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.tool-approval-overlay__freeform-toggle:hover {\n color: var(--chat-primary);\n text-decoration: underline;\n}\n.tool-approval-overlay__freeform {\n display: flex;\n flex-direction: column;\n}\n.tool-approval-overlay__freeform-body {\n padding: 1rem 1.25rem;\n}\n.tool-approval-overlay__freeform-input {\n width: 100%;\n padding: 0.75rem;\n font-size: 0.875rem;\n font-family: var(--chat-font-family);\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: 80px;\n box-sizing: border-box;\n}\n.tool-approval-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.tool-approval-overlay__freeform-input::-moz-placeholder {\n color: var(--chat-input-placeholder);\n}\n.tool-approval-overlay__freeform-input::placeholder {\n color: var(--chat-input-placeholder);\n}\n.tool-approval-overlay__loading {\n display: flex;\n justify-content: center;\n align-items: center;\n height: 160px;\n}\n.tool-approval-overlay__loading-spinner {\n width: 24px;\n height: 24px;\n border: 2px solid var(--chat-border);\n border-top-color: var(--chat-primary);\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n}\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n");
22514
+
22515
+ // lib/chat/components/ToolApprovalOverlay.tsx
22516
+ import { useState as useState5 } from "react";
22517
+ import { Fragment, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
22518
+ function ToolApprovalOverlay({ approval, config: config2, configLoading, onApprove, onDeny }) {
22519
+ const { toolName, args } = approval;
22520
+ const [showFreeform, setShowFreeform] = useState5(false);
22521
+ const [freeformText, setFreeformText] = useState5("");
22522
+ const handleApprove = () => {
22523
+ onApprove();
22524
+ };
22525
+ const handleDeny = () => {
22526
+ onDeny();
22527
+ };
22528
+ const handleFreeformSubmit = () => {
22529
+ if (freeformText.trim()) {
22530
+ onDeny(freeformText.trim());
22531
+ }
22532
+ };
22533
+ const entries = Object.entries(args);
22534
+ const title = config2?.message || `Approve ${toolName} execution?`;
22535
+ const approveLabel = config2?.approveLabel || "Approve";
22536
+ const denyLabel = config2?.denyLabel || "Deny";
22537
+ return /* @__PURE__ */ jsx9("div", { className: "tool-approval-overlay", children: /* @__PURE__ */ jsx9("div", { className: `tool-approval-overlay__content ${configLoading ? "tool-approval-overlay__content--loading" : ""}`, children: configLoading ? /* @__PURE__ */ jsx9("div", { className: "tool-approval-overlay__loading", children: /* @__PURE__ */ jsx9("div", { className: "tool-approval-overlay__loading-spinner" }) }) : !showFreeform ? /* @__PURE__ */ jsxs8(Fragment, { children: [
22538
+ /* @__PURE__ */ jsxs8("div", { className: "tool-approval-overlay__scrollable", children: [
22539
+ /* @__PURE__ */ jsx9("h3", { className: "tool-approval-overlay__title", children: title }),
22540
+ entries.length > 0 ? /* @__PURE__ */ jsx9("div", { className: "tool-approval-overlay__args", children: entries.map(([key, value]) => /* @__PURE__ */ jsxs8("div", { className: "tool-approval-overlay__arg", children: [
22541
+ /* @__PURE__ */ jsx9("label", { className: "tool-approval-overlay__arg-label", children: key }),
22542
+ /* @__PURE__ */ jsx9("div", { className: "tool-approval-overlay__arg-value", children: typeof value === "string" ? value : JSON.stringify(value, null, 2) })
22543
+ ] }, key)) }) : /* @__PURE__ */ jsx9("p", { className: "tool-approval-overlay__no-args", children: "No inputs provided." })
22544
+ ] }),
22545
+ /* @__PURE__ */ jsx9("div", { className: "tool-approval-overlay__footer", children: /* @__PURE__ */ jsxs8("div", { className: "tool-approval-overlay__actions", children: [
22546
+ /* @__PURE__ */ jsx9(
22547
+ "button",
22548
+ {
22549
+ type: "button",
22550
+ onClick: handleApprove,
22551
+ className: "tool-approval-overlay__button tool-approval-overlay__button--primary",
22552
+ children: approveLabel
22553
+ }
22554
+ ),
22555
+ /* @__PURE__ */ jsx9(
22556
+ "button",
22557
+ {
22558
+ type: "button",
22559
+ onClick: handleDeny,
22560
+ className: "tool-approval-overlay__button tool-approval-overlay__button--secondary",
22561
+ children: denyLabel
22562
+ }
22563
+ ),
22564
+ /* @__PURE__ */ jsx9(
22565
+ "button",
22566
+ {
22567
+ type: "button",
22568
+ onClick: () => setShowFreeform(true),
22569
+ className: "tool-approval-overlay__freeform-toggle",
22570
+ children: "Or type a response instead..."
22571
+ }
22572
+ )
22573
+ ] }) })
22574
+ ] }) : /* @__PURE__ */ jsxs8("div", { className: "tool-approval-overlay__freeform", children: [
22575
+ /* @__PURE__ */ jsx9("div", { className: "tool-approval-overlay__freeform-body", children: /* @__PURE__ */ jsx9(
22576
+ "textarea",
22577
+ {
22578
+ value: freeformText,
22579
+ onChange: (e) => setFreeformText(e.target.value),
22580
+ placeholder: "Tell the assistant what's wrong or what you'd like instead...",
22581
+ className: "tool-approval-overlay__freeform-input",
22582
+ autoFocus: true,
22583
+ rows: 4
22584
+ }
22585
+ ) }),
22586
+ /* @__PURE__ */ jsx9("div", { className: "tool-approval-overlay__footer", children: /* @__PURE__ */ jsxs8("div", { className: "tool-approval-overlay__actions", children: [
22587
+ /* @__PURE__ */ jsx9(
22588
+ "button",
22589
+ {
22590
+ type: "button",
22591
+ onClick: handleFreeformSubmit,
22592
+ disabled: !freeformText.trim(),
22593
+ className: "tool-approval-overlay__button tool-approval-overlay__button--primary",
22594
+ children: "Send"
22595
+ }
22596
+ ),
22597
+ /* @__PURE__ */ jsx9(
22598
+ "button",
22599
+ {
22600
+ type: "button",
22601
+ onClick: () => setShowFreeform(false),
22602
+ className: "tool-approval-overlay__button tool-approval-overlay__button--secondary",
22603
+ children: "Back"
22604
+ }
22605
+ )
22606
+ ] }) })
22607
+ ] }) }) });
22608
+ }
22609
+
21986
22610
  // lib/chat/display-modes/BriefDisplayMode.tsx
21987
- import React2, { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3, useState as useState4 } from "react";
21988
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
22611
+ import React2, { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3, useState as useState6 } from "react";
22612
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
21989
22613
  function CollapsedDisplay({
21990
22614
  collapsed,
21991
22615
  renderPart,
21992
22616
  itemKey
21993
22617
  }) {
21994
- const [isExpanded, setIsExpanded] = useState4(false);
21995
- const [isAnimating, setIsAnimating] = useState4(false);
22618
+ const [isExpanded, setIsExpanded] = useState6(false);
22619
+ const [isAnimating, setIsAnimating] = useState6(false);
21996
22620
  const contentRef = useRef3(null);
21997
22621
  const partsCountRef = useRef3(collapsed.parts.length);
21998
22622
  useEffect3(() => {
@@ -22010,19 +22634,19 @@ function CollapsedDisplay({
22010
22634
  "chat-widget__collapsed",
22011
22635
  isAnimating ? "chat-widget__collapsed--animating" : ""
22012
22636
  ].filter(Boolean).join(" ");
22013
- return /* @__PURE__ */ jsxs2("div", { className: collapsedClasses, children: [
22014
- /* @__PURE__ */ jsx2(
22637
+ return /* @__PURE__ */ jsxs9("div", { className: collapsedClasses, children: [
22638
+ /* @__PURE__ */ jsx10(
22015
22639
  "div",
22016
22640
  {
22017
22641
  className: `chat-widget__collapsed-content ${isExpanded ? "chat-widget__collapsed-content--expanded" : ""}`,
22018
- children: /* @__PURE__ */ jsx2("div", { ref: contentRef, className: "chat-widget__collapsed-content-inner", children: collapsed.parts.map((part, idx) => /* @__PURE__ */ jsx2("div", { children: renderPart(part, `${itemKey}-expanded-${idx}`) }, `${itemKey}-expanded-${idx}`)) })
22642
+ children: /* @__PURE__ */ jsx10("div", { ref: contentRef, className: "chat-widget__collapsed-content-inner", children: collapsed.parts.map((part, idx) => /* @__PURE__ */ jsx10("div", { children: renderPart(part, `${itemKey}-expanded-${idx}`) }, `${itemKey}-expanded-${idx}`)) })
22019
22643
  }
22020
22644
  ),
22021
- /* @__PURE__ */ jsxs2("div", { className: `chat-widget__collapsed-preview ${isExpanded ? "chat-widget__collapsed-preview--hidden" : ""}`, children: [
22645
+ /* @__PURE__ */ jsxs9("div", { className: `chat-widget__collapsed-preview ${isExpanded ? "chat-widget__collapsed-preview--hidden" : ""}`, children: [
22022
22646
  renderPart(collapsed.lastPart, `${itemKey}-preview`),
22023
- /* @__PURE__ */ jsx2("div", { className: "chat-widget__collapsed-gradient" })
22647
+ /* @__PURE__ */ jsx10("div", { className: "chat-widget__collapsed-gradient" })
22024
22648
  ] }),
22025
- /* @__PURE__ */ jsx2(
22649
+ /* @__PURE__ */ jsx10(
22026
22650
  "button",
22027
22651
  {
22028
22652
  type: "button",
@@ -22117,9 +22741,9 @@ function BriefDisplayMode({
22117
22741
  () => computeCollapsedView(sections, messageId),
22118
22742
  [sections, messageId]
22119
22743
  );
22120
- return /* @__PURE__ */ jsx2(Fragment, { children: viewItems.map((viewItem) => {
22744
+ return /* @__PURE__ */ jsx10(Fragment2, { children: viewItems.map((viewItem) => {
22121
22745
  if (viewItem.type === "collapsed") {
22122
- return /* @__PURE__ */ jsx2(
22746
+ return /* @__PURE__ */ jsx10(
22123
22747
  CollapsedDisplay,
22124
22748
  {
22125
22749
  collapsed: viewItem.collapsed,
@@ -22130,11 +22754,11 @@ function BriefDisplayMode({
22130
22754
  );
22131
22755
  }
22132
22756
  if (viewItem.type === "parts") {
22133
- return /* @__PURE__ */ jsx2(React2.Fragment, { children: viewItem.parts.map((part, idx) => /* @__PURE__ */ jsx2("div", { children: renderPart(part, `${viewItem.key}-part-${idx}`) }, `${viewItem.key}-part-${idx}`)) }, viewItem.key);
22757
+ return /* @__PURE__ */ jsx10(React2.Fragment, { children: viewItem.parts.map((part, idx) => /* @__PURE__ */ jsx10("div", { children: renderPart(part, `${viewItem.key}-part-${idx}`) }, `${viewItem.key}-part-${idx}`)) }, viewItem.key);
22134
22758
  }
22135
22759
  if (viewItem.type === "group") {
22136
- const children = /* @__PURE__ */ jsxs2(Fragment, { children: [
22137
- viewItem.collapsedParts && /* @__PURE__ */ jsx2(
22760
+ const children = /* @__PURE__ */ jsxs9(Fragment2, { children: [
22761
+ viewItem.collapsedParts && /* @__PURE__ */ jsx10(
22138
22762
  CollapsedDisplay,
22139
22763
  {
22140
22764
  collapsed: viewItem.collapsedParts,
@@ -22142,7 +22766,7 @@ function BriefDisplayMode({
22142
22766
  itemKey: `${viewItem.key}-collapsed`
22143
22767
  }
22144
22768
  ),
22145
- viewItem.currentParts.map((part, idx) => /* @__PURE__ */ jsx2("div", { children: renderPart(part, `${viewItem.key}-current-${idx}`) }, `${viewItem.key}-current-${idx}`))
22769
+ viewItem.currentParts.map((part, idx) => /* @__PURE__ */ jsx10("div", { children: renderPart(part, `${viewItem.key}-current-${idx}`) }, `${viewItem.key}-current-${idx}`))
22146
22770
  ] });
22147
22771
  return renderGroup(viewItem.groupName, viewItem.key, children);
22148
22772
  }
@@ -22152,22 +22776,22 @@ function BriefDisplayMode({
22152
22776
 
22153
22777
  // lib/chat/display-modes/FullDisplayMode.tsx
22154
22778
  import React3 from "react";
22155
- import { Fragment as Fragment2, jsx as jsx3 } from "react/jsx-runtime";
22779
+ import { Fragment as Fragment3, jsx as jsx11 } from "react/jsx-runtime";
22156
22780
  function FullDisplayMode({
22157
22781
  sections,
22158
22782
  messageId,
22159
22783
  renderPart,
22160
22784
  renderGroup
22161
22785
  }) {
22162
- return /* @__PURE__ */ jsx3(Fragment2, { children: sections.map((section, sectionIdx) => {
22786
+ return /* @__PURE__ */ jsx11(Fragment3, { children: sections.map((section, sectionIdx) => {
22163
22787
  const sectionKey = `${messageId}-section-${sectionIdx}`;
22164
22788
  if (section.type === "step") {
22165
- return /* @__PURE__ */ jsx3(React3.Fragment, { children: section.parts.map((part, partIdx) => /* @__PURE__ */ jsx3("div", { children: renderPart(part, `${sectionKey}-part-${partIdx}`) }, `${sectionKey}-part-${partIdx}`)) }, sectionKey);
22789
+ return /* @__PURE__ */ jsx11(React3.Fragment, { children: section.parts.map((part, partIdx) => /* @__PURE__ */ jsx11("div", { children: renderPart(part, `${sectionKey}-part-${partIdx}`) }, `${sectionKey}-part-${partIdx}`)) }, sectionKey);
22166
22790
  }
22167
22791
  if (section.type === "group") {
22168
22792
  const groupKey = `${messageId}-group-${section.groupName}`;
22169
- const children = section.parts.map((part, partIdx) => /* @__PURE__ */ jsx3("div", { children: renderPart(part, `${groupKey}-part-${partIdx}`) }, `${groupKey}-part-${partIdx}`));
22170
- return renderGroup(section.groupName, groupKey, /* @__PURE__ */ jsx3(Fragment2, { children }));
22793
+ const children = section.parts.map((part, partIdx) => /* @__PURE__ */ jsx11("div", { children: renderPart(part, `${groupKey}-part-${partIdx}`) }, `${groupKey}-part-${partIdx}`));
22794
+ return renderGroup(section.groupName, groupKey, /* @__PURE__ */ jsx11(Fragment3, { children }));
22171
22795
  }
22172
22796
  return null;
22173
22797
  }) });
@@ -25637,12 +26261,12 @@ function remarkGfm(options) {
25637
26261
  }
25638
26262
 
25639
26263
  // lib/chat/components/MessageFeedback.css
25640
- styleInject(".chat-widget__feedback {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n margin-top: 0.35rem;\n}\n.chat-widget__feedback-button {\n border: none;\n background: transparent;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n color: #9ca3af;\n cursor: pointer;\n border-radius: 0.35rem;\n transition: all 0.15s ease;\n}\n.chat-widget__feedback-button:hover:not(:disabled) {\n background: rgba(0, 0, 0, 0.05);\n color: #6b7280;\n}\n.chat-widget__feedback-button:disabled {\n cursor: default;\n opacity: 0.5;\n}\n.chat-widget__feedback-button--positive.chat-widget__feedback-button--selected {\n color: #22c55e;\n background: rgba(34, 197, 94, 0.1);\n}\n.chat-widget__feedback-button--negative.chat-widget__feedback-button--selected {\n color: #ef4444;\n background: rgba(239, 68, 68, 0.1);\n}\n.chat-widget__feedback-button--comment.chat-widget__feedback-button--selected {\n background: rgba(0, 0, 0, 0.05);\n}\n.chat-widget__feedback-button--comment.chat-widget__feedback-button--has-content {\n color: #3b82f6;\n}\n.chat-widget__feedback-icon {\n width: 1rem;\n height: 1rem;\n}\n.chat-widget__feedback-comment-section {\n margin-top: 0.75rem;\n background: var(--chat-background, #ffffff);\n border: 1px solid var(--chat-border, #e5e7eb);\n border-radius: 0.5rem;\n padding: 0.75rem;\n width: 100%;\n max-width: 400px;\n}\n.chat-widget__feedback-comment-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 0.5rem;\n font-size: 0.8125rem;\n font-weight: 600;\n color: var(--chat-assistant-text, #111827);\n}\n.chat-widget__feedback-comment-required {\n font-size: 0.6875rem;\n font-weight: 500;\n color: #ef4444;\n background: rgba(239, 68, 68, 0.1);\n padding: 0.125rem 0.375rem;\n border-radius: 0.25rem;\n}\n.chat-widget__feedback-comment-body {\n display: flex;\n gap: 0.5rem;\n align-items: flex-start;\n}\n.chat-widget__feedback-textarea {\n flex: 1;\n min-height: 60px;\n padding: 0.625rem;\n border: 1px solid var(--chat-border, #e5e7eb);\n border-radius: 0.35rem;\n font-size: 0.875rem;\n font-family: inherit;\n resize: vertical;\n color: var(--chat-input-text, #111827);\n background: var(--chat-input-bg, #ffffff);\n line-height: 1.5;\n}\n.chat-widget__feedback-textarea:focus {\n outline: none;\n border-color: var(--chat-primary, #3b82f6);\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);\n}\n.chat-widget__feedback-textarea::-moz-placeholder {\n color: var(--chat-input-placeholder, #6b7280);\n}\n.chat-widget__feedback-textarea::placeholder {\n color: var(--chat-input-placeholder, #6b7280);\n}\n.chat-widget__feedback-actions {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n}\n.chat-widget__feedback-cancel,\n.chat-widget__feedback-submit {\n padding: 0.35rem 0.75rem;\n font-size: 0.75rem;\n font-weight: 500;\n border-radius: 0.3rem;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.chat-widget__feedback-cancel {\n background: transparent;\n border: none;\n color: #9ca3af;\n padding: 0.25rem 0.5rem;\n}\n.chat-widget__feedback-cancel:hover {\n color: #6b7280;\n}\n.chat-widget__feedback-submit {\n background: var(--chat-primary, #3b82f6);\n border: none;\n color: var(--chat-primary-text, #ffffff);\n}\n.chat-widget__feedback-submit:hover:not(:disabled) {\n background: var(--chat-primary-hover, #2563eb);\n}\n.chat-widget__feedback-submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.chat-widget__feedback-wrapper {\n position: relative;\n}\n");
26264
+ styleInject(".chat-widget__feedback {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n margin-top: 0.35rem;\n}\n.chat-widget__feedback-button {\n border: none;\n background: transparent;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n color: var(--chat-text-disabled);\n cursor: pointer;\n border-radius: 0.35rem;\n transition: all 0.15s ease;\n}\n.chat-widget__feedback-button:hover:not(:disabled) {\n background: var(--chat-primary-subtle);\n color: var(--chat-text-muted);\n}\n.chat-widget__feedback-button:disabled {\n cursor: default;\n opacity: 0.5;\n}\n.chat-widget__feedback-button--positive.chat-widget__feedback-button--selected {\n color: var(--chat-success);\n background: var(--chat-success-bg);\n}\n.chat-widget__feedback-button--negative.chat-widget__feedback-button--selected {\n color: var(--chat-error);\n background: var(--chat-error-bg);\n}\n.chat-widget__feedback-button--comment.chat-widget__feedback-button--selected {\n background: var(--chat-primary-subtle);\n}\n.chat-widget__feedback-button--comment.chat-widget__feedback-button--has-content {\n color: var(--chat-primary);\n}\n.chat-widget__feedback-icon {\n width: 1rem;\n height: 1rem;\n}\n.chat-widget__feedback-comment-section {\n margin-top: 0.75rem;\n background: var(--chat-background);\n border: 1px solid var(--chat-border);\n border-radius: 0.5rem;\n padding: 0.75rem;\n width: 100%;\n max-width: 400px;\n}\n.chat-widget__feedback-comment-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 0.5rem;\n font-size: 0.8125rem;\n font-weight: 600;\n color: var(--chat-text);\n}\n.chat-widget__feedback-comment-required {\n font-size: 0.6875rem;\n font-weight: 500;\n color: var(--chat-error);\n background: var(--chat-error-bg);\n padding: 0.125rem 0.375rem;\n border-radius: 0.25rem;\n}\n.chat-widget__feedback-comment-body {\n display: flex;\n gap: 0.5rem;\n align-items: flex-start;\n}\n.chat-widget__feedback-textarea {\n flex: 1;\n min-height: 60px;\n padding: 0.625rem;\n border: 1px solid var(--chat-border);\n border-radius: 0.35rem;\n font-size: 0.875rem;\n font-family: inherit;\n resize: vertical;\n color: var(--chat-input-text);\n background: var(--chat-input-bg);\n line-height: 1.5;\n}\n.chat-widget__feedback-textarea:focus {\n outline: none;\n border-color: var(--chat-primary);\n box-shadow: 0 0 0 2px var(--chat-primary-subtle);\n}\n.chat-widget__feedback-textarea::-moz-placeholder {\n color: var(--chat-input-placeholder);\n}\n.chat-widget__feedback-textarea::placeholder {\n color: var(--chat-input-placeholder);\n}\n.chat-widget__feedback-actions {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n}\n.chat-widget__feedback-cancel,\n.chat-widget__feedback-submit {\n padding: 0.35rem 0.75rem;\n font-size: 0.75rem;\n font-weight: 500;\n border-radius: 0.3rem;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.chat-widget__feedback-cancel {\n background: transparent;\n border: none;\n color: var(--chat-text-disabled);\n padding: 0.25rem 0.5rem;\n}\n.chat-widget__feedback-cancel:hover {\n color: var(--chat-text-muted);\n}\n.chat-widget__feedback-submit {\n background: var(--chat-primary);\n border: none;\n color: var(--chat-primary-text);\n}\n.chat-widget__feedback-submit:hover:not(:disabled) {\n background: var(--chat-primary-hover);\n}\n.chat-widget__feedback-submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.chat-widget__feedback-wrapper {\n position: relative;\n}\n");
25641
26265
 
25642
26266
  // lib/chat/components/MessageFeedback.tsx
25643
26267
  import { MessageSquare, MessageSquareText, ThumbsDown, ThumbsUp } from "lucide-react";
25644
- import { useCallback as useCallback4, useEffect as useEffect4, useState as useState5 } from "react";
25645
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
26268
+ import { useCallback as useCallback4, useEffect as useEffect4, useState as useState7 } from "react";
26269
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
25646
26270
  var classNames = {
25647
26271
  wrapper: "chat-widget__feedback-wrapper",
25648
26272
  container: "chat-widget__feedback",
@@ -25670,11 +26294,11 @@ var MessageFeedback = ({
25670
26294
  requireCommentForNegative = false,
25671
26295
  onSubmit
25672
26296
  }) => {
25673
- const [savedRating, setSavedRating] = useState5(existingRating ?? null);
25674
- const [savedComment, setSavedComment] = useState5(existingComment ?? "");
25675
- const [pendingRating, setPendingRating] = useState5(null);
25676
- const [showCommentBox, setShowCommentBox] = useState5(false);
25677
- const [commentText, setCommentText] = useState5(existingComment ?? "");
26297
+ const [savedRating, setSavedRating] = useState7(existingRating ?? null);
26298
+ const [savedComment, setSavedComment] = useState7(existingComment ?? "");
26299
+ const [pendingRating, setPendingRating] = useState7(null);
26300
+ const [showCommentBox, setShowCommentBox] = useState7(false);
26301
+ const [commentText, setCommentText] = useState7(existingComment ?? "");
25678
26302
  useEffect4(() => {
25679
26303
  if (existingRating) {
25680
26304
  setSavedRating(existingRating);
@@ -25759,9 +26383,9 @@ var MessageFeedback = ({
25759
26383
  const hasComment = savedComment.length > 0;
25760
26384
  const canSubmitComment = (!isCommentRequired || commentText.trim().length > 0) && (displayRating || commentText.trim().length > 0 || hasComment);
25761
26385
  const CommentIcon = hasComment ? MessageSquareText : MessageSquare;
25762
- return /* @__PURE__ */ jsxs3("div", { className: classNames.wrapper, children: [
25763
- /* @__PURE__ */ jsxs3("div", { className: classNames.container, children: [
25764
- /* @__PURE__ */ jsx4(
26386
+ return /* @__PURE__ */ jsxs10("div", { className: classNames.wrapper, children: [
26387
+ /* @__PURE__ */ jsxs10("div", { className: classNames.container, children: [
26388
+ /* @__PURE__ */ jsx12(
25765
26389
  "button",
25766
26390
  {
25767
26391
  type: "button",
@@ -25770,10 +26394,10 @@ var MessageFeedback = ({
25770
26394
  disabled: isSubmitting,
25771
26395
  title: "Good response",
25772
26396
  "aria-label": "Mark as good response",
25773
- children: /* @__PURE__ */ jsx4(ThumbsUp, { className: classNames.icon })
26397
+ children: /* @__PURE__ */ jsx12(ThumbsUp, { className: classNames.icon })
25774
26398
  }
25775
26399
  ),
25776
- /* @__PURE__ */ jsx4(
26400
+ /* @__PURE__ */ jsx12(
25777
26401
  "button",
25778
26402
  {
25779
26403
  type: "button",
@@ -25782,10 +26406,10 @@ var MessageFeedback = ({
25782
26406
  disabled: isSubmitting,
25783
26407
  title: "Could be improved",
25784
26408
  "aria-label": "Mark as could be improved",
25785
- children: /* @__PURE__ */ jsx4(ThumbsDown, { className: classNames.icon })
26409
+ children: /* @__PURE__ */ jsx12(ThumbsDown, { className: classNames.icon })
25786
26410
  }
25787
26411
  ),
25788
- /* @__PURE__ */ jsx4(
26412
+ /* @__PURE__ */ jsx12(
25789
26413
  "button",
25790
26414
  {
25791
26415
  type: "button",
@@ -25794,14 +26418,14 @@ var MessageFeedback = ({
25794
26418
  disabled: isSubmitting,
25795
26419
  title: "Add comment",
25796
26420
  "aria-label": "Add comment",
25797
- children: /* @__PURE__ */ jsx4(CommentIcon, { className: classNames.icon })
26421
+ children: /* @__PURE__ */ jsx12(CommentIcon, { className: classNames.icon })
25798
26422
  }
25799
26423
  )
25800
26424
  ] }),
25801
- showCommentBox && /* @__PURE__ */ jsxs3("div", { className: classNames.commentSection, children: [
25802
- /* @__PURE__ */ jsx4("div", { className: classNames.commentHeader, children: isCommentRequired && /* @__PURE__ */ jsx4("span", { className: classNames.commentRequired, children: "Required" }) }),
25803
- /* @__PURE__ */ jsxs3("div", { className: classNames.commentBody, children: [
25804
- /* @__PURE__ */ jsx4(
26425
+ showCommentBox && /* @__PURE__ */ jsxs10("div", { className: classNames.commentSection, children: [
26426
+ /* @__PURE__ */ jsx12("div", { className: classNames.commentHeader, children: isCommentRequired && /* @__PURE__ */ jsx12("span", { className: classNames.commentRequired, children: "Required" }) }),
26427
+ /* @__PURE__ */ jsxs10("div", { className: classNames.commentBody, children: [
26428
+ /* @__PURE__ */ jsx12(
25805
26429
  "textarea",
25806
26430
  {
25807
26431
  className: classNames.textarea,
@@ -25811,8 +26435,8 @@ var MessageFeedback = ({
25811
26435
  rows: 3
25812
26436
  }
25813
26437
  ),
25814
- /* @__PURE__ */ jsxs3("div", { className: classNames.actions, children: [
25815
- /* @__PURE__ */ jsx4(
26438
+ /* @__PURE__ */ jsxs10("div", { className: classNames.actions, children: [
26439
+ /* @__PURE__ */ jsx12(
25816
26440
  "button",
25817
26441
  {
25818
26442
  type: "button",
@@ -25822,7 +26446,7 @@ var MessageFeedback = ({
25822
26446
  children: "Save"
25823
26447
  }
25824
26448
  ),
25825
- /* @__PURE__ */ jsx4(
26449
+ /* @__PURE__ */ jsx12(
25826
26450
  "button",
25827
26451
  {
25828
26452
  type: "button",
@@ -25838,19 +26462,19 @@ var MessageFeedback = ({
25838
26462
  };
25839
26463
 
25840
26464
  // lib/chat/components/TagGroupDisplay.css
25841
- styleInject('.tag-group {\n margin: 6px 0;\n}\n.tag-group-header {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n background: none;\n border: none;\n padding: 2px 6px 2px 2px;\n cursor: pointer;\n font-size: 13px;\n color: #666;\n border-radius: 4px;\n transition: background-color 0.15s ease;\n}\n.tag-group-header:hover {\n background: #f5f5f5;\n}\n.tag-group-chevron {\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n transition: transform 0.15s ease;\n color: #999;\n}\n.tag-group-chevron--expanded {\n transform: rotate(90deg);\n}\n.tag-group-label {\n font-weight: 500;\n color: #555;\n}\n.tag-group-content {\n margin-left: 7px;\n padding-left: 12px;\n border-left: 2px solid #e0e0e0;\n margin-top: 4px;\n}\n.tag-group-item {\n margin: 4px 0;\n font-size: 13px;\n color: #444;\n}\n.tag-group-item--text {\n display: flex;\n align-items: flex-start;\n gap: 6px;\n}\n.tag-group-item--text::before {\n content: "\\2022";\n color: #999;\n font-size: 14px;\n line-height: 1.4;\n flex-shrink: 0;\n}\n.tag-group-item .tool-call-item {\n margin: 0;\n}\n.tag-group-item--widget {\n display: block;\n margin: 8px 0;\n}\n.tag-group-item .chat-widget__markdown {\n margin: 0;\n}\n.tag-group-item .chat-widget__markdown p {\n margin: 0;\n}\n');
26465
+ styleInject('.tag-group {\n margin: 6px 0;\n}\n.tag-group-header {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n background: none;\n border: none;\n padding: 2px 6px 2px 2px;\n cursor: pointer;\n font-size: 13px;\n color: var(--chat-text-muted);\n border-radius: 4px;\n transition: background-color 0.15s ease;\n}\n.tag-group-header:hover {\n background: var(--chat-background-secondary);\n}\n.tag-group-chevron {\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n transition: transform 0.15s ease;\n color: var(--chat-text-disabled);\n}\n.tag-group-chevron--expanded {\n transform: rotate(90deg);\n}\n.tag-group-label {\n font-weight: 500;\n color: var(--chat-text-secondary);\n}\n.tag-group-content {\n margin-left: 7px;\n padding-left: 12px;\n border-left: 2px solid var(--chat-border);\n margin-top: 4px;\n}\n.tag-group-item {\n margin: 4px 0;\n font-size: 13px;\n color: var(--chat-text-secondary);\n}\n.tag-group-item--text {\n display: flex;\n align-items: flex-start;\n gap: 6px;\n}\n.tag-group-item--text::before {\n content: "\\2022";\n color: var(--chat-text-disabled);\n font-size: 14px;\n line-height: 1.4;\n flex-shrink: 0;\n}\n.tag-group-item .tool-call-item {\n margin: 0;\n}\n.tag-group-item--widget {\n display: block;\n margin: 8px 0;\n}\n.tag-group-item .chat-widget__markdown {\n margin: 0;\n}\n.tag-group-item .chat-widget__markdown p {\n margin: 0;\n}\n');
25842
26466
 
25843
26467
  // lib/chat/components/TagGroupDisplay.tsx
25844
26468
  import { ChevronRight } from "lucide-react";
25845
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
26469
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
25846
26470
  function TagGroupDisplay({
25847
26471
  tagId,
25848
26472
  isExpanded,
25849
26473
  onToggle,
25850
26474
  children
25851
26475
  }) {
25852
- return /* @__PURE__ */ jsxs4("div", { className: "tag-group", children: [
25853
- /* @__PURE__ */ jsxs4(
26476
+ return /* @__PURE__ */ jsxs11("div", { className: "tag-group", children: [
26477
+ /* @__PURE__ */ jsxs11(
25854
26478
  "button",
25855
26479
  {
25856
26480
  className: "tag-group-header",
@@ -25858,33 +26482,33 @@ function TagGroupDisplay({
25858
26482
  "aria-expanded": isExpanded,
25859
26483
  type: "button",
25860
26484
  children: [
25861
- /* @__PURE__ */ jsx5(
26485
+ /* @__PURE__ */ jsx13(
25862
26486
  ChevronRight,
25863
26487
  {
25864
26488
  className: `tag-group-chevron ${isExpanded ? "tag-group-chevron--expanded" : ""}`,
25865
26489
  "aria-hidden": "true"
25866
26490
  }
25867
26491
  ),
25868
- /* @__PURE__ */ jsx5("span", { className: "tag-group-label", children: tagId })
26492
+ /* @__PURE__ */ jsx13("span", { className: "tag-group-label", children: tagId })
25869
26493
  ]
25870
26494
  }
25871
26495
  ),
25872
- isExpanded && /* @__PURE__ */ jsx5("div", { className: "tag-group-content", role: "region", children })
26496
+ isExpanded && /* @__PURE__ */ jsx13("div", { className: "tag-group-content", role: "region", children })
25873
26497
  ] });
25874
26498
  }
25875
26499
 
25876
26500
  // lib/chat/components/ToolCallDisplay.css
25877
- styleInject(".tool-call-item {\n font-size: 13px;\n color: #666;\n margin: 4px 0;\n}\n.tool-call-header {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 4px;\n margin-bottom: 4px;\n}\n.tool-call-spinner {\n width: 12px;\n height: 12px;\n border: 2px solid #e0e0e0;\n border-top-color: #666;\n border-radius: 50%;\n animation: tool-call-spin 0.8s linear infinite;\n flex-shrink: 0;\n}\n@keyframes tool-call-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.tool-call-status-icon {\n width: 12px;\n height: 12px;\n border: 2px solid #e0e0e0;\n border-radius: 50%;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n}\n.tool-call-status-icon--error {\n border-color: #dc2626;\n}\n.tool-call-status-icon__inner {\n width: 8px;\n height: 8px;\n}\n.tool-call-status-icon__inner--success {\n color: #9ca3af;\n}\n.tool-call-status-icon__inner--error {\n color: #dc2626;\n}\n.tool-call-label {\n color: #888;\n}\n.tool-call-label code {\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n monospace;\n font-size: 12px;\n background: #f5f5f5;\n padding: 2px 6px;\n border-radius: 4px;\n color: #555;\n}\n.tool-call-toggle {\n font-size: 9px;\n font-weight: 600;\n letter-spacing: 0.5px;\n text-transform: uppercase;\n color: #6b7280;\n background: transparent;\n border: 1px solid #d1d5db;\n border-radius: 3px;\n cursor: pointer;\n padding: 2px 6px;\n margin-left: 4px;\n transition: all 0.15s ease;\n}\n.tool-call-toggle:hover {\n color: #374151;\n border-color: #9ca3af;\n background: #f9fafb;\n}\n.tool-call-details {\n margin-top: 8px;\n margin-left: 16px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.tool-call-section {\n display: flex;\n gap: 4px;\n}\n.tool-call-section-label {\n flex-shrink: 0;\n font-size: 10px;\n font-weight: 600;\n color: #6b7280;\n width: 28px;\n padding-top: 8px;\n text-align: right;\n}\n.tool-call-section-content-wrapper {\n flex: 1;\n position: relative;\n min-width: 0;\n}\n.tool-call-section-toggle {\n position: absolute;\n top: 4px;\n right: 4px;\n font-size: 9px;\n font-weight: 600;\n letter-spacing: 0.5px;\n text-transform: uppercase;\n color: #6b7280;\n background: rgba(255, 255, 255, 0.9);\n border: 1px solid #d1d5db;\n border-radius: 3px;\n cursor: pointer;\n padding: 2px 6px;\n transition: all 0.15s ease;\n opacity: 0;\n z-index: 1;\n}\n.tool-call-section-content-wrapper:hover .tool-call-section-toggle {\n opacity: 1;\n}\n.tool-call-section-toggle:hover {\n color: #374151;\n border-color: #9ca3af;\n background: #f9fafb;\n}\n.tool-call-section-content {\n padding: 8px 12px;\n background: #f8f9fa;\n border-radius: 6px;\n border: 1px solid #e9ecef;\n overflow-x: auto;\n}\n.tool-call-section-content.collapsed {\n max-height: 2.4em;\n overflow: hidden;\n padding-top: 4px;\n padding-bottom: 4px;\n}\n.tool-call-section-content.collapsed pre {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: block;\n max-width: 100%;\n}\n.tool-call-section-content pre {\n margin: 0;\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n monospace;\n font-size: 11px;\n color: #333;\n white-space: pre-wrap;\n word-break: break-word;\n}\n.tool-call-error {\n color: #dc2626;\n font-weight: 600;\n font-size: 9px;\n letter-spacing: 0.5px;\n margin-left: auto;\n}\n");
26501
+ styleInject(".tool-call-item {\n font-size: 13px;\n color: var(--chat-text-muted);\n margin: 4px 0;\n}\n.tool-call-header {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 4px;\n margin-bottom: 4px;\n}\n.tool-call-spinner {\n width: 12px;\n height: 12px;\n border: 2px solid var(--chat-border);\n border-top-color: var(--chat-text-muted);\n border-radius: 50%;\n animation: tool-call-spin 0.8s linear infinite;\n flex-shrink: 0;\n}\n@keyframes tool-call-spin {\n to {\n transform: rotate(360deg);\n }\n}\n.tool-call-status-icon {\n width: 12px;\n height: 12px;\n border: 2px solid var(--chat-border);\n border-radius: 50%;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n}\n.tool-call-status-icon--error {\n border-color: var(--chat-error);\n}\n.tool-call-status-icon__inner {\n width: 8px;\n height: 8px;\n}\n.tool-call-status-icon__inner--success {\n color: var(--chat-text-disabled);\n}\n.tool-call-status-icon__inner--error {\n color: var(--chat-error);\n}\n.tool-call-label {\n color: var(--chat-text-muted);\n}\n.tool-call-label code {\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n monospace;\n font-size: 12px;\n background: var(--chat-background-secondary);\n padding: 2px 6px;\n border-radius: 4px;\n color: var(--chat-text-secondary);\n}\n.tool-call-toggle {\n font-size: 9px;\n font-weight: 600;\n letter-spacing: 0.5px;\n text-transform: uppercase;\n color: var(--chat-text-muted);\n background: transparent;\n border: 1px solid var(--chat-border);\n border-radius: 3px;\n cursor: pointer;\n padding: 2px 6px;\n margin-left: 4px;\n transition: all 0.15s ease;\n}\n.tool-call-toggle:hover {\n color: var(--chat-text-secondary);\n border-color: var(--chat-text-disabled);\n background: var(--chat-background-secondary);\n}\n.tool-call-details {\n margin-top: 8px;\n margin-left: 16px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.tool-call-section {\n display: flex;\n gap: 4px;\n}\n.tool-call-section-label {\n flex-shrink: 0;\n font-size: 10px;\n font-weight: 600;\n color: var(--chat-text-muted);\n width: 28px;\n padding-top: 8px;\n text-align: right;\n}\n.tool-call-section-content-wrapper {\n flex: 1;\n position: relative;\n min-width: 0;\n}\n.tool-call-section-toggle {\n position: absolute;\n top: 4px;\n right: 4px;\n font-size: 9px;\n font-weight: 600;\n letter-spacing: 0.5px;\n text-transform: uppercase;\n color: var(--chat-text-muted);\n background: var(--chat-background);\n border: 1px solid var(--chat-border);\n border-radius: 3px;\n cursor: pointer;\n padding: 2px 6px;\n transition: all 0.15s ease;\n opacity: 0;\n z-index: 1;\n}\n.tool-call-section-content-wrapper:hover .tool-call-section-toggle {\n opacity: 1;\n}\n.tool-call-section-toggle:hover {\n color: var(--chat-text-secondary);\n border-color: var(--chat-text-disabled);\n background: var(--chat-background-secondary);\n}\n.tool-call-section-content {\n padding: 8px 12px;\n background: var(--chat-background-secondary);\n border-radius: 6px;\n border: 1px solid var(--chat-border-light);\n overflow-x: auto;\n}\n.tool-call-section-content.collapsed {\n max-height: 2.4em;\n overflow: hidden;\n padding-top: 4px;\n padding-bottom: 4px;\n}\n.tool-call-section-content.collapsed pre {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: block;\n max-width: 100%;\n}\n.tool-call-section-content pre {\n margin: 0;\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n monospace;\n font-size: 11px;\n color: var(--chat-text);\n white-space: pre-wrap;\n word-break: break-word;\n}\n.tool-call-error {\n color: var(--chat-error);\n font-weight: 600;\n font-size: 9px;\n letter-spacing: 0.5px;\n margin-left: auto;\n}\n");
25878
26502
 
25879
26503
  // lib/chat/components/ToolCallDisplay.tsx
25880
- import { useState as useState6 } from "react";
25881
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
26504
+ import { useState as useState8 } from "react";
26505
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
25882
26506
  function CollapsibleSection({ label, content }) {
25883
- const [isCollapsed, setIsCollapsed] = useState6(false);
25884
- return /* @__PURE__ */ jsxs5("div", { className: "tool-call-section", children: [
25885
- /* @__PURE__ */ jsx6("div", { className: "tool-call-section-label", children: label }),
25886
- /* @__PURE__ */ jsxs5("div", { className: "tool-call-section-content-wrapper", children: [
25887
- /* @__PURE__ */ jsx6(
26507
+ const [isCollapsed, setIsCollapsed] = useState8(false);
26508
+ return /* @__PURE__ */ jsxs12("div", { className: "tool-call-section", children: [
26509
+ /* @__PURE__ */ jsx14("div", { className: "tool-call-section-label", children: label }),
26510
+ /* @__PURE__ */ jsxs12("div", { className: "tool-call-section-content-wrapper", children: [
26511
+ /* @__PURE__ */ jsx14(
25888
26512
  "button",
25889
26513
  {
25890
26514
  className: "tool-call-section-toggle",
@@ -25893,40 +26517,42 @@ function CollapsibleSection({ label, content }) {
25893
26517
  children: isCollapsed ? "SHOW" : "HIDE"
25894
26518
  }
25895
26519
  ),
25896
- /* @__PURE__ */ jsx6("div", { className: `tool-call-section-content ${isCollapsed ? "collapsed" : ""}`, children: /* @__PURE__ */ jsx6("pre", { children: formatOutput(content) }) })
26520
+ /* @__PURE__ */ jsx14("div", { className: `tool-call-section-content ${isCollapsed ? "collapsed" : ""}`, children: /* @__PURE__ */ jsx14("pre", { children: formatOutput(content) }) })
25897
26521
  ] })
25898
26522
  ] });
25899
26523
  }
25900
26524
  function ToolCallDisplay({ toolPart, className = "" }) {
25901
- const [isExpanded, setIsExpanded] = useState6(false);
26525
+ const [isExpanded, setIsExpanded] = useState8(false);
25902
26526
  const toolName = "toolName" in toolPart ? toolPart.toolName : toolPart.type.replace("tool-", "");
25903
26527
  const state = "state" in toolPart ? toolPart.state : "pending";
25904
26528
  const hasOutput = state === "output-available" && "output" in toolPart && toolPart.output !== void 0;
25905
26529
  const isLoading = state === "input-streaming" || state === "input-available" || state === "approval-requested";
25906
- const hasError = state === "output-error" || state === "output-denied";
26530
+ const hasError = state === "output-error";
26531
+ const isDenied = state === "output-denied";
26532
+ const hasFailed = hasError || isDenied;
25907
26533
  const input = "input" in toolPart ? toolPart.input : void 0;
25908
26534
  const output = "output" in toolPart ? toolPart.output : void 0;
25909
26535
  const hasInput = input !== void 0 && input !== null && !(typeof input === "object" && Object.keys(input).length === 0);
25910
26536
  const canExpand = hasInput || hasOutput;
25911
26537
  const renderStatusIcon = () => {
25912
26538
  if (isLoading) {
25913
- return /* @__PURE__ */ jsx6("span", { className: "tool-call-spinner" });
26539
+ return /* @__PURE__ */ jsx14("span", { className: "tool-call-spinner" });
25914
26540
  }
25915
- const borderClass = hasError ? "tool-call-status-icon--error" : "";
25916
- return /* @__PURE__ */ jsx6("span", { className: `tool-call-status-icon ${borderClass}`, children: hasError ? /* @__PURE__ */ jsxs5("svg", { className: "tool-call-status-icon__inner tool-call-status-icon__inner--error", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: [
25917
- /* @__PURE__ */ jsx6("line", { x1: "5", y1: "5", x2: "11", y2: "11" }),
25918
- /* @__PURE__ */ jsx6("line", { x1: "11", y1: "5", x2: "5", y2: "11" })
25919
- ] }) : /* @__PURE__ */ jsx6("svg", { className: "tool-call-status-icon__inner tool-call-status-icon__inner--success", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("polyline", { points: "4,8 7,11 12,5" }) }) });
26541
+ const borderClass = hasFailed ? "tool-call-status-icon--error" : "";
26542
+ return /* @__PURE__ */ jsx14("span", { className: `tool-call-status-icon ${borderClass}`, children: hasFailed ? /* @__PURE__ */ jsxs12("svg", { className: "tool-call-status-icon__inner tool-call-status-icon__inner--error", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: [
26543
+ /* @__PURE__ */ jsx14("line", { x1: "5", y1: "5", x2: "11", y2: "11" }),
26544
+ /* @__PURE__ */ jsx14("line", { x1: "11", y1: "5", x2: "5", y2: "11" })
26545
+ ] }) : /* @__PURE__ */ jsx14("svg", { className: "tool-call-status-icon__inner tool-call-status-icon__inner--success", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx14("polyline", { points: "4,8 7,11 12,5" }) }) });
25920
26546
  };
25921
- return /* @__PURE__ */ jsxs5("div", { className: `tool-call-item ${className}`, children: [
25922
- /* @__PURE__ */ jsxs5("div", { className: "tool-call-header", children: [
26547
+ return /* @__PURE__ */ jsxs12("div", { className: `tool-call-item ${className}`, children: [
26548
+ /* @__PURE__ */ jsxs12("div", { className: "tool-call-header", children: [
25923
26549
  renderStatusIcon(),
25924
- /* @__PURE__ */ jsxs5("span", { className: "tool-call-label", children: [
26550
+ /* @__PURE__ */ jsxs12("span", { className: "tool-call-label", children: [
25925
26551
  isLoading ? "Calling" : "Called",
25926
26552
  " ",
25927
- /* @__PURE__ */ jsx6("code", { children: toolName })
26553
+ /* @__PURE__ */ jsx14("code", { children: toolName })
25928
26554
  ] }),
25929
- canExpand && /* @__PURE__ */ jsx6(
26555
+ canExpand && /* @__PURE__ */ jsx14(
25930
26556
  "button",
25931
26557
  {
25932
26558
  className: "tool-call-toggle",
@@ -25935,11 +26561,12 @@ function ToolCallDisplay({ toolPart, className = "" }) {
25935
26561
  children: isExpanded ? "HIDE" : "SHOW"
25936
26562
  }
25937
26563
  ),
25938
- hasError && /* @__PURE__ */ jsx6("span", { className: "tool-call-error", children: "ERROR" })
26564
+ isDenied && /* @__PURE__ */ jsx14("span", { className: "tool-call-error", children: "DENIED" }),
26565
+ hasError && /* @__PURE__ */ jsx14("span", { className: "tool-call-error", children: "ERROR" })
25939
26566
  ] }),
25940
- isExpanded && canExpand && /* @__PURE__ */ jsxs5("div", { className: "tool-call-details", children: [
25941
- hasInput && /* @__PURE__ */ jsx6(CollapsibleSection, { label: "IN", content: input }),
25942
- hasOutput && /* @__PURE__ */ jsx6(CollapsibleSection, { label: "OUT", content: output })
26567
+ isExpanded && canExpand && /* @__PURE__ */ jsxs12("div", { className: "tool-call-details", children: [
26568
+ hasInput && /* @__PURE__ */ jsx14(CollapsibleSection, { label: "IN", content: input }),
26569
+ hasOutput && /* @__PURE__ */ jsx14(CollapsibleSection, { label: "OUT", content: output })
25943
26570
  ] })
25944
26571
  ] });
25945
26572
  }
@@ -25974,7 +26601,7 @@ function createSDKWidget(widget) {
25974
26601
  var createWidget = (widget) => widget;
25975
26602
 
25976
26603
  // lib/chat/components/WidgetRenderer.tsx
25977
- import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
26604
+ import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
25978
26605
  function renderError(container, message) {
25979
26606
  container.innerHTML = "";
25980
26607
  const errorDiv = document.createElement("div");
@@ -25982,7 +26609,7 @@ function renderError(container, message) {
25982
26609
  errorDiv.textContent = message;
25983
26610
  container.appendChild(errorDiv);
25984
26611
  }
25985
- function WidgetRenderer({ widget, payload, enriched, messageContext }) {
26612
+ function WidgetRenderer({ widget, payload, enriched, messageContext, invokeTool }) {
25986
26613
  const containerRef = useRef4(null);
25987
26614
  const rootRef = useRef4(null);
25988
26615
  const customerReactDOMRef = useRef4(void 0);
@@ -26019,7 +26646,7 @@ function WidgetRenderer({ widget, payload, enriched, messageContext }) {
26019
26646
  }
26020
26647
  let element;
26021
26648
  try {
26022
- element = widget.render(payload, enriched, { messageContext });
26649
+ element = widget.render(payload, enriched, { messageContext, invokeTool });
26023
26650
  } catch (error48) {
26024
26651
  console.error(`Widget "${widget.widgetType}" render function threw:`, error48);
26025
26652
  renderError(containerRef.current, `Widget render error: ${widget.widgetType}`);
@@ -26080,28 +26707,37 @@ To fix, add your ReactDOM to the widget config:
26080
26707
  renderError(containerRef.current, `Widget system error: ${widget.widgetType}`);
26081
26708
  }
26082
26709
  }
26083
- }, [isSdk, widget, payload, enriched, payloadHash, enrichedHash, messageContext]);
26710
+ }, [isSdk, widget, payload, enriched, payloadHash, enrichedHash, messageContext, invokeTool]);
26084
26711
  if (isSdk) {
26085
26712
  try {
26086
- const element = widget.render(payload, enriched, { messageContext });
26087
- return /* @__PURE__ */ jsx7(Fragment3, { children: element });
26713
+ const element = widget.render(payload, enriched, { messageContext, invokeTool });
26714
+ return /* @__PURE__ */ jsx15(Fragment4, { children: element });
26088
26715
  } catch (error48) {
26089
26716
  console.error(`SDK widget "${widget.widgetType}" render threw:`, error48);
26090
26717
  const errorMessage = error48 instanceof Error ? error48.message : String(error48);
26091
- return /* @__PURE__ */ jsxs6("div", { className: "widget-error", title: errorMessage, children: [
26718
+ return /* @__PURE__ */ jsxs13("div", { className: "widget-error", title: errorMessage, children: [
26092
26719
  "Widget error: ",
26093
26720
  widget.widgetType
26094
26721
  ] });
26095
26722
  }
26096
26723
  }
26097
- return /* @__PURE__ */ jsx7("div", { ref: containerRef, className: "widget-customer-root" });
26724
+ return /* @__PURE__ */ jsx15("div", { ref: containerRef, className: "widget-customer-root" });
26098
26725
  }
26099
26726
 
26100
26727
  // lib/chat/renderers/MessageRenderer.tsx
26101
- import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
26728
+ import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
26102
26729
  function FormattedMarkdownComponent({ children }) {
26103
26730
  const MarkdownComponent = ReactMarkdown;
26104
- return /* @__PURE__ */ jsx8(MarkdownComponent, { remarkPlugins: [remarkGfm], children: children.replace(/\n\n/gi, "\n\n \n\n") });
26731
+ return /* @__PURE__ */ jsx16(
26732
+ MarkdownComponent,
26733
+ {
26734
+ remarkPlugins: [remarkGfm],
26735
+ components: {
26736
+ a: ({ children: children2, href, ...props }) => /* @__PURE__ */ jsx16("a", { href, target: "_blank", rel: "noopener noreferrer", ...props, children: children2 })
26737
+ },
26738
+ children: children.replace(/\n\n/gi, "\n\n \n\n")
26739
+ }
26740
+ );
26105
26741
  }
26106
26742
  var FormattedMarkdown = React5.memo(FormattedMarkdownComponent);
26107
26743
  function MessageRenderer({
@@ -26111,7 +26747,8 @@ function MessageRenderer({
26111
26747
  displayMode = "brief",
26112
26748
  tagExpansion,
26113
26749
  className,
26114
- feedback
26750
+ feedback,
26751
+ invokeTool
26115
26752
  }) {
26116
26753
  const messageContext = useMemo4(() => {
26117
26754
  if (!feedback) return void 0;
@@ -26133,43 +26770,44 @@ function MessageRenderer({
26133
26770
  if (part.type === "text") {
26134
26771
  const trimmed = part.text?.trim();
26135
26772
  if (!trimmed) return null;
26136
- return /* @__PURE__ */ jsx8("div", { className: "chat-widget__markdown", children: /* @__PURE__ */ jsx8(FormattedMarkdown, { children: trimmed }) }, key);
26773
+ return /* @__PURE__ */ jsx16("div", { className: "chat-widget__markdown", children: /* @__PURE__ */ jsx16(FormattedMarkdown, { children: trimmed }) }, key);
26137
26774
  }
26138
26775
  if (part.type.startsWith("tool-") || part.type === "dynamic-tool") {
26139
- return /* @__PURE__ */ jsx8(ToolCallDisplay, { toolPart: part }, key);
26776
+ return /* @__PURE__ */ jsx16(ToolCallDisplay, { toolPart: part }, key);
26140
26777
  }
26141
26778
  if (part.type === "data-ui") {
26142
26779
  const dataPart = part;
26143
26780
  const uiWidgets = dataPart.data;
26144
26781
  if (!Array.isArray(uiWidgets)) return null;
26145
26782
  if (!widgets || widgets.length === 0) {
26146
- return /* @__PURE__ */ jsxs7("div", { className: "text-muted-foreground text-sm italic", children: [
26783
+ return /* @__PURE__ */ jsxs14("div", { className: "text-muted-foreground text-sm italic", children: [
26147
26784
  "[UI Widget: ",
26148
26785
  uiWidgets.map((w) => w.widgetType || "unknown").join(", "),
26149
26786
  "]"
26150
26787
  ] }, key);
26151
26788
  }
26152
- return /* @__PURE__ */ jsx8(React5.Fragment, { children: uiWidgets.map((widget, idx) => {
26789
+ return /* @__PURE__ */ jsx16(React5.Fragment, { children: uiWidgets.map((widget, idx) => {
26153
26790
  const widgetDef = widgets.find((w) => w.widgetType === widget.widgetType);
26154
26791
  if (!widgetDef) {
26155
- return /* @__PURE__ */ jsxs7("span", { children: [
26792
+ return /* @__PURE__ */ jsxs14("span", { children: [
26156
26793
  "[Unknown widget: ",
26157
26794
  widget.widgetType,
26158
26795
  "]"
26159
26796
  ] }, `${key}-widget-${idx}`);
26160
26797
  }
26161
- return /* @__PURE__ */ jsx8(
26798
+ return /* @__PURE__ */ jsx16(
26162
26799
  "div",
26163
26800
  {
26164
26801
  className: "chat-widget__widget",
26165
26802
  inert: readonly2 ? true : void 0,
26166
- children: /* @__PURE__ */ jsx8(
26803
+ children: /* @__PURE__ */ jsx16(
26167
26804
  WidgetRenderer,
26168
26805
  {
26169
26806
  widget: widgetDef,
26170
26807
  payload: widget.payload,
26171
26808
  enriched: widget.enriched ?? {},
26172
- messageContext: messageContext ?? void 0
26809
+ messageContext: messageContext ?? void 0,
26810
+ invokeTool
26173
26811
  }
26174
26812
  )
26175
26813
  },
@@ -26184,7 +26822,7 @@ function MessageRenderer({
26184
26822
  const renderGroup = useCallback5(
26185
26823
  (groupName, key, children) => {
26186
26824
  const isExpanded = tagExpansion?.state.get(key) ?? true;
26187
- return /* @__PURE__ */ jsx8(
26825
+ return /* @__PURE__ */ jsx16(
26188
26826
  TagGroupDisplay,
26189
26827
  {
26190
26828
  tagId: groupName,
@@ -26198,8 +26836,8 @@ function MessageRenderer({
26198
26836
  [tagExpansion]
26199
26837
  );
26200
26838
  const DisplayMode = displayMode === "brief" ? BriefDisplayMode : FullDisplayMode;
26201
- return /* @__PURE__ */ jsxs7(Fragment4, { children: [
26202
- /* @__PURE__ */ jsx8("div", { className, children: /* @__PURE__ */ jsx8(
26839
+ return /* @__PURE__ */ jsxs14(Fragment5, { children: [
26840
+ /* @__PURE__ */ jsx16("div", { className, children: /* @__PURE__ */ jsx16(
26203
26841
  DisplayMode,
26204
26842
  {
26205
26843
  sections: message.sections,
@@ -26208,7 +26846,7 @@ function MessageRenderer({
26208
26846
  renderGroup
26209
26847
  }
26210
26848
  ) }),
26211
- !readonly2 && feedback && /* @__PURE__ */ jsx8(
26849
+ !readonly2 && feedback && /* @__PURE__ */ jsx16(
26212
26850
  MessageFeedback,
26213
26851
  {
26214
26852
  messageId: message.id,
@@ -26223,7 +26861,7 @@ function MessageRenderer({
26223
26861
  }
26224
26862
 
26225
26863
  // lib/chat/ChatWidget.tsx
26226
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
26864
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
26227
26865
  var classNames2 = {
26228
26866
  container: "chat-widget",
26229
26867
  header: "chat-widget__header",
@@ -26255,15 +26893,23 @@ var classNames2 = {
26255
26893
  voiceControl: "chat-widget__voice",
26256
26894
  micButton: "chat-widget__mic-button"
26257
26895
  };
26258
- var defaultTheme = {
26896
+ var lightTheme = {
26897
+ theme: "light",
26259
26898
  primaryColor: "#3b82f6",
26260
26899
  primaryTextColor: "#ffffff",
26261
26900
  backgroundColor: "#ffffff",
26901
+ backgroundSecondary: "#f9fafb",
26902
+ backgroundTertiary: "#f3f4f6",
26262
26903
  borderColor: "#e5e7eb",
26904
+ borderColorLight: "#f3f4f6",
26263
26905
  headerTextColor: "#ffffff",
26264
26906
  userBubbleTextColor: "#ffffff",
26265
26907
  assistantBubbleBackground: "transparent",
26266
26908
  assistantBubbleTextColor: "#111827",
26909
+ textColor: "#111827",
26910
+ textSecondary: "#4b5563",
26911
+ textMuted: "#6b7280",
26912
+ textDisabled: "#9ca3af",
26267
26913
  fontFamily: `'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif`,
26268
26914
  borderRadius: "0.75rem",
26269
26915
  inputBackground: "#ffffff",
@@ -26271,6 +26917,44 @@ var defaultTheme = {
26271
26917
  inputPlaceholderColor: "#6b7280",
26272
26918
  thoughtsBorderColor: "#d1d5db"
26273
26919
  };
26920
+ var darkTheme = {
26921
+ theme: "dark",
26922
+ primaryColor: "#3b82f6",
26923
+ primaryTextColor: "#ffffff",
26924
+ backgroundColor: "#1f2937",
26925
+ backgroundSecondary: "#374151",
26926
+ backgroundTertiary: "#4b5563",
26927
+ borderColor: "#4b5563",
26928
+ borderColorLight: "#374151",
26929
+ headerTextColor: "#ffffff",
26930
+ userBubbleTextColor: "#ffffff",
26931
+ assistantBubbleBackground: "transparent",
26932
+ assistantBubbleTextColor: "#f9fafb",
26933
+ textColor: "#f9fafb",
26934
+ textSecondary: "#d1d5db",
26935
+ textMuted: "#9ca3af",
26936
+ textDisabled: "#6b7280",
26937
+ fontFamily: `'Inter', system-ui, -apple-system, BlinkMacSystemFont, sans-serif`,
26938
+ borderRadius: "0.75rem",
26939
+ inputBackground: "#374151",
26940
+ inputTextColor: "#f9fafb",
26941
+ inputPlaceholderColor: "#9ca3af",
26942
+ thoughtsBorderColor: "#4b5563"
26943
+ };
26944
+ function detectDarkMode() {
26945
+ if (typeof window === "undefined") return false;
26946
+ const html2 = document.documentElement;
26947
+ const body = document.body;
26948
+ const dataTheme = html2.getAttribute("data-theme") || body.getAttribute("data-theme");
26949
+ if (dataTheme === "dark") return true;
26950
+ if (dataTheme === "light") return false;
26951
+ if (html2.classList.contains("dark") || body.classList.contains("dark")) return true;
26952
+ if (html2.classList.contains("light") || body.classList.contains("light")) return false;
26953
+ const colorScheme = getComputedStyle(html2).colorScheme;
26954
+ if (colorScheme === "dark") return true;
26955
+ if (colorScheme === "light") return false;
26956
+ return window.matchMedia("(prefers-color-scheme: dark)").matches;
26957
+ }
26274
26958
  var mixWithBlack = (hex3, ratio = 0.15) => {
26275
26959
  const normalized = hex3.replace("#", "");
26276
26960
  if (!/^[0-9a-fA-F]{6}$/.test(normalized)) return hex3;
@@ -26303,17 +26987,50 @@ var ChatWidget = forwardRef(function ChatWidget2({
26303
26987
  widgets,
26304
26988
  feedback
26305
26989
  }, ref) {
26306
- const theme = useMemo5(
26307
- () => ({ ...defaultTheme, ...styleProps || {} }),
26308
- [styleProps]
26309
- );
26990
+ const [detectedDarkMode, setDetectedDarkMode] = useState9(false);
26991
+ useEffect6(() => {
26992
+ setDetectedDarkMode(detectDarkMode());
26993
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
26994
+ const handleChange = () => setDetectedDarkMode(detectDarkMode());
26995
+ mediaQuery.addEventListener("change", handleChange);
26996
+ const observer = new MutationObserver(() => {
26997
+ setDetectedDarkMode(detectDarkMode());
26998
+ });
26999
+ observer.observe(document.documentElement, {
27000
+ attributes: true,
27001
+ attributeFilter: ["data-theme", "class"]
27002
+ });
27003
+ observer.observe(document.body, {
27004
+ attributes: true,
27005
+ attributeFilter: ["data-theme", "class"]
27006
+ });
27007
+ return () => {
27008
+ mediaQuery.removeEventListener("change", handleChange);
27009
+ observer.disconnect();
27010
+ };
27011
+ }, []);
27012
+ const theme = useMemo5(() => {
27013
+ const themeMode = styleProps?.theme || "auto";
27014
+ const isDark = themeMode === "dark" || themeMode === "auto" && detectedDarkMode;
27015
+ const baseTheme = isDark ? darkTheme : lightTheme;
27016
+ return { ...baseTheme, ...styleProps || {} };
27017
+ }, [styleProps, detectedDarkMode]);
26310
27018
  const themeVariables = useMemo5(
26311
27019
  () => ({
26312
27020
  "--chat-primary": theme.primaryColor,
26313
27021
  "--chat-primary-text": theme.primaryTextColor,
26314
27022
  "--chat-primary-hover": mixWithBlack(theme.primaryColor, 0.2),
27023
+ "--chat-primary-subtle": `${theme.primaryColor}1a`,
27024
+ // 10% opacity
26315
27025
  "--chat-background": theme.backgroundColor,
27026
+ "--chat-background-secondary": theme.backgroundSecondary,
27027
+ "--chat-background-tertiary": theme.backgroundTertiary,
26316
27028
  "--chat-border": theme.borderColor,
27029
+ "--chat-border-light": theme.borderColorLight,
27030
+ "--chat-text": theme.textColor,
27031
+ "--chat-text-secondary": theme.textSecondary,
27032
+ "--chat-text-muted": theme.textMuted,
27033
+ "--chat-text-disabled": theme.textDisabled,
26317
27034
  "--chat-header-text": theme.headerTextColor,
26318
27035
  "--chat-user-text": theme.userBubbleTextColor,
26319
27036
  "--chat-assistant-bg": theme.assistantBubbleBackground,
@@ -26327,9 +27044,9 @@ var ChatWidget = forwardRef(function ChatWidget2({
26327
27044
  }),
26328
27045
  [theme]
26329
27046
  );
26330
- const [input, setInput] = useState7("");
26331
- const [isMicActive, setIsMicActive] = useState7(false);
26332
- const [isSpeechPending, setIsSpeechPending] = useState7(false);
27047
+ const [input, setInput] = useState9("");
27048
+ const [isMicActive, setIsMicActive] = useState9(false);
27049
+ const [isSpeechPending, setIsSpeechPending] = useState9(false);
26333
27050
  const messagesEndRef = useRef5(null);
26334
27051
  const scrollContainerRef = useRef5(null);
26335
27052
  const isAtBottomRef = useRef5(true);
@@ -26341,7 +27058,11 @@ var ChatWidget = forwardRef(function ChatWidget2({
26341
27058
  isLoadingInitial,
26342
27059
  sendMessage,
26343
27060
  stop,
26344
- setMessages
27061
+ setMessages,
27062
+ addToolOutput,
27063
+ addToolApprovalResponse,
27064
+ pendingToolOutput,
27065
+ pendingToolApproval
26345
27066
  } = useChat({
26346
27067
  api,
26347
27068
  threadId,
@@ -26354,6 +27075,24 @@ var ChatWidget = forwardRef(function ChatWidget2({
26354
27075
  onFinish,
26355
27076
  onMessage
26356
27077
  });
27078
+ const handleToolOutput = useCallback6((result) => {
27079
+ if (pendingToolOutput && addToolOutput) {
27080
+ addToolOutput({
27081
+ tool: "collect_user_input",
27082
+ toolCallId: pendingToolOutput.toolCallId,
27083
+ output: result
27084
+ });
27085
+ }
27086
+ }, [pendingToolOutput, addToolOutput]);
27087
+ const handleToolApproval = useCallback6((approved, reason) => {
27088
+ if (!pendingToolApproval) return;
27089
+ addToolApprovalResponse({
27090
+ id: pendingToolApproval.approvalId,
27091
+ approved,
27092
+ reason
27093
+ });
27094
+ }, [pendingToolApproval, addToolApprovalResponse]);
27095
+ const isInputDisabled = status !== "ready" || !!pendingToolOutput || !!pendingToolApproval;
26357
27096
  useImperativeHandle(ref, () => ({
26358
27097
  sendMessage: (message) => {
26359
27098
  if (message.trim() && status === "ready") {
@@ -26372,7 +27111,36 @@ var ChatWidget = forwardRef(function ChatWidget2({
26372
27111
  agentId,
26373
27112
  agentVersion
26374
27113
  });
26375
- const [tagExpansionState, setTagExpansionState] = useState7(/* @__PURE__ */ new Map());
27114
+ const invokeTool = useMemo5(
27115
+ () => createInvokeTool(api, onAuthError),
27116
+ [api, onAuthError]
27117
+ );
27118
+ const [tagExpansionState, setTagExpansionState] = useState9(/* @__PURE__ */ new Map());
27119
+ const [approvalConfig, setApprovalConfig] = useState9(null);
27120
+ const [approvalConfigLoading, setApprovalConfigLoading] = useState9(false);
27121
+ useEffect6(() => {
27122
+ if (!pendingToolApproval) {
27123
+ setApprovalConfig(null);
27124
+ setApprovalConfigLoading(false);
27125
+ return;
27126
+ }
27127
+ setApprovalConfigLoading(true);
27128
+ fetchApprovalConfig({
27129
+ api,
27130
+ agentId,
27131
+ agentVersion,
27132
+ toolName: pendingToolApproval.toolName,
27133
+ args: pendingToolApproval.args,
27134
+ onAuthError
27135
+ }).then((config2) => {
27136
+ setApprovalConfig(config2);
27137
+ }).catch((err) => {
27138
+ console.error("[ChatWidget] Failed to fetch approval config:", err);
27139
+ setApprovalConfig(null);
27140
+ }).finally(() => {
27141
+ setApprovalConfigLoading(false);
27142
+ });
27143
+ }, [pendingToolApproval, api, agentId, agentVersion, onAuthError]);
26376
27144
  const handleTagToggle = useCallback6((messageId, tagId, currentlyExpanded) => {
26377
27145
  suppressScrollRef.current = true;
26378
27146
  setTagExpansionState((prev) => {
@@ -26455,11 +27223,11 @@ var ChatWidget = forwardRef(function ChatWidget2({
26455
27223
  }, [status]);
26456
27224
  const sendText = useCallback6((raw) => {
26457
27225
  const text4 = (raw ?? input).trim();
26458
- if (!text4 || status !== "ready") return false;
27226
+ if (!text4 || isInputDisabled) return false;
26459
27227
  sendMessage({ text: text4 });
26460
27228
  setInput("");
26461
27229
  return true;
26462
- }, [input, status, sendMessage, setInput]);
27230
+ }, [input, isInputDisabled, sendMessage, setInput]);
26463
27231
  const handleSendMessage = () => {
26464
27232
  sendText();
26465
27233
  };
@@ -26505,15 +27273,15 @@ var ChatWidget = forwardRef(function ChatWidget2({
26505
27273
  console.error("Failed to register chat widgets", err);
26506
27274
  });
26507
27275
  }, [api, threadId, widgets, onAuthError]);
26508
- return /* @__PURE__ */ jsxs8(
27276
+ return /* @__PURE__ */ jsxs15(
26509
27277
  "div",
26510
27278
  {
26511
27279
  className: cn(classNames2.container, className),
26512
27280
  style: themeVariables,
26513
27281
  "data-chat-widget": "",
26514
27282
  children: [
26515
- title && /* @__PURE__ */ jsx9("div", { className: classNames2.header, children: /* @__PURE__ */ jsx9("h3", { className: classNames2.headerTitle, children: title }) }),
26516
- /* @__PURE__ */ jsxs8(
27283
+ title && /* @__PURE__ */ jsx17("div", { className: classNames2.header, children: /* @__PURE__ */ jsx17("h3", { className: classNames2.headerTitle, children: title }) }),
27284
+ /* @__PURE__ */ jsxs15(
26517
27285
  "div",
26518
27286
  {
26519
27287
  className: classNames2.messagesContainer,
@@ -26524,21 +27292,21 @@ var ChatWidget = forwardRef(function ChatWidget2({
26524
27292
  const isUser = message.role === "user";
26525
27293
  const isLastMessage = index === messages.length - 1;
26526
27294
  const showFeedback = feedbackEnabled && !isUser && !(status === "streaming" && isLastMessage);
26527
- return /* @__PURE__ */ jsx9("div", { className: classNames2.messageWrapper, children: /* @__PURE__ */ jsx9(
27295
+ return /* @__PURE__ */ jsx17("div", { className: classNames2.messageWrapper, children: /* @__PURE__ */ jsx17(
26528
27296
  "div",
26529
27297
  {
26530
27298
  className: cn(
26531
27299
  classNames2.messageRow,
26532
27300
  isUser ? classNames2.userMessageRow : classNames2.assistantMessageRow
26533
27301
  ),
26534
- children: /* @__PURE__ */ jsx9(
27302
+ children: /* @__PURE__ */ jsx17(
26535
27303
  "div",
26536
27304
  {
26537
27305
  className: cn(
26538
27306
  classNames2.messageBubble,
26539
27307
  isUser ? classNames2.userMessage : classNames2.assistantMessage
26540
27308
  ),
26541
- children: /* @__PURE__ */ jsx9(
27309
+ children: /* @__PURE__ */ jsx17(
26542
27310
  MessageRenderer,
26543
27311
  {
26544
27312
  message,
@@ -26553,7 +27321,8 @@ var ChatWidget = forwardRef(function ChatWidget2({
26553
27321
  requireCommentForNegative: feedback?.requireCommentForNegative,
26554
27322
  getFeedback: () => getFeedback(message.id),
26555
27323
  submitFeedback: (params) => submitFeedback(message.id, params)
26556
- } : void 0
27324
+ } : void 0,
27325
+ invokeTool
26557
27326
  }
26558
27327
  )
26559
27328
  }
@@ -26561,17 +27330,17 @@ var ChatWidget = forwardRef(function ChatWidget2({
26561
27330
  }
26562
27331
  ) }, message.id);
26563
27332
  }),
26564
- status === "streaming" && /* @__PURE__ */ jsx9("div", { className: classNames2.loadingContainer, children: /* @__PURE__ */ jsx9("div", { className: classNames2.loadingBubble, children: /* @__PURE__ */ jsxs8("div", { className: classNames2.loadingDots, children: [
26565
- /* @__PURE__ */ jsx9("div", { className: classNames2.loadingDot }),
26566
- /* @__PURE__ */ jsx9("div", { className: classNames2.loadingDot, "data-delay": "1" }),
26567
- /* @__PURE__ */ jsx9("div", { className: classNames2.loadingDot, "data-delay": "2" })
27333
+ status === "streaming" && /* @__PURE__ */ jsx17("div", { className: classNames2.loadingContainer, children: /* @__PURE__ */ jsx17("div", { className: classNames2.loadingBubble, children: /* @__PURE__ */ jsxs15("div", { className: classNames2.loadingDots, children: [
27334
+ /* @__PURE__ */ jsx17("div", { className: classNames2.loadingDot }),
27335
+ /* @__PURE__ */ jsx17("div", { className: classNames2.loadingDot, "data-delay": "1" }),
27336
+ /* @__PURE__ */ jsx17("div", { className: classNames2.loadingDot, "data-delay": "2" })
26568
27337
  ] }) }) }),
26569
- /* @__PURE__ */ jsx9("div", { ref: messagesEndRef })
27338
+ /* @__PURE__ */ jsx17("div", { ref: messagesEndRef })
26570
27339
  ]
26571
27340
  }
26572
27341
  ),
26573
- /* @__PURE__ */ jsx9("div", { className: classNames2.inputContainer, children: /* @__PURE__ */ jsxs8("form", { onSubmit: handleSubmit, className: classNames2.inputForm, children: [
26574
- /* @__PURE__ */ jsx9(
27342
+ /* @__PURE__ */ jsx17("div", { className: classNames2.inputContainer, children: /* @__PURE__ */ jsxs15("form", { onSubmit: handleSubmit, className: classNames2.inputForm, children: [
27343
+ /* @__PURE__ */ jsx17(
26575
27344
  "textarea",
26576
27345
  {
26577
27346
  ref: textareaRef,
@@ -26579,12 +27348,12 @@ var ChatWidget = forwardRef(function ChatWidget2({
26579
27348
  onChange: (e) => setInput(e.target.value),
26580
27349
  onKeyDown: handleKeyDown,
26581
27350
  placeholder: inputPlaceholder,
26582
- disabled: status !== "ready",
27351
+ disabled: isInputDisabled,
26583
27352
  rows: 1,
26584
27353
  className: classNames2.textarea
26585
27354
  }
26586
27355
  ),
26587
- /* @__PURE__ */ jsx9("div", { className: classNames2.toolbar, children: speechEnabled && /* @__PURE__ */ jsx9(
27356
+ /* @__PURE__ */ jsx17("div", { className: classNames2.toolbar, children: speechEnabled && /* @__PURE__ */ jsx17(
26588
27357
  SpeechToTextButton,
26589
27358
  {
26590
27359
  className: classNames2.micButton,
@@ -26598,32 +27367,49 @@ var ChatWidget = forwardRef(function ChatWidget2({
26598
27367
  onListeningChange: setIsMicActive
26599
27368
  }
26600
27369
  ) }),
26601
- /* @__PURE__ */ jsx9(
27370
+ /* @__PURE__ */ jsx17(
26602
27371
  "button",
26603
27372
  {
26604
27373
  type: "button",
26605
27374
  onClick: status === "streaming" ? stop : handleSendMessage,
26606
- disabled: status === "streaming" ? false : !input.trim() || status !== "ready",
27375
+ disabled: status === "streaming" ? false : !input.trim() || isInputDisabled,
26607
27376
  className: classNames2.submitButton,
26608
- children: status === "streaming" ? /* @__PURE__ */ jsx9(StopCircle, { className: classNames2.sendIcon }) : /* @__PURE__ */ jsx9(Send, { className: classNames2.sendIcon })
27377
+ children: status === "streaming" ? /* @__PURE__ */ jsx17(StopCircle, { className: classNames2.sendIcon }) : /* @__PURE__ */ jsx17(Send, { className: classNames2.sendIcon })
26609
27378
  }
26610
27379
  )
26611
- ] }) })
27380
+ ] }) }),
27381
+ pendingToolOutput && /* @__PURE__ */ jsx17(
27382
+ InputFormOverlay,
27383
+ {
27384
+ args: pendingToolOutput.args,
27385
+ onComplete: handleToolOutput
27386
+ }
27387
+ ),
27388
+ pendingToolApproval && /* @__PURE__ */ jsx17(
27389
+ ToolApprovalOverlay,
27390
+ {
27391
+ approval: pendingToolApproval,
27392
+ config: approvalConfig,
27393
+ configLoading: approvalConfigLoading,
27394
+ onApprove: () => handleToolApproval(true),
27395
+ onDeny: (reason) => handleToolApproval(false, reason)
27396
+ }
27397
+ )
26612
27398
  ]
26613
27399
  }
26614
27400
  );
26615
27401
  });
26616
27402
 
26617
27403
  // lib/chat/PopupChatWidget.css
26618
- styleInject(".chat-popup__anchor {\n position: fixed;\n inset-block-end: 20px;\n inset-inline-end: 20px;\n}\n.chat-popup--start {\n inset-inline-end: auto;\n inset-inline-start: 20px;\n}\n.chat-popup__anchor-button {\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: 0 10px 25px rgba(15, 23, 42, 0.2);\n cursor: pointer;\n font-weight: 600;\n z-index: 99999;\n}\n.chat-popup__anchor-button:hover {\n background: var(--chat-primary-hover);\n}\n.chat-popup__anchor-icon {\n width: 1.1rem;\n height: 1.1rem;\n}\n.chat-popup__panel {\n position: fixed;\n inset-block-end: 20px;\n inset-inline-end: 20px;\n z-index: 99998;\n transition: opacity 0.15s ease, visibility 0.15s ease;\n}\n.chat-popup--start.chat-popup__panel {\n inset-inline-end: auto;\n inset-inline-start: 20px;\n}\n.chat-popup__panel--open {\n opacity: 1;\n visibility: visible;\n pointer-events: auto;\n}\n.chat-popup__panel--closed {\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n}\n.chat-popup__panel-inner {\n width: 384px;\n max-width: calc(100vw - 40px);\n height: 500px;\n max-height: calc(100vh - 140px);\n box-shadow: 0 20px 45px rgba(15, 23, 42, 0.12);\n border-radius: 12px;\n overflow: visible;\n background: var(--chat-background);\n border: 1px solid var(--chat-border);\n position: relative;\n}\n.chat-popup__close {\n position: absolute;\n top: 0;\n z-index: 10;\n transform: translate(30%, -40%);\n}\n.chat-popup__close--end {\n inset-inline-end: 0;\n}\n.chat-popup__close--start {\n inset-inline-start: 0;\n}\n.chat-popup__close-button {\n border: none;\n background: var(--chat-primary);\n color: var(--chat-primary-text);\n width: 32px;\n height: 32px;\n border-radius: 999px;\n cursor: pointer;\n display: grid;\n place-items: center;\n box-shadow: 0 10px 25px rgba(15, 23, 42, 0.2);\n}\n.chat-popup__close-button:hover {\n background: var(--chat-primary-hover);\n}\n.chat-popup__close-icon {\n width: 16px;\n height: 16px;\n}\n");
27404
+ styleInject(".chat-popup__anchor {\n position: fixed;\n inset-block-end: 20px;\n inset-inline-end: 20px;\n}\n.chat-popup--start {\n inset-inline-end: auto;\n inset-inline-start: 20px;\n}\n.chat-popup__anchor-button {\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-popup__anchor-button:hover {\n background: var(--chat-primary-hover);\n}\n.chat-popup__anchor-icon {\n width: 1.1rem;\n height: 1.1rem;\n}\n.chat-popup__panel {\n position: fixed;\n inset-block-end: 20px;\n inset-inline-end: 20px;\n z-index: 99998;\n transition: opacity 0.15s ease, visibility 0.15s ease;\n}\n.chat-popup--start.chat-popup__panel {\n inset-inline-end: auto;\n inset-inline-start: 20px;\n}\n.chat-popup__panel--open {\n opacity: 1;\n visibility: visible;\n pointer-events: auto;\n}\n.chat-popup__panel--closed {\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n}\n.chat-popup__panel-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: visible;\n background: var(--chat-background);\n border: 1px solid var(--chat-border);\n position: relative;\n}\n.chat-popup__close {\n position: absolute;\n top: 0;\n z-index: 10;\n transform: translate(30%, -40%);\n}\n.chat-popup__close--end {\n inset-inline-end: 0;\n}\n.chat-popup__close--start {\n inset-inline-start: 0;\n}\n.chat-popup__close-button {\n border: none;\n background: var(--chat-primary);\n color: var(--chat-primary-text);\n width: 32px;\n height: 32px;\n border-radius: 999px;\n cursor: pointer;\n display: grid;\n place-items: center;\n box-shadow: var(--chat-shadow);\n}\n.chat-popup__close-button:hover {\n background: var(--chat-primary-hover);\n}\n.chat-popup__close-icon {\n width: 16px;\n height: 16px;\n}\n");
26619
27405
 
26620
27406
  // lib/chat/PopupChatWidget.tsx
26621
27407
  import { MessageSquare as MessageSquare2, X } from "lucide-react";
26622
- import { useEffect as useEffect7, useMemo as useMemo6, useState as useState8 } from "react";
26623
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
27408
+ import { useEffect as useEffect7, useMemo as useMemo6, useState as useState10 } from "react";
27409
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
26624
27410
  function PopupChatWidget({ anchor, ...props }) {
26625
- const [isOpen, setIsOpen] = useState8(anchor?.initiallyOpen ?? false);
26626
- const [hasOpened, setHasOpened] = useState8(anchor?.initiallyOpen ?? false);
27411
+ const [isOpen, setIsOpen] = useState10(anchor?.initiallyOpen ?? false);
27412
+ const [hasOpened, setHasOpened] = useState10(anchor?.initiallyOpen ?? false);
26627
27413
  const openResolved = props.openOverride ?? isOpen;
26628
27414
  useEffect7(() => {
26629
27415
  if (props.openOverride === void 0) return;
@@ -26677,8 +27463,8 @@ function PopupChatWidget({ anchor, ...props }) {
26677
27463
  maxHeight: size.maxHeight ?? "calc(100vh - 140px)"
26678
27464
  };
26679
27465
  }, [props.popupSize]);
26680
- return /* @__PURE__ */ jsxs9("div", { style: themeStyle, children: [
26681
- /* @__PURE__ */ jsx10("div", { className: cn("chat-popup__anchor", anchorPositionClass), children: anchor?.render ? anchor.render({ isOpen: openResolved, toggle: handleToggle }) : !openResolved && /* @__PURE__ */ jsxs9(
27466
+ return /* @__PURE__ */ jsxs16("div", { style: themeStyle, children: [
27467
+ /* @__PURE__ */ jsx18("div", { className: cn("chat-popup__anchor", anchorPositionClass), children: anchor?.render ? anchor.render({ isOpen: openResolved, toggle: handleToggle }) : !openResolved && /* @__PURE__ */ jsxs16(
26682
27468
  "button",
26683
27469
  {
26684
27470
  type: "button",
@@ -26687,12 +27473,12 @@ function PopupChatWidget({ anchor, ...props }) {
26687
27473
  "aria-expanded": isOpen,
26688
27474
  "aria-label": anchor?.label ?? "Open chat",
26689
27475
  children: [
26690
- /* @__PURE__ */ jsx10(MessageSquare2, { className: "chat-popup__anchor-icon" }),
26691
- /* @__PURE__ */ jsx10("span", { children: anchor?.label ?? "Chat" })
27476
+ /* @__PURE__ */ jsx18(MessageSquare2, { className: "chat-popup__anchor-icon" }),
27477
+ /* @__PURE__ */ jsx18("span", { children: anchor?.label ?? "Chat" })
26692
27478
  ]
26693
27479
  }
26694
27480
  ) }),
26695
- /* @__PURE__ */ jsx10(
27481
+ /* @__PURE__ */ jsx18(
26696
27482
  "div",
26697
27483
  {
26698
27484
  className: cn(
@@ -26700,87 +27486,68 @@ function PopupChatWidget({ anchor, ...props }) {
26700
27486
  anchorPositionClass,
26701
27487
  openResolved ? "chat-popup__panel--open" : "chat-popup__panel--closed"
26702
27488
  ),
26703
- children: /* @__PURE__ */ jsxs9("div", { className: "chat-popup__panel-inner", style: popupStyle, children: [
26704
- showClose && /* @__PURE__ */ jsx10(
27489
+ children: /* @__PURE__ */ jsxs16("div", { className: "chat-popup__panel-inner", style: popupStyle, children: [
27490
+ showClose && /* @__PURE__ */ jsx18(
26705
27491
  "div",
26706
27492
  {
26707
27493
  className: cn(
26708
27494
  "chat-popup__close",
26709
27495
  closeConfig?.position === "top-start" ? "chat-popup__close--start" : "chat-popup__close--end"
26710
27496
  ),
26711
- children: closeConfig?.render ? closeConfig.render({ toggle: handleToggle }) : /* @__PURE__ */ jsx10(
27497
+ children: closeConfig?.render ? closeConfig.render({ toggle: handleToggle }) : /* @__PURE__ */ jsx18(
26712
27498
  "button",
26713
27499
  {
26714
27500
  type: "button",
26715
27501
  className: "chat-popup__close-button",
26716
27502
  onClick: handleToggle,
26717
27503
  "aria-label": "Close chat",
26718
- children: /* @__PURE__ */ jsx10(X, { className: "chat-popup__close-icon" })
27504
+ children: /* @__PURE__ */ jsx18(X, { className: "chat-popup__close-icon" })
26719
27505
  }
26720
27506
  )
26721
27507
  }
26722
27508
  ),
26723
- hasOpened && /* @__PURE__ */ jsx10(ChatWidget, { ...props })
27509
+ hasOpened && /* @__PURE__ */ jsx18(ChatWidget, { ...props })
26724
27510
  ] })
26725
27511
  }
26726
27512
  )
26727
27513
  ] });
26728
27514
  }
26729
27515
 
26730
- // lib/chat/widgets/VendorCards.tsx
27516
+ // lib/chat/widgets/HybridVendorCards.tsx
26731
27517
  import { MessageSquare as MessageSquare3, MessageSquareText as MessageSquareText2, ThumbsDown as ThumbsDown2, ThumbsUp as ThumbsUp2 } from "lucide-react";
26732
- import React8 from "react";
26733
- import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
26734
- var vendorCardsSchema = jsonSchema({
26735
- type: "object",
26736
- description: "displaying a list of vendor cards. Use this widget to represent data from CareNetwork vendor search tool.",
26737
- properties: {
26738
- // fromLocation: {
26739
- // type: 'string',
26740
- // description: 'The location the user is searching for',
26741
- // },
26742
- // fromCoordinates: {
26743
- // type: 'object',
26744
- // description: "The location's lat/lng coordinates. This must come from the previous geocoding tool as-is - do NOT guess",
26745
- // properties: {
26746
- // latitude: { type: 'number' },
26747
- // longitude: { type: 'number' },
26748
- // },
26749
- // required: ['latitude', 'longitude'],
26750
- // },
26751
- vendors: {
26752
- type: "array",
26753
- items: {
26754
- type: "object",
26755
- properties: {
26756
- vendor_id: { type: "string" }
26757
- // notes: {
26758
- // type: 'string',
26759
- // description: 'Give 7-10 words on why this vendor was recommended. Only include the notes for the top 3 vendors',
26760
- // },
26761
- // vendorCoordinates: {
26762
- // type: 'object',
26763
- // description: "The lat/lng coordinates of this vendor. This must come from the vendor's location.coordinates from the previous vendor search tool - do NOT guess",
26764
- // properties: {
26765
- // latitude: { type: 'number' },
26766
- // longitude: { type: 'number' },
26767
- // },
26768
- // required: ['latitude', 'longitude'],
26769
- // },
26770
- },
26771
- required: ["vendor_id"]
26772
- // required: ['vendor_id', 'vendorCoordinates'],
26773
- }
26774
- // description: '5-7 vendors to display. With notes for the top 3 only',
26775
- }
26776
- },
26777
- required: ["vendors"]
26778
- // required: ['fromLocation', 'fromCoordinates', 'vendors'],
26779
- });
26780
- function VendorCards({ payload, enriched, onAddToList, onFeedback, existingFeedback }) {
26781
- const [feedbackState, setFeedbackState] = React8.useState({});
26782
- const initializedRef = React8.useRef(false);
26783
- React8.useEffect(() => {
27518
+ import { useEffect as useEffect8, useMemo as useMemo7, useRef as useRef6, useState as useState11 } from "react";
27519
+ import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
27520
+ var vendorCardsHybridSchema = zod_default.object({
27521
+ fromLocation: zod_default.string().describe("The location the user is searching from"),
27522
+ fromCoordinates: zod_default.object({
27523
+ latitude: zod_default.number(),
27524
+ longitude: zod_default.number()
27525
+ }).describe("The user's lat/lng coordinates from geocoding"),
27526
+ vendors: zod_default.array(zod_default.object({
27527
+ vendor_id: zod_default.string(),
27528
+ notes: zod_default.string().optional().describe("7-10 words on why this vendor was recommended. Be brief and concise - do not include unecessary details such as vendor names.")
27529
+ }))
27530
+ }).describe("Display vendor cards. Only vendor IDs needed - details enriched server-side, distances fetched client-side.");
27531
+ function HybridVendorCards({
27532
+ payload,
27533
+ serverEnriched,
27534
+ distanceMatrixToolId,
27535
+ invokeTool,
27536
+ messageContext
27537
+ }) {
27538
+ const [distanceMatrix, setDistanceMatrix] = useState11();
27539
+ const [loadingDistance, setLoadingDistance] = useState11(true);
27540
+ const [feedbackState, setFeedbackState] = useState11({});
27541
+ const hasFetchedRef = useRef6(false);
27542
+ const initializedRef = useRef6(false);
27543
+ const vendorIds = useMemo7(
27544
+ () => payload.vendors.map((v) => v.vendor_id).join(","),
27545
+ [payload.vendors]
27546
+ );
27547
+ const originKey = `${payload.fromCoordinates.latitude},${payload.fromCoordinates.longitude}`;
27548
+ const hasVendorDetails = serverEnriched.vendorDetails?.success ?? false;
27549
+ const existingFeedback = messageContext?.getFeedback?.()?.notes;
27550
+ useEffect8(() => {
26784
27551
  if (!initializedRef.current && existingFeedback && existingFeedback.length > 0) {
26785
27552
  initializedRef.current = true;
26786
27553
  const initialState = {};
@@ -26796,6 +27563,44 @@ function VendorCards({ payload, enriched, onAddToList, onFeedback, existingFeedb
26796
27563
  setFeedbackState(initialState);
26797
27564
  }
26798
27565
  }, [existingFeedback]);
27566
+ useEffect8(() => {
27567
+ if (hasFetchedRef.current) {
27568
+ return;
27569
+ }
27570
+ if (!invokeTool || !hasVendorDetails) {
27571
+ setLoadingDistance(false);
27572
+ return;
27573
+ }
27574
+ const fetchDistance = async () => {
27575
+ hasFetchedRef.current = true;
27576
+ try {
27577
+ const vendorDetails = serverEnriched.vendorDetails?.data;
27578
+ const destinations = payload.vendors.map((v) => {
27579
+ const detail = vendorDetails?.[v.vendor_id];
27580
+ return detail?.location?.coordinates ?? null;
27581
+ }).filter(Boolean);
27582
+ if (destinations.length === 0) {
27583
+ setLoadingDistance(false);
27584
+ return;
27585
+ }
27586
+ const distanceResult = await invokeTool(distanceMatrixToolId, {
27587
+ args: {
27588
+ origin: payload.fromCoordinates,
27589
+ destinations
27590
+ }
27591
+ });
27592
+ setDistanceMatrix(
27593
+ distanceResult.success ? { success: true, data: distanceResult.data } : { success: false }
27594
+ );
27595
+ } catch (error48) {
27596
+ console.warn("[HybridVendorCards] Distance fetch failed:", error48);
27597
+ setDistanceMatrix({ success: false });
27598
+ } finally {
27599
+ setLoadingDistance(false);
27600
+ }
27601
+ };
27602
+ fetchDistance();
27603
+ }, [invokeTool, vendorIds, originKey, hasVendorDetails, distanceMatrixToolId, payload, serverEnriched]);
26799
27604
  const getFeedbackState = (vendorId) => {
26800
27605
  return feedbackState[vendorId] || { rating: null, commentText: null, showComment: false };
26801
27606
  };
@@ -26807,52 +27612,63 @@ function VendorCards({ payload, enriched, onAddToList, onFeedback, existingFeedb
26807
27612
  };
26808
27613
  const removeFeedbackState = (vendorId) => {
26809
27614
  setFeedbackState((prev) => {
26810
- const { [vendorId]: _, ...rest } = prev;
27615
+ const { [vendorId]: _removed, ...rest } = prev;
27616
+ void _removed;
26811
27617
  return rest;
26812
27618
  });
26813
27619
  };
26814
- const { vendorDetails, distanceMatrix } = enriched || {};
26815
- const vendorData = vendorDetails?.data ?? {};
26816
- const distances = distanceMatrix?.data ?? [];
27620
+ const handleFeedback = (noteId, feedbackPayload) => {
27621
+ messageContext?.submitFeedback?.({
27622
+ notes: [{
27623
+ noteId,
27624
+ ...feedbackPayload
27625
+ }]
27626
+ });
27627
+ };
26817
27628
  const formatDistance = (meters) => {
26818
27629
  const miles = meters / 1609.34;
26819
27630
  return miles < 0.1 ? "< 0.1 mi" : `${miles.toFixed(1)} mi`;
26820
27631
  };
26821
- return /* @__PURE__ */ jsx11("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: payload.vendors.map((v, index) => {
26822
- const data = vendorData[v.vendor_id];
26823
- const name21 = data?.names?.[0]?.value ?? "Unknown";
26824
- const address = data?.location?.address;
26825
- const distanceEntry = distances.find((d) => d.destinationIndex === index);
26826
- const distance = distanceEntry && distanceEntry.distanceMeters ? formatDistance(distanceEntry.distanceMeters) : void 0;
26827
- const hourlyRate = data?.financials?.fees?.find((f) => f.fee_type?.includes("Hourly"))?.amount;
26828
- const avgRating = data?.avg_rating;
26829
- const reviewCount = data?.review_count;
26830
- const booleans = data?.booleans;
26831
- const verification = data?.verification;
26832
- const cnScore = data?.quality_scores?.completeness_score;
26833
- const subtypes = data?.subtype ?? [];
26834
- const careLocationType = subtypes.includes("In-Home") ? "In-Home" : subtypes.includes("In-Center") ? "In-Center" : null;
26835
- const backgroundCheckStatus = data?.references_and_background_check?.background_check_status?.toLowerCase();
26836
- const hasBackgroundCheck = backgroundCheckStatus === "clear" || backgroundCheckStatus === "completed";
26837
- return /* @__PURE__ */ jsxs10(
26838
- "div",
26839
- {
26840
- style: {
26841
- display: "flex",
26842
- flexDirection: "column",
26843
- gap: "0.2rem",
26844
- padding: "1rem",
26845
- background: "#ffffff",
26846
- border: "1px solid #e5e7eb",
26847
- borderRadius: "0.5rem",
26848
- boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.1)",
26849
- fontSize: "0.875rem",
26850
- position: "relative"
26851
- },
26852
- children: [
26853
- /* @__PURE__ */ jsxs10("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start" }, children: [
26854
- /* @__PURE__ */ jsxs10("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
26855
- /* @__PURE__ */ jsx11("div", { style: {
27632
+ if (!serverEnriched || !serverEnriched.vendorDetails) {
27633
+ return /* @__PURE__ */ jsx19("div", { children: "Loading vendor details..." });
27634
+ }
27635
+ const vendorData = serverEnriched.vendorDetails?.data ?? {};
27636
+ const distances = distanceMatrix?.data ?? [];
27637
+ return /* @__PURE__ */ jsxs17("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
27638
+ loadingDistance && /* @__PURE__ */ jsx19("style", { children: `@keyframes hybrid-vendor-cards-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }` }),
27639
+ payload.vendors.map((v, index) => {
27640
+ const data = vendorData[v.vendor_id];
27641
+ const name21 = data?.names?.[0]?.value ?? "Unknown";
27642
+ const address = data?.location?.address;
27643
+ const distanceEntry = distances.find((d) => d.destinationIndex === index);
27644
+ const distance = distanceEntry && distanceEntry.distanceMeters ? formatDistance(distanceEntry.distanceMeters) : void 0;
27645
+ const hourlyRate = data?.financials?.fees?.find((f) => f.fee_type?.includes("Hourly"))?.amount;
27646
+ const avgRating = data?.avg_rating;
27647
+ const reviewCount = data?.review_count;
27648
+ const verification = data?.verification;
27649
+ const cnScore = data?.quality_scores?.completeness_score;
27650
+ const subtypes = data?.subtype ?? [];
27651
+ const careLocationType = subtypes.includes("In-Home") ? "In-Home" : subtypes.includes("In-Center") ? "In-Center" : null;
27652
+ const backgroundCheckStatus = data?.references_and_background_check?.background_check_status?.toLowerCase();
27653
+ const hasBackgroundCheck = backgroundCheckStatus === "clear" || backgroundCheckStatus === "completed";
27654
+ return /* @__PURE__ */ jsxs17(
27655
+ "div",
27656
+ {
27657
+ style: {
27658
+ display: "flex",
27659
+ flexDirection: "column",
27660
+ gap: "0.2rem",
27661
+ padding: "1rem",
27662
+ background: "#ffffff",
27663
+ border: "1px solid #e5e7eb",
27664
+ borderRadius: "0.5rem",
27665
+ boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.1)",
27666
+ fontSize: "0.875rem",
27667
+ position: "relative"
27668
+ },
27669
+ children: [
27670
+ /* @__PURE__ */ jsx19("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start" }, children: /* @__PURE__ */ jsxs17("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
27671
+ /* @__PURE__ */ jsx19("div", { style: {
26856
27672
  width: "2rem",
26857
27673
  height: "2rem",
26858
27674
  borderRadius: "9999px",
@@ -26864,163 +27680,111 @@ function VendorCards({ payload, enriched, onAddToList, onFeedback, existingFeedb
26864
27680
  fontSize: "0.875rem",
26865
27681
  color: "#374151"
26866
27682
  }, children: name21.charAt(0).toUpperCase() }),
26867
- /* @__PURE__ */ jsx11("span", { style: { fontWeight: 600, fontSize: "1rem", color: "#111827" }, children: name21 })
27683
+ /* @__PURE__ */ jsx19("span", { style: { fontWeight: 600, fontSize: "1rem", color: "#111827" }, children: name21 })
27684
+ ] }) }),
27685
+ (reviewCount != null || cnScore != null) && /* @__PURE__ */ jsxs17("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem", color: "#6b7280" }, children: [
27686
+ avgRating != null && /* @__PURE__ */ jsxs17(Fragment6, { children: [
27687
+ /* @__PURE__ */ jsx19("span", { style: { color: "#facc15" }, children: "\u2605" }),
27688
+ /* @__PURE__ */ jsx19("span", { children: avgRating.toFixed(1) }),
27689
+ reviewCount != null && /* @__PURE__ */ jsxs17("span", { style: { color: "#9ca3af" }, children: [
27690
+ "(",
27691
+ reviewCount,
27692
+ " reviews)"
27693
+ ] })
27694
+ ] }),
27695
+ avgRating != null && cnScore != null ? /* @__PURE__ */ jsx19("span", { style: { color: "#9ca3af" }, children: "\u2022" }) : null,
27696
+ cnScore != null ? /* @__PURE__ */ jsxs17("span", { children: [
27697
+ "CN Score: ",
27698
+ cnScore
27699
+ ] }) : null
26868
27700
  ] }),
26869
- onAddToList && /* @__PURE__ */ jsx11(
26870
- "button",
26871
- {
26872
- onClick: () => onAddToList(v.vendor_id),
26873
- style: {
26874
- background: "none",
26875
- border: "none",
26876
- color: "#3b82f6",
26877
- fontSize: "0.875rem",
26878
- cursor: "pointer",
26879
- padding: 0
26880
- },
26881
- children: "Add to list"
26882
- }
26883
- )
26884
- ] }),
26885
- (reviewCount != null || cnScore != null) && /* @__PURE__ */ jsxs10("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem", color: "#6b7280" }, children: [
26886
- avgRating != null && /* @__PURE__ */ jsxs10(Fragment5, { children: [
26887
- /* @__PURE__ */ jsx11("span", { style: { color: "#facc15" }, children: "\u2605" }),
26888
- /* @__PURE__ */ jsx11("span", { children: avgRating.toFixed(1) }),
26889
- reviewCount != null && /* @__PURE__ */ jsxs10("span", { style: { color: "#9ca3af" }, children: [
26890
- "(",
26891
- reviewCount,
26892
- " reviews)"
27701
+ careLocationType && /* @__PURE__ */ jsx19("div", { style: { color: "#6b7280" }, children: careLocationType }),
27702
+ address && /* @__PURE__ */ jsx19("div", { style: { color: "#6b7280" }, children: address }),
27703
+ /* @__PURE__ */ jsx19("div", { style: { display: "flex", alignItems: "center", gap: "0.25rem", color: "#6b7280", minHeight: "1.25rem" }, children: loadingDistance ? /* @__PURE__ */ jsxs17(Fragment6, { children: [
27704
+ /* @__PURE__ */ jsx19("span", { children: "\u{1F4CD}" }),
27705
+ /* @__PURE__ */ jsx19("span", { style: {
27706
+ width: "100px",
27707
+ height: "0.875rem",
27708
+ background: "linear-gradient(90deg, #f3f4f6 25%, #e5e7eb 50%, #f3f4f6 75%)",
27709
+ backgroundSize: "200% 100%",
27710
+ animation: "hybrid-vendor-cards-shimmer 1.5s infinite",
27711
+ borderRadius: "0.25rem"
27712
+ } })
27713
+ ] }) : distance ? /* @__PURE__ */ jsxs17(Fragment6, { children: [
27714
+ /* @__PURE__ */ jsx19("span", { children: "\u{1F4CD}" }),
27715
+ /* @__PURE__ */ jsxs17("span", { children: [
27716
+ distance,
27717
+ " from ",
27718
+ payload.fromLocation
27719
+ ] })
27720
+ ] }) : null }),
27721
+ hourlyRate && /* @__PURE__ */ jsxs17("div", { style: { display: "flex", alignItems: "center", gap: "0.25rem", color: "#6b7280" }, children: [
27722
+ /* @__PURE__ */ jsx19("span", { children: "\u{1F4B0}" }),
27723
+ /* @__PURE__ */ jsxs17("span", { children: [
27724
+ "Rate: $",
27725
+ hourlyRate,
27726
+ "/hr"
26893
27727
  ] })
26894
27728
  ] }),
26895
- avgRating != null && cnScore != null ? /* @__PURE__ */ jsx11("span", { style: { color: "#9ca3af" }, children: "\u2022" }) : null,
26896
- cnScore != null ? /* @__PURE__ */ jsxs10("span", { children: [
26897
- "CN Score: ",
26898
- cnScore
26899
- ] }) : null
26900
- ] }),
26901
- careLocationType && /* @__PURE__ */ jsx11("div", { style: { color: "#6b7280" }, children: careLocationType }),
26902
- address && /* @__PURE__ */ jsx11("div", { style: { color: "#6b7280" }, children: address }),
26903
- distance && /* @__PURE__ */ jsxs10("div", { style: { display: "flex", alignItems: "center", gap: "0.25rem", color: "#6b7280" }, children: [
26904
- /* @__PURE__ */ jsx11("span", { children: "\u{1F4CD}" }),
26905
- /* @__PURE__ */ jsxs10("span", { children: [
26906
- distance,
26907
- " from ",
26908
- payload.fromLocation
26909
- ] })
26910
- ] }),
26911
- hourlyRate && /* @__PURE__ */ jsxs10("div", { style: { display: "flex", alignItems: "center", gap: "0.25rem", color: "#6b7280" }, children: [
26912
- /* @__PURE__ */ jsx11("span", { children: "\u{1F4B0}" }),
26913
- /* @__PURE__ */ jsxs10("span", { children: [
26914
- "Rate: $",
26915
- hourlyRate,
26916
- "/hr"
26917
- ] })
26918
- ] }),
26919
- v.notes && /* @__PURE__ */ jsxs10("div", { style: { color: "#374151", marginTop: "0.4rem" }, children: [
26920
- /* @__PURE__ */ jsx11("span", { style: { marginRight: "0.25rem" }, children: "\u2728" }),
26921
- /* @__PURE__ */ jsx11("strong", { children: "Recommendation notes" }),
26922
- /* @__PURE__ */ jsx11("div", { style: { marginLeft: "1.25rem", marginTop: "0.25rem", color: "#6b7280" }, children: v.notes })
26923
- ] }),
26924
- (() => {
26925
- const state = getFeedbackState(v.vendor_id);
26926
- const isPositiveSelected = state.rating === "positive";
26927
- const isNegativeSelected = state.rating === "negative";
26928
- const handleRatingClick = (rating) => {
26929
- const currentState = getFeedbackState(v.vendor_id);
26930
- if (currentState.rating === rating) {
26931
- removeFeedbackState(v.vendor_id);
26932
- onFeedback?.(v.vendor_id, {});
26933
- } else {
26934
- updateFeedbackState(v.vendor_id, { rating });
26935
- onFeedback?.(v.vendor_id, { rating, vendorId: v.vendor_id, vendorName: name21 });
26936
- }
26937
- };
26938
- const handleCommentToggle = () => {
26939
- const currentState = getFeedbackState(v.vendor_id);
26940
- updateFeedbackState(v.vendor_id, { showComment: !currentState.showComment });
26941
- };
26942
- const handleCommentSubmit = () => {
26943
- const currentState = getFeedbackState(v.vendor_id);
26944
- const trimmedComment = currentState.commentText?.trim();
26945
- if (trimmedComment) {
26946
- updateFeedbackState(v.vendor_id, { showComment: false, commentText: trimmedComment });
26947
- onFeedback?.(v.vendor_id, { comment: trimmedComment, vendorId: v.vendor_id, vendorName: name21 });
26948
- }
26949
- };
26950
- return /* @__PURE__ */ jsxs10(Fragment5, { children: [
26951
- /* @__PURE__ */ jsxs10("div", { style: {
26952
- display: "flex",
26953
- flexWrap: "wrap",
26954
- gap: "0.5rem",
26955
- // marginTop: '0.25rem',
26956
- alignItems: "center",
26957
- minHeight: "1.75rem"
26958
- }, children: [
26959
- verification?.verified && /* @__PURE__ */ jsxs10("span", { style: { display: "flex", alignItems: "center", gap: "0.25rem", color: "#22c55e", fontSize: "0.75rem" }, children: [
26960
- /* @__PURE__ */ jsx11("span", { style: { fontSize: "0.875rem" }, children: "\u2713" }),
26961
- " Wellthy Verified"
26962
- ] }),
26963
- hasBackgroundCheck && /* @__PURE__ */ jsxs10("span", { style: { display: "flex", alignItems: "center", gap: "0.25rem", color: "#22c55e", fontSize: "0.75rem" }, children: [
26964
- /* @__PURE__ */ jsx11("span", { style: { fontSize: "0.875rem" }, children: "\u2713" }),
26965
- " Background check"
26966
- ] }),
26967
- onFeedback && /* @__PURE__ */ jsxs10("div", { style: {
26968
- marginLeft: "auto",
27729
+ v.notes && /* @__PURE__ */ jsxs17("div", { style: { color: "#374151", marginTop: "0.4rem" }, children: [
27730
+ /* @__PURE__ */ jsx19("span", { style: { marginRight: "0.25rem" }, children: "\u2728" }),
27731
+ /* @__PURE__ */ jsx19("strong", { children: "Recommendation notes" }),
27732
+ /* @__PURE__ */ jsx19("div", { style: { marginLeft: "1.25rem", marginTop: "0.25rem", color: "#6b7280" }, children: v.notes })
27733
+ ] }),
27734
+ (() => {
27735
+ const state = getFeedbackState(v.vendor_id);
27736
+ const isPositiveSelected = state.rating === "positive";
27737
+ const isNegativeSelected = state.rating === "negative";
27738
+ const handleRatingClick = (rating) => {
27739
+ const currentState = getFeedbackState(v.vendor_id);
27740
+ if (currentState.rating === rating) {
27741
+ removeFeedbackState(v.vendor_id);
27742
+ handleFeedback(v.vendor_id, {});
27743
+ } else {
27744
+ updateFeedbackState(v.vendor_id, { rating });
27745
+ handleFeedback(v.vendor_id, { rating, vendorId: v.vendor_id, vendorName: name21 });
27746
+ }
27747
+ };
27748
+ const handleCommentToggle = () => {
27749
+ const currentState = getFeedbackState(v.vendor_id);
27750
+ updateFeedbackState(v.vendor_id, { showComment: !currentState.showComment });
27751
+ };
27752
+ const handleCommentSubmit = () => {
27753
+ const currentState = getFeedbackState(v.vendor_id);
27754
+ const trimmedComment = currentState.commentText?.trim();
27755
+ if (trimmedComment) {
27756
+ updateFeedbackState(v.vendor_id, { showComment: false, commentText: trimmedComment });
27757
+ handleFeedback(v.vendor_id, { comment: trimmedComment, vendorId: v.vendor_id, vendorName: name21 });
27758
+ }
27759
+ };
27760
+ return /* @__PURE__ */ jsxs17(Fragment6, { children: [
27761
+ /* @__PURE__ */ jsxs17("div", { style: {
26969
27762
  display: "flex",
26970
- gap: "0.25rem",
26971
- alignItems: "center"
27763
+ flexWrap: "wrap",
27764
+ gap: "0.5rem",
27765
+ alignItems: "center",
27766
+ minHeight: "1.75rem"
26972
27767
  }, children: [
26973
- /* @__PURE__ */ jsx11(
26974
- "button",
26975
- {
26976
- onClick: () => handleRatingClick("positive"),
26977
- style: {
26978
- background: isPositiveSelected ? "rgba(34, 197, 94, 0.1)" : "transparent",
26979
- border: "none",
26980
- borderRadius: "0.35rem",
26981
- padding: "0.25rem",
26982
- cursor: "pointer",
26983
- display: "flex",
26984
- alignItems: "center",
26985
- justifyContent: "center",
26986
- color: isPositiveSelected ? "#22c55e" : "#9ca3af",
26987
- width: "1.75rem",
26988
- height: "1.75rem"
26989
- },
26990
- title: "This vendor was helpful",
26991
- children: /* @__PURE__ */ jsx11(ThumbsUp2, { style: { width: "1rem", height: "1rem" } })
26992
- }
26993
- ),
26994
- /* @__PURE__ */ jsx11(
26995
- "button",
26996
- {
26997
- onClick: () => handleRatingClick("negative"),
26998
- style: {
26999
- background: isNegativeSelected ? "rgba(239, 68, 68, 0.1)" : "transparent",
27000
- border: "none",
27001
- borderRadius: "0.35rem",
27002
- padding: "0.25rem",
27003
- cursor: "pointer",
27004
- display: "flex",
27005
- alignItems: "center",
27006
- justifyContent: "center",
27007
- color: isNegativeSelected ? "#ef4444" : "#9ca3af",
27008
- width: "1.75rem",
27009
- height: "1.75rem"
27010
- },
27011
- title: "This vendor was not helpful",
27012
- children: /* @__PURE__ */ jsx11(ThumbsDown2, { style: { width: "1rem", height: "1rem" } })
27013
- }
27014
- ),
27015
- (() => {
27016
- const hasComment = !!state.commentText?.trim();
27017
- const CommentIcon = hasComment ? MessageSquareText2 : MessageSquare3;
27018
- return /* @__PURE__ */ jsx11(
27768
+ verification?.verified && /* @__PURE__ */ jsxs17("span", { style: { display: "flex", alignItems: "center", gap: "0.25rem", color: "#22c55e", fontSize: "0.75rem" }, children: [
27769
+ /* @__PURE__ */ jsx19("span", { style: { fontSize: "0.875rem" }, children: "\u2713" }),
27770
+ " Wellthy Verified"
27771
+ ] }),
27772
+ hasBackgroundCheck && /* @__PURE__ */ jsxs17("span", { style: { display: "flex", alignItems: "center", gap: "0.25rem", color: "#22c55e", fontSize: "0.75rem" }, children: [
27773
+ /* @__PURE__ */ jsx19("span", { style: { fontSize: "0.875rem" }, children: "\u2713" }),
27774
+ " Background check"
27775
+ ] }),
27776
+ messageContext && /* @__PURE__ */ jsxs17("div", { style: {
27777
+ marginLeft: "auto",
27778
+ display: "flex",
27779
+ gap: "0.25rem",
27780
+ alignItems: "center"
27781
+ }, children: [
27782
+ /* @__PURE__ */ jsx19(
27019
27783
  "button",
27020
27784
  {
27021
- onClick: handleCommentToggle,
27785
+ onClick: () => handleRatingClick("positive"),
27022
27786
  style: {
27023
- background: state.showComment ? "rgba(0, 0, 0, 0.05)" : "transparent",
27787
+ background: isPositiveSelected ? "rgba(34, 197, 94, 0.1)" : "transparent",
27024
27788
  border: "none",
27025
27789
  borderRadius: "0.35rem",
27026
27790
  padding: "0.25rem",
@@ -27028,96 +27792,190 @@ function VendorCards({ payload, enriched, onAddToList, onFeedback, existingFeedb
27028
27792
  display: "flex",
27029
27793
  alignItems: "center",
27030
27794
  justifyContent: "center",
27031
- color: hasComment ? "#3b82f6" : state.showComment ? "#6b7280" : "#9ca3af",
27795
+ color: isPositiveSelected ? "#22c55e" : "#9ca3af",
27032
27796
  width: "1.75rem",
27033
27797
  height: "1.75rem"
27034
27798
  },
27035
- title: hasComment ? "Edit comment" : "Add comment",
27036
- children: /* @__PURE__ */ jsx11(CommentIcon, { style: { width: "1rem", height: "1rem" } })
27799
+ title: "This vendor was helpful",
27800
+ children: /* @__PURE__ */ jsx19(ThumbsUp2, { style: { width: "1rem", height: "1rem" } })
27037
27801
  }
27038
- );
27039
- })()
27040
- ] })
27041
- ] }),
27042
- state.showComment && /* @__PURE__ */ jsx11("div", { style: {
27043
- position: "absolute",
27044
- bottom: 0,
27045
- left: 0,
27046
- right: 0,
27047
- background: "#ffffff",
27048
- borderTop: "1px solid #e5e7eb",
27049
- borderRadius: "0 0 0.5rem 0.5rem",
27050
- padding: "0.75rem 1rem",
27051
- boxShadow: "0 -2px 8px rgba(0, 0, 0, 0.1)"
27052
- }, children: /* @__PURE__ */ jsxs10("div", { style: { display: "flex", gap: "0.5rem", alignItems: "flex-start" }, children: [
27053
- /* @__PURE__ */ jsx11(
27054
- "textarea",
27055
- {
27056
- placeholder: "Share your thoughts about this vendor...",
27057
- value: state.commentText ?? "",
27058
- onChange: (e) => updateFeedbackState(v.vendor_id, { commentText: e.target.value }),
27059
- rows: 2,
27060
- style: {
27061
- flex: 1,
27062
- padding: "0.5rem",
27063
- border: "1px solid #e5e7eb",
27064
- borderRadius: "0.35rem",
27065
- fontSize: "0.875rem",
27066
- fontFamily: "inherit",
27067
- resize: "none",
27068
- minHeight: "50px"
27069
- }
27070
- }
27071
- ),
27072
- /* @__PURE__ */ jsxs10("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
27073
- /* @__PURE__ */ jsx11(
27074
- "button",
27802
+ ),
27803
+ /* @__PURE__ */ jsx19(
27804
+ "button",
27805
+ {
27806
+ onClick: () => handleRatingClick("negative"),
27807
+ style: {
27808
+ background: isNegativeSelected ? "rgba(239, 68, 68, 0.1)" : "transparent",
27809
+ border: "none",
27810
+ borderRadius: "0.35rem",
27811
+ padding: "0.25rem",
27812
+ cursor: "pointer",
27813
+ display: "flex",
27814
+ alignItems: "center",
27815
+ justifyContent: "center",
27816
+ color: isNegativeSelected ? "#ef4444" : "#9ca3af",
27817
+ width: "1.75rem",
27818
+ height: "1.75rem"
27819
+ },
27820
+ title: "This vendor was not helpful",
27821
+ children: /* @__PURE__ */ jsx19(ThumbsDown2, { style: { width: "1rem", height: "1rem" } })
27822
+ }
27823
+ ),
27824
+ (() => {
27825
+ const hasComment = !!state.commentText?.trim();
27826
+ const CommentIcon = hasComment ? MessageSquareText2 : MessageSquare3;
27827
+ return /* @__PURE__ */ jsx19(
27828
+ "button",
27829
+ {
27830
+ onClick: handleCommentToggle,
27831
+ style: {
27832
+ background: state.showComment ? "rgba(0, 0, 0, 0.05)" : "transparent",
27833
+ border: "none",
27834
+ borderRadius: "0.35rem",
27835
+ padding: "0.25rem",
27836
+ cursor: "pointer",
27837
+ display: "flex",
27838
+ alignItems: "center",
27839
+ justifyContent: "center",
27840
+ color: hasComment ? "#3b82f6" : state.showComment ? "#6b7280" : "#9ca3af",
27841
+ width: "1.75rem",
27842
+ height: "1.75rem"
27843
+ },
27844
+ title: hasComment ? "Edit comment" : "Add comment",
27845
+ children: /* @__PURE__ */ jsx19(CommentIcon, { style: { width: "1rem", height: "1rem" } })
27846
+ }
27847
+ );
27848
+ })()
27849
+ ] })
27850
+ ] }),
27851
+ state.showComment && /* @__PURE__ */ jsx19("div", { style: {
27852
+ position: "absolute",
27853
+ bottom: 0,
27854
+ left: 0,
27855
+ right: 0,
27856
+ background: "#ffffff",
27857
+ borderTop: "1px solid #e5e7eb",
27858
+ borderRadius: "0 0 0.5rem 0.5rem",
27859
+ padding: "0.75rem 1rem",
27860
+ boxShadow: "0 -2px 8px rgba(0, 0, 0, 0.1)"
27861
+ }, children: /* @__PURE__ */ jsxs17("div", { style: { display: "flex", gap: "0.5rem", alignItems: "flex-start" }, children: [
27862
+ /* @__PURE__ */ jsx19(
27863
+ "textarea",
27075
27864
  {
27076
- onClick: handleCommentSubmit,
27077
- disabled: !state.commentText?.trim(),
27865
+ placeholder: "Share your thoughts about this vendor...",
27866
+ value: state.commentText ?? "",
27867
+ onChange: (e) => updateFeedbackState(v.vendor_id, { commentText: e.target.value }),
27868
+ rows: 2,
27078
27869
  style: {
27079
- padding: "0.35rem 0.75rem",
27080
- fontSize: "0.75rem",
27081
- fontWeight: 500,
27082
- borderRadius: "0.3rem",
27083
- cursor: state.commentText?.trim() ? "pointer" : "not-allowed",
27084
- background: "#3b82f6",
27085
- border: "none",
27086
- color: "#ffffff",
27087
- opacity: state.commentText?.trim() ? 1 : 0.5
27088
- },
27089
- children: "Save"
27870
+ flex: 1,
27871
+ padding: "0.5rem",
27872
+ border: "1px solid #e5e7eb",
27873
+ borderRadius: "0.35rem",
27874
+ fontSize: "0.875rem",
27875
+ fontFamily: "inherit",
27876
+ resize: "none",
27877
+ minHeight: "50px"
27878
+ }
27090
27879
  }
27091
27880
  ),
27092
- /* @__PURE__ */ jsx11(
27093
- "button",
27094
- {
27095
- onClick: handleCommentToggle,
27096
- style: {
27097
- padding: "0.25rem 0.5rem",
27098
- fontSize: "0.75rem",
27099
- fontWeight: 500,
27100
- background: "transparent",
27101
- border: "none",
27102
- color: "#9ca3af",
27103
- cursor: "pointer"
27104
- },
27105
- children: "Cancel"
27106
- }
27107
- )
27108
- ] })
27109
- ] }) })
27110
- ] });
27111
- })()
27112
- ]
27113
- },
27114
- v.vendor_id
27115
- );
27116
- }) });
27881
+ /* @__PURE__ */ jsxs17("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [
27882
+ /* @__PURE__ */ jsx19(
27883
+ "button",
27884
+ {
27885
+ onClick: handleCommentSubmit,
27886
+ disabled: !state.commentText?.trim(),
27887
+ style: {
27888
+ padding: "0.35rem 0.75rem",
27889
+ fontSize: "0.75rem",
27890
+ fontWeight: 500,
27891
+ borderRadius: "0.3rem",
27892
+ cursor: state.commentText?.trim() ? "pointer" : "not-allowed",
27893
+ background: "#3b82f6",
27894
+ border: "none",
27895
+ color: "#ffffff",
27896
+ opacity: state.commentText?.trim() ? 1 : 0.5
27897
+ },
27898
+ children: "Save"
27899
+ }
27900
+ ),
27901
+ /* @__PURE__ */ jsx19(
27902
+ "button",
27903
+ {
27904
+ onClick: handleCommentToggle,
27905
+ style: {
27906
+ padding: "0.25rem 0.5rem",
27907
+ fontSize: "0.75rem",
27908
+ fontWeight: 500,
27909
+ background: "transparent",
27910
+ border: "none",
27911
+ color: "#9ca3af",
27912
+ cursor: "pointer"
27913
+ },
27914
+ children: "Cancel"
27915
+ }
27916
+ )
27917
+ ] })
27918
+ ] }) })
27919
+ ] });
27920
+ })()
27921
+ ]
27922
+ },
27923
+ v.vendor_id
27924
+ );
27925
+ })
27926
+ ] });
27117
27927
  }
27118
27928
 
27929
+ // lib/chat/widgets/VendorCards.tsx
27930
+ import { MessageSquare as MessageSquare4, MessageSquareText as MessageSquareText3, ThumbsDown as ThumbsDown3, ThumbsUp as ThumbsUp3 } from "lucide-react";
27931
+ import React9 from "react";
27932
+ import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
27933
+ var vendorCardsSchema = jsonSchema({
27934
+ type: "object",
27935
+ description: "displaying a list of vendor cards. Use this widget to represent data from CareNetwork vendor search tool.",
27936
+ properties: {
27937
+ fromLocation: {
27938
+ type: "string",
27939
+ description: "The location the user is searching for"
27940
+ },
27941
+ fromCoordinates: {
27942
+ type: "object",
27943
+ description: "The location's lat/lng coordinates. This must come from the previous geocoding tool as-is - do NOT guess",
27944
+ properties: {
27945
+ latitude: { type: "number" },
27946
+ longitude: { type: "number" }
27947
+ },
27948
+ required: ["latitude", "longitude"]
27949
+ },
27950
+ vendors: {
27951
+ type: "array",
27952
+ items: {
27953
+ type: "object",
27954
+ properties: {
27955
+ vendor_id: { type: "string" },
27956
+ notes: {
27957
+ type: "string",
27958
+ description: "Give 7-10 words on why this vendor was recommended"
27959
+ },
27960
+ vendorCoordinates: {
27961
+ type: "object",
27962
+ description: "The lat/lng coordinates of this vendor. This must come from the vendor's location.coordinates from the previous vendor search tool - do NOT guess",
27963
+ properties: {
27964
+ latitude: { type: "number" },
27965
+ longitude: { type: "number" }
27966
+ },
27967
+ required: ["latitude", "longitude"]
27968
+ }
27969
+ },
27970
+ required: ["vendor_id", "vendorCoordinates"]
27971
+ }
27972
+ }
27973
+ },
27974
+ required: ["fromLocation", "fromCoordinates", "vendors"]
27975
+ });
27976
+
27119
27977
  // lib/chat/widgets/default-widgets.tsx
27120
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
27978
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
27121
27979
  var defaultChatWidgets = [
27122
27980
  createSDKWidget({
27123
27981
  widgetType: "person-card",
@@ -27126,7 +27984,7 @@ var defaultChatWidgets = [
27126
27984
  photoUri: zod_default.string().optional().describe("URL to a photo of the person"),
27127
27985
  details: zod_default.record(zod_default.string(), zod_default.any()).optional()
27128
27986
  }).describe("showing a person card with name, photo and additional details"),
27129
- render: (payload) => /* @__PURE__ */ jsx12(
27987
+ render: (payload) => /* @__PURE__ */ jsx21(
27130
27988
  "div",
27131
27989
  {
27132
27990
  style: {
@@ -27139,8 +27997,8 @@ var defaultChatWidgets = [
27139
27997
  borderRadius: "0.5rem",
27140
27998
  boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)"
27141
27999
  },
27142
- children: /* @__PURE__ */ jsxs11("div", { style: { display: "flex", alignItems: "flex-start", gap: "0.75rem" }, children: [
27143
- payload.photoUri && /* @__PURE__ */ jsx12(
28000
+ children: /* @__PURE__ */ jsxs19("div", { style: { display: "flex", alignItems: "flex-start", gap: "0.75rem" }, children: [
28001
+ payload.photoUri && /* @__PURE__ */ jsx21(
27144
28002
  "img",
27145
28003
  {
27146
28004
  src: payload.photoUri,
@@ -27155,14 +28013,14 @@ var defaultChatWidgets = [
27155
28013
  loading: "lazy"
27156
28014
  }
27157
28015
  ),
27158
- /* @__PURE__ */ jsxs11("div", { style: { flex: 1, minWidth: 0 }, children: [
27159
- /* @__PURE__ */ jsx12("div", { style: { fontWeight: 600, fontSize: "1rem", color: "#111827", marginBottom: "0.25rem" }, children: payload.name }),
27160
- payload.details ? /* @__PURE__ */ jsx12("div", { style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: Object.entries(payload.details).map(([key, value]) => /* @__PURE__ */ jsxs11("div", { style: { display: "flex", gap: "0.5rem", fontSize: "0.875rem" }, children: [
27161
- /* @__PURE__ */ jsxs11("span", { style: { color: "#6b7280", fontWeight: 500, minWidth: "fit-content" }, children: [
28016
+ /* @__PURE__ */ jsxs19("div", { style: { flex: 1, minWidth: 0 }, children: [
28017
+ /* @__PURE__ */ jsx21("div", { style: { fontWeight: 600, fontSize: "1rem", color: "#111827", marginBottom: "0.25rem" }, children: payload.name }),
28018
+ payload.details ? /* @__PURE__ */ jsx21("div", { style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: Object.entries(payload.details).map(([key, value]) => /* @__PURE__ */ jsxs19("div", { style: { display: "flex", gap: "0.5rem", fontSize: "0.875rem" }, children: [
28019
+ /* @__PURE__ */ jsxs19("span", { style: { color: "#6b7280", fontWeight: 500, minWidth: "fit-content" }, children: [
27162
28020
  key,
27163
28021
  ":"
27164
28022
  ] }),
27165
- /* @__PURE__ */ jsx12("span", { style: { color: "#374151" }, children: String(value) })
28023
+ /* @__PURE__ */ jsx21("span", { style: { color: "#374151" }, children: String(value) })
27166
28024
  ] }, key)) }) : null
27167
28025
  ] })
27168
28026
  ] })
@@ -27175,7 +28033,7 @@ var defaultChatWidgets = [
27175
28033
  uri: zod_default.string().url(),
27176
28034
  text: zod_default.string().optional()
27177
28035
  }).describe("rendering a clickable link"),
27178
- render: (payload) => /* @__PURE__ */ jsx12(
28036
+ render: (payload) => /* @__PURE__ */ jsx21(
27179
28037
  "a",
27180
28038
  {
27181
28039
  href: payload.uri,
@@ -27215,43 +28073,25 @@ var getVendorCardsWidget = (isProd) => {
27215
28073
  return [
27216
28074
  createSDKWidget({
27217
28075
  widgetType: "vendor-cards",
27218
- schema: vendorCardsSchema,
28076
+ schema: vendorCardsHybridSchema,
28077
+ // Server-side enrichment for vendor details (runs parallel to LLM)
27219
28078
  enrich: {
27220
- /** fetch vendor details from the list of IDs */
27221
28079
  vendorDetails: {
27222
28080
  toolId: vendorDetailsToolId,
27223
28081
  inputs: {
27224
28082
  vendorIds: "${vendors|map('vendor_id')|join(',')}"
27225
28083
  }
27226
28084
  }
27227
- /* calculate distance from user to each vendor */
27228
- // distanceMatrix: {
27229
- // toolId: distanceMatrixToolId,
27230
- // inputs: {
27231
- // origin: "${fromCoordinates}",
27232
- // destinations: "${vendors|map('vendorCoordinates')}",
27233
- // },
27234
- // }
27235
28085
  },
27236
- render: (payload, enriched, { messageContext }) => /* @__PURE__ */ jsx12(
27237
- VendorCards,
28086
+ // Client-side: fetch distance matrix progressively
28087
+ render: (payload, enriched, { messageContext, invokeTool }) => /* @__PURE__ */ jsx21(
28088
+ HybridVendorCards,
27238
28089
  {
27239
28090
  payload,
27240
- enriched,
27241
- existingFeedback: messageContext?.getFeedback?.()?.notes,
27242
- onAddToList: (vendorId) => {
27243
- window.dispatchEvent(new CustomEvent("vendor-selected", {
27244
- detail: { vendorId }
27245
- }));
27246
- },
27247
- onFeedback: (noteId, payload2) => {
27248
- messageContext?.submitFeedback?.({
27249
- notes: [{
27250
- noteId,
27251
- ...payload2
27252
- }]
27253
- });
27254
- }
28091
+ serverEnriched: enriched,
28092
+ distanceMatrixToolId,
28093
+ invokeTool,
28094
+ messageContext
27255
28095
  }
27256
28096
  )
27257
28097
  })
@@ -27272,6 +28112,7 @@ export {
27272
28112
  createSDKWidget,
27273
28113
  createWidget,
27274
28114
  defaultChatWidgets,
28115
+ fetchApprovalConfig,
27275
28116
  getVendorCardsWidget,
27276
28117
  isSDKWidget,
27277
28118
  registerChatWidgets,