@inkeep/agents-ui 0.0.0-dev-20260513213554 → 0.0.0-dev-20260514122955

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.
@@ -1,2 +1,2 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Ze=require("@ai-sdk/react"),Xe=require("./file-upload-input.cjs"),Ye=require("ai"),t=require("react"),et=require("../../providers/config-provider.cjs"),tt=require("../../providers/chat-auth-provider.cjs"),st=require("../../hooks/use-media-query.cjs"),rt=require("../../hooks/use-conversation-loader.cjs"),nt=require("../../hooks/use-initial-conversation.cjs"),T=require("../../utils/generate-uid.cjs"),at=require("../../providers/base-events-provider.cjs"),ot=require("../../providers/chat-form-provider.cjs"),it=require("../../providers/widget-provider.cjs"),ct=require("@radix-ui/react-use-controllable-state"),ut=require("../../hooks/use-streaming-events.cjs"),lt=require("../../hooks/use-input-notification.cjs"),p=require("./chat-error-helpers.cjs"),dt=()=>{const{baseSettings:se,aiChatSettings:R}=et.useInkeepConfig(),[c="",m]=ct.useControllableState({prop:R.conversationIdOverride,defaultProp:R.conversationIdOverride??""}),{logEvent:h}=at.useBaseEvents(),{setConversationId:ke,emitToParent:k}=ut.useStreamingEvents(),re=t.useRef(c);t.useEffect(()=>{const e=re.current;re.current=c,e!==c&&h({eventName:"chat_conversation_changed",properties:{conversationId:c,previousConversationId:e}})},[c,h]);const[E,S]=t.useState(""),Fe=e=>S(e.target.value),{shouldBypassCaptcha:_e,filters:ne,userProperties:N,analyticsProperties:O}=se,{authToken:ae,isAuthenticated:v,isAuthConfigured:oe,refreshAuthToken:ie,sessionToken:ce,refreshSession:ue,getCaptchaHeader:F,invalidateCaptcha:d,effectiveAuthToken:le,applicableRefreshSession:Pe}=tt.useChatAuth(),{onInputMessageChange:xe,filters:de,baseUrl:pe,agentUrl:qe,context:fe,headers:ge,appId:_,apiKey:U,files:C}=R,he=t.useRef(F);he.current=F;const me=qe||`${pe}/run/api/chat`,{loadConversation:ve}=rt.useConversationLoader({baseUrl:pe,appId:_,authToken:le,getCaptchaHeader:F,invalidateCaptcha:d,refreshSession:Pe}),[Le,ye]=t.useState(!1),D=t.useRef(null);D.current=ce;const $=t.useRef(null);$.current=ae;const B=t.useRef(void 0);B.current=N&&Object.keys(N).length>0?N:void 0;const G=t.useRef(void 0);G.current=O&&Object.keys(O).length>0?O:void 0;const y=t.useRef(0),H=t.useRef(null),K=t.useRef(null),I=t.useRef(void 0),Ne=C?.map(e=>`${e.filename??""}:${e.mediaType}:${e.url.length}:${e.url.slice(0,64)}:${e.url.slice(-32)}`).join(`
2
- `)??"";t.useEffect(()=>{I.current=C?.length?C:void 0},[Ne]);const Re=t.useRef(ge);Re.current=ge;const z=t.useRef(void 0);z.current=ne||de?JSON.stringify({...ne,...de}):void 0;const Oe=e=>{switch(p.resolveHttpStatusCode(e)){case 400:try{const s=JSON.parse(e.message??"");return s.detail??s.error?.message??p.RECOVERABLE_FALLBACK_MESSAGE}catch{return e.message?.trim()||p.RECOVERABLE_FALLBACK_MESSAGE}case 401:return oe?"Authentication failed. Please try again.":p.DEFAULT_ERROR_MESSAGE;case 403:return`There seems to be a configuration error. Please contact ${se.organizationDisplayName??"Administrator"}`;case 429:return p.RATE_LIMIT_MESSAGE;default:return p.DEFAULT_ERROR_MESSAGE}},[P,j]=t.useState([]),Ue=t.useMemo(()=>new Ye.DefaultChatTransport({api:me,headers:()=>{const e=U??$.current??D.current;return{"x-inkeep-client-timezone":Intl.DateTimeFormat().resolvedOptions().timeZone,"x-inkeep-client-timestamp":new Date().toISOString(),"x-inkeep-invocation-type":"chat_widget",..._?{"x-inkeep-app-id":_}:{},...e?{Authorization:`Bearer ${e}`}:{},...z.current?{"inkeep-filters":z.current}:{},...Re.current}},prepareSendMessagesRequest:async e=>{const a=await he.current(),s=e.messages[e.messages.length-1];return s||console.warn("[useInkeepChat] prepareSendMessagesRequest called with empty messages array"),{body:{...e.body,id:e.id,messages:s?[s]:[],trigger:e.trigger,messageId:e.messageId,...B.current?{userProperties:B.current}:{},...G.current?{properties:G.current}:{}},headers:{...e.headers,...a}}},body:{requestContext:fe}}),[me,fe,_,U]),{messages:A,sendMessage:V,addToolApprovalResponse:J,status:Ee,setMessages:f,stop:x,error:q}=Ze.useChat({transport:Ue,onData(e){k(e.type,e.data)},async onFinish({message:e}){k("completion",{conversationId:c}),await h({eventName:"assistant_message_received",properties:{conversationId:c,messageId:e.id}}),h({eventName:"assistant_answer_displayed",properties:{conversationId:c,messageId:e.id}})},onError(e){console.error("onError",{code:e.code,message:e.message});const a=_e||U?null:p.resolveStreamingAuthError(e);if(a!==null&&y.current<1){y.current++;const n=K.current,r=H.current;(async()=>{if(a==="session"&&oe){const l=await ie();if(!l)throw new Error("Auth token refresh failed");$.current=l}else if(a==="session"){const l=await ue();l&&(D.current=l)}else d();if(n){J(n);return}r&&(f(l=>{let o=[...l];return o.at(-1)?.role==="assistant"&&(o=o.slice(0,-1)),o.at(-1)?.role==="user"&&(o=o.slice(0,-1)),o}),V({id:r.messageId,parts:[...r.content?[{type:"text",text:r.content}]:[],...r.files??[]]},{body:r.body}))})().catch(()=>{y.current=0,d(),f(l=>{const o=[...l],g=o[o.length-1];if(!g)return o;const L=p.DEFAULT_ERROR_MESSAGE;return g.role==="user"?o.push({id:T.generateUid(16),role:"assistant",parts:[{type:"text",text:L}]}):g.parts=[{type:"text",text:L}],o})});return}y.current=0,a!==null&&d();const s=p.isRecoverableError(e),u=Oe(e);if(h({eventName:"chat_error",properties:{conversationId:c,messageId:A.at(-1)?.id,error:e.message}}),s){Y({title:"Request failed",message:u},p.RECOVERABLE_NOTIFICATION_DURATION_MS),f(r=>{let i=[...r];return i.at(-1)?.role==="assistant"&&(i=i.slice(0,-1)),i.at(-1)?.role==="user"&&(i=i.slice(0,-1)),i});const n=H.current?.content;n&&S(n),X.current=e;return}f(n=>{const r=[...n],i=r[r.length-1];return i&&(i.role==="user"?r.push({id:T.generateUid(16),role:"assistant",parts:[{type:"text",text:u}]}):i.parts=[{type:"text",text:u}]),r})}}),Se=t.useRef(v);t.useEffect(()=>{const e=Se.current;Se.current=v,e!==v&&(x(),b(null),f([]),m(""),S(""),j([]),d())},[v,x,f,m,d]);const Ce=Ee==="submitted",Q=Ee==="streaming",De=t.useMemo(()=>{const e=n=>{if(!n||typeof n!="object")return!1;const r=n;return typeof r.type=="string"&&r.type.startsWith("tool-")},s=[...A??[]].reverse().find(n=>n.role==="assistant");if(!s)return!1;const u=s.parts?.at(-1);return!(!e(u)||u.state!=="output-available"||!u.approval?.id||Q)},[A,Q]),[$e,W]=t.useState(!1),Ie=Q||De&&!$e,Ae=Ce||Ie,Be=A.length===0,Z=!E.trim()&&P.length===0||Ae,Ge=st.useMediaQuery("(max-width: 768px)"),[He,b]=t.useState(null),X=t.useRef(null);t.useEffect(()=>{if(q){if(X.current===q){X.current=null;return}b(q)}},[q]);const Ke=()=>b(null),{inputNotification:ze,showInputNotification:Y,clearInputNotification:je}=lt.useInputNotification(),be=t.useRef(null);t.useEffect(()=>{xe?.(E)},[E]);const Ve=e=>{e.key==="Enter"&&!e.shiftKey&&!Z&&!e.nativeEvent.isComposing&&(e.preventDefault(),ee())},ee=async(e=E)=>{if(Z&&(!e||e.trim().length===0)&&P.length===0)return;const a=P;j([]),S(""),y.current=0,K.current=null,W(!1);let s=c;s||(s=`conv_${T.generateUid(16)}`,m(s));const u=T.generateUid(21);ke(s),await h({eventName:"user_message_submitted",properties:{conversationId:s,messageId:u}});const n=I.current;I.current=void 0;let r=[];if(a.length>0)try{r=await Promise.all(a.map(o=>{const g=Xe.normalizeFileType(o);return new Promise((L,Te)=>{const M=new FileReader;M.onload=()=>{if(typeof M.result!="string"){Te(new Error(`Failed to read file "${g.name}"`));return}L({type:"file",url:M.result,mediaType:g.type,filename:g.name})},M.onerror=()=>Te(new Error(`Failed to read file "${g.name}"`)),M.readAsDataURL(g)})}))}catch{Y({title:"Failed to attach files",message:"Could not read one or more files. Please try again."});return}const i=r.length||n?.length?[...r,...n??[]]:void 0,l=[...e.trim()?[{type:"text",text:e}]:[],...i??[]];H.current={content:e,messageId:u,body:{conversationId:s},files:i},V({id:u,parts:l},{body:{conversationId:s}})},Je=t.useCallback(e=>{y.current=0,K.current=e,W(!1),J(e)},[J]),te=t.useCallback(()=>{W(!0),x().then(()=>{k("aborted",{conversationId:c})})},[x,c,k]),we=()=>{Ke(),f([]),m(""),d(),I.current=C?.length?C:void 0,h({eventName:"chat_clear_button_clicked",properties:{conversationId:c}})},w=t.useCallback((e,a)=>{b(null),f(a),m(e),d(),I.current=void 0},[f,m,d]),Me=t.useCallback(async(e,a)=>{te(),w(e,[]),ye(!0);try{const s=await ve(e,a);if(s===null)return!1;const n=s[s.length-1]?.role==="user"?[...s,{id:T.generateUid(16),role:"assistant",parts:[{type:"text",text:"This session was interrupted. Please check back in a few minutes or start a new conversation."}]}]:s;return w(e,n),!0}finally{a?.aborted||ye(!1)}},[w,ve,te]);nt.useInitialConversation({conversationId:R.conversationId,effectiveAuthToken:le,loadAndRestoreSession:Me,onLoadFailed:()=>w("",[])});const{openForm:Qe}=ot.useChatForm(),We=it.useWidget();return t.useImperativeHandle(R.chatFunctionsRef,()=>({submitMessage:ee,updateInputMessage(e){S(e)},clearChat:we,openForm:e=>{We?.setView("chat"),Qe(e,void 0)},focusInput:()=>{be.current?.focus()}})),{messages:A,sendMessage:V,addToolApprovalResponse:Je,isLoading:Ce,isStreaming:Ie,isBusy:Ae,error:He,setError:b,isSubmitDisabled:Z,input:E,handleInputChange:Fe,handleInputKeyDown:Ve,handleSubmit:ee,stop:te,clear:we,inputRef:be,isMobile:Ge,files:P,setFiles:j,isNewChat:Be,conversationId:c,restoreSession:w,loadAndRestoreSession:Me,isSessionLoading:Le,authToken:v?ae:ce,refreshSession:v?ie:ue,getCaptchaHeader:F,invalidateCaptcha:d,inputNotification:ze,showInputNotification:Y,clearInputNotification:je}};exports.useInkeepChat=dt;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Ze=require("@ai-sdk/react"),Xe=require("./file-upload-input.cjs"),Ye=require("ai"),t=require("react"),et=require("../../providers/config-provider.cjs"),tt=require("../../providers/chat-auth-provider.cjs"),st=require("../../hooks/use-media-query.cjs"),rt=require("../../hooks/use-conversation-loader.cjs"),nt=require("../../hooks/use-initial-conversation.cjs"),k=require("../../utils/generate-uid.cjs"),at=require("../../providers/base-events-provider.cjs"),ot=require("../../providers/chat-form-provider.cjs"),it=require("../../providers/widget-provider.cjs"),ct=require("@radix-ui/react-use-controllable-state"),ut=require("../../hooks/use-streaming-events.cjs"),lt=require("../../hooks/use-input-notification.cjs"),p=require("./chat-error-helpers.cjs"),dt=()=>{const{baseSettings:se,aiChatSettings:E}=et.useInkeepConfig(),[c="",m]=ct.useControllableState({prop:E.conversationIdOverride,defaultProp:E.conversationIdOverride??""}),{logEvent:h}=at.useBaseEvents(),{setConversationId:ke,emitToParent:F}=ut.useStreamingEvents(),re=t.useRef(c);t.useEffect(()=>{const e=re.current;re.current=c,e!==c&&h({eventName:"chat_conversation_changed",properties:{conversationId:c,previousConversationId:e}})},[c,h]);const[S,C]=t.useState(""),Fe=e=>C(e.target.value),{shouldBypassCaptcha:_e,filters:ne,userProperties:N,analyticsProperties:O}=se,{authToken:ae,isAuthenticated:v,isAuthConfigured:oe,refreshAuthToken:ie,sessionToken:ce,refreshSession:ue,getCaptchaHeader:_,invalidateCaptcha:d,effectiveAuthToken:le,applicableRefreshSession:Pe}=tt.useChatAuth(),{onInputMessageChange:xe,filters:de,baseUrl:pe,agentUrl:qe,context:fe,headers:ge,appId:P,apiKey:U,files:I}=E,he=t.useRef(_);he.current=_;const me=qe||`${pe}/run/api/chat`,{loadConversation:ve}=rt.useConversationLoader({baseUrl:pe,appId:P,authToken:le,getCaptchaHeader:_,invalidateCaptcha:d,refreshSession:Pe}),[Le,ye]=t.useState(!1),D=t.useRef(null);D.current=ce;const $=t.useRef(null);$.current=ae;const B=t.useRef(void 0);B.current=N&&Object.keys(N).length>0?N:void 0;const G=t.useRef(void 0);G.current=O&&Object.keys(O).length>0?O:void 0;const y=t.useRef(0),H=t.useRef(null),K=t.useRef(null),R=t.useRef(void 0),Ne=I?.map(e=>`${e.filename??""}:${e.mediaType}:${e.url.length}:${e.url.slice(0,64)}:${e.url.slice(-32)}`).join(`
2
+ `)??"";t.useEffect(()=>{R.current=I?.length?I:void 0},[Ne]);const Re=t.useRef(ge);Re.current=ge;const z=t.useRef(void 0);z.current=ne||de?JSON.stringify({...ne,...de}):void 0;const Oe=e=>{switch(p.resolveHttpStatusCode(e)){case 400:try{const s=JSON.parse(e.message??"");return s.detail??s.error?.message??p.RECOVERABLE_FALLBACK_MESSAGE}catch{return e.message?.trim()||p.RECOVERABLE_FALLBACK_MESSAGE}case 401:return oe?"Authentication failed. Please try again.":p.DEFAULT_ERROR_MESSAGE;case 403:return`There seems to be a configuration error. Please contact ${se.organizationDisplayName??"Administrator"}`;case 429:return p.RATE_LIMIT_MESSAGE;default:return p.DEFAULT_ERROR_MESSAGE}},[A,j]=t.useState([]),Ue=t.useMemo(()=>new Ye.DefaultChatTransport({api:me,headers:()=>{const e=U??$.current??D.current;return{"x-inkeep-client-timezone":Intl.DateTimeFormat().resolvedOptions().timeZone,"x-inkeep-client-timestamp":new Date().toISOString(),"x-inkeep-invocation-type":"chat_widget",...P?{"x-inkeep-app-id":P}:{},...e?{Authorization:`Bearer ${e}`}:{},...z.current?{"inkeep-filters":z.current}:{},...Re.current}},prepareSendMessagesRequest:async e=>{const a=await he.current(),s=e.messages[e.messages.length-1];return s||console.warn("[useInkeepChat] prepareSendMessagesRequest called with empty messages array"),{body:{...e.body,id:e.id,messages:s?[s]:[],trigger:e.trigger,messageId:e.messageId,...B.current?{userProperties:B.current}:{},...G.current?{properties:G.current}:{}},headers:{...e.headers,...a}}},body:{requestContext:fe}}),[me,fe,P,U]),{messages:b,sendMessage:V,addToolApprovalResponse:J,status:Ee,setMessages:f,stop:x,error:q}=Ze.useChat({transport:Ue,onData(e){F(e.type,e.data)},async onFinish({message:e}){F("completion",{conversationId:c}),await h({eventName:"assistant_message_received",properties:{conversationId:c,messageId:e.id}}),h({eventName:"assistant_answer_displayed",properties:{conversationId:c,messageId:e.id}})},onError(e){console.error("onError",{code:e.code,message:e.message});const a=_e||U?null:p.resolveStreamingAuthError(e);if(a!==null&&y.current<1){y.current++;const n=K.current,r=H.current;(async()=>{if(a==="session"&&oe){const l=await ie();if(!l)throw new Error("Auth token refresh failed");$.current=l}else if(a==="session"){const l=await ue();l&&(D.current=l)}else d();if(n){J(n);return}r&&(f(l=>{let o=[...l];return o.at(-1)?.role==="assistant"&&(o=o.slice(0,-1)),o.at(-1)?.role==="user"&&(o=o.slice(0,-1)),o}),V({id:r.messageId,parts:[...r.content.trim()?[{type:"text",text:r.content}]:[],...r.files??[]]},{body:r.body}))})().catch(()=>{y.current=0,d(),f(l=>{const o=[...l],g=o[o.length-1];if(!g)return o;const L=p.DEFAULT_ERROR_MESSAGE;return g.role==="user"?o.push({id:k.generateUid(16),role:"assistant",parts:[{type:"text",text:L}]}):g.parts=[{type:"text",text:L}],o})});return}y.current=0,a!==null&&d();const s=p.isRecoverableError(e),u=Oe(e);if(h({eventName:"chat_error",properties:{conversationId:c,messageId:b.at(-1)?.id,error:e.message}}),s){Y({title:"Request failed",message:u},p.RECOVERABLE_NOTIFICATION_DURATION_MS),f(r=>{let i=[...r];return i.at(-1)?.role==="assistant"&&(i=i.slice(0,-1)),i.at(-1)?.role==="user"&&(i=i.slice(0,-1)),i});const n=H.current?.content;n&&C(n),X.current=e;return}f(n=>{const r=[...n],i=r[r.length-1];return i&&(i.role==="user"?r.push({id:k.generateUid(16),role:"assistant",parts:[{type:"text",text:u}]}):i.parts=[{type:"text",text:u}]),r})}}),Se=t.useRef(v);t.useEffect(()=>{const e=Se.current;Se.current=v,e!==v&&(x(),w(null),f([]),m(""),C(""),j([]),d())},[v,x,f,m,d]);const Ce=Ee==="submitted",Q=Ee==="streaming",De=t.useMemo(()=>{const e=n=>{if(!n||typeof n!="object")return!1;const r=n;return typeof r.type=="string"&&r.type.startsWith("tool-")},s=[...b??[]].reverse().find(n=>n.role==="assistant");if(!s)return!1;const u=s.parts?.at(-1);return!(!e(u)||u.state!=="output-available"||!u.approval?.id||Q)},[b,Q]),[$e,W]=t.useState(!1),Ie=Q||De&&!$e,Ae=Ce||Ie,Be=b.length===0,Z=!S.trim()&&A.length===0||Ae,Ge=st.useMediaQuery("(max-width: 768px)"),[He,w]=t.useState(null),X=t.useRef(null);t.useEffect(()=>{if(q){if(X.current===q){X.current=null;return}w(q)}},[q]);const Ke=()=>w(null),{inputNotification:ze,showInputNotification:Y,clearInputNotification:je}=lt.useInputNotification(),be=t.useRef(null);t.useEffect(()=>{xe?.(S)},[S]);const Ve=e=>{e.key==="Enter"&&!e.shiftKey&&!Z&&!e.nativeEvent.isComposing&&(e.preventDefault(),ee())},ee=async(e=S)=>{if(Z&&(!e||e.trim().length===0)&&A.length===0||!e.trim()&&!A.length&&!R.current?.length)return;const a=A;j([]),C(""),y.current=0,K.current=null,W(!1);let s=c;s||(s=`conv_${k.generateUid(16)}`,m(s));const u=k.generateUid(21);ke(s),await h({eventName:"user_message_submitted",properties:{conversationId:s,messageId:u}});const n=R.current;R.current=void 0;let r=[];if(a.length>0)try{r=await Promise.all(a.map(o=>{const g=Xe.normalizeFileType(o);return new Promise((L,Te)=>{const T=new FileReader;T.onload=()=>{if(typeof T.result!="string"){Te(new Error(`Failed to read file "${g.name}"`));return}L({type:"file",url:T.result,mediaType:g.type,filename:g.name})},T.onerror=()=>Te(new Error(`Failed to read file "${g.name}"`)),T.readAsDataURL(g)})}))}catch{Y({title:"Failed to attach files",message:"Could not read one or more files. Please try again."});return}const i=r.length||n?.length?[...r,...n??[]]:void 0,l=[...e.trim()?[{type:"text",text:e}]:[],...i??[]];H.current={content:e,messageId:u,body:{conversationId:s},files:i},V({id:u,parts:l},{body:{conversationId:s}})},Je=t.useCallback(e=>{y.current=0,K.current=e,W(!1),J(e)},[J]),te=t.useCallback(()=>{W(!0),x().then(()=>{F("aborted",{conversationId:c})})},[x,c,F]),we=()=>{Ke(),f([]),m(""),d(),R.current=I?.length?I:void 0,h({eventName:"chat_clear_button_clicked",properties:{conversationId:c}})},M=t.useCallback((e,a)=>{w(null),f(a),m(e),d(),R.current=void 0},[f,m,d]),Me=t.useCallback(async(e,a)=>{te(),M(e,[]),ye(!0);try{const s=await ve(e,a);if(s===null)return!1;const n=s[s.length-1]?.role==="user"?[...s,{id:k.generateUid(16),role:"assistant",parts:[{type:"text",text:"This session was interrupted. Please check back in a few minutes or start a new conversation."}]}]:s;return M(e,n),!0}finally{a?.aborted||ye(!1)}},[M,ve,te]);nt.useInitialConversation({conversationId:E.conversationId,effectiveAuthToken:le,loadAndRestoreSession:Me,onLoadFailed:()=>M("",[])});const{openForm:Qe}=ot.useChatForm(),We=it.useWidget();return t.useImperativeHandle(E.chatFunctionsRef,()=>({submitMessage:ee,updateInputMessage(e){C(e)},clearChat:we,openForm:e=>{We?.setView("chat"),Qe(e,void 0)},focusInput:()=>{be.current?.focus()}})),{messages:b,sendMessage:V,addToolApprovalResponse:Je,isLoading:Ce,isStreaming:Ie,isBusy:Ae,error:He,setError:w,isSubmitDisabled:Z,input:S,handleInputChange:Fe,handleInputKeyDown:Ve,handleSubmit:ee,stop:te,clear:we,inputRef:be,isMobile:Ge,files:A,setFiles:j,isNewChat:Be,conversationId:c,restoreSession:M,loadAndRestoreSession:Me,isSessionLoading:Le,authToken:v?ae:ce,refreshSession:v?ie:ue,getCaptchaHeader:_,invalidateCaptcha:d,inputNotification:ze,showInputNotification:Y,clearInputNotification:je}};exports.useInkeepChat=dt;
@@ -2,13 +2,13 @@
2
2
  import { useChat as st } from "@ai-sdk/react";
3
3
  import { normalizeFileType as rt } from "./file-upload-input.js";
4
4
  import { DefaultChatTransport as nt } from "ai";
5
- import { useRef as i, useEffect as T, useState as M, useMemo as _e, useCallback as L, useImperativeHandle as ot } from "react";
5
+ import { useRef as i, useEffect as M, useState as k, useMemo as _e, useCallback as L, useImperativeHandle as ot } from "react";
6
6
  import { useInkeepConfig as at } from "../../providers/config-provider.js";
7
7
  import { useChatAuth as it } from "../../providers/chat-auth-provider.js";
8
8
  import { useMediaQuery as ct } from "../../hooks/use-media-query.js";
9
9
  import { useConversationLoader as lt } from "../../hooks/use-conversation-loader.js";
10
10
  import { useInitialConversation as ut } from "../../hooks/use-initial-conversation.js";
11
- import { generateUid as k } from "../../utils/generate-uid.js";
11
+ import { generateUid as F } from "../../utils/generate-uid.js";
12
12
  import { useBaseEvents as pt } from "../../providers/base-events-provider.js";
13
13
  import { useChatForm as dt } from "../../providers/chat-form-provider.js";
14
14
  import { useWidget as ft } from "../../providers/widget-provider.js";
@@ -17,11 +17,11 @@ import { useStreamingEvents as gt } from "../../hooks/use-streaming-events.js";
17
17
  import { useInputNotification as ht } from "../../hooks/use-input-notification.js";
18
18
  import { resolveStreamingAuthError as vt, DEFAULT_ERROR_MESSAGE as ne, isRecoverableError as yt, RECOVERABLE_NOTIFICATION_DURATION_MS as It, resolveHttpStatusCode as Ct, RATE_LIMIT_MESSAGE as Rt, RECOVERABLE_FALLBACK_MESSAGE as Ne } from "./chat-error-helpers.js";
19
19
  const Bt = () => {
20
- const { baseSettings: oe, aiChatSettings: y } = at(), [c = "", g] = mt({
21
- prop: y.conversationIdOverride,
22
- defaultProp: y.conversationIdOverride ?? ""
23
- }), { logEvent: m } = pt(), { setConversationId: Pe, emitToParent: F } = gt(), ae = i(c);
24
- T(() => {
20
+ const { baseSettings: oe, aiChatSettings: I } = at(), [c = "", g] = mt({
21
+ prop: I.conversationIdOverride,
22
+ defaultProp: I.conversationIdOverride ?? ""
23
+ }), { logEvent: m } = pt(), { setConversationId: Pe, emitToParent: x } = gt(), ae = i(c);
24
+ M(() => {
25
25
  const e = ae.current;
26
26
  ae.current = c, e !== c && m({
27
27
  eventName: "chat_conversation_changed",
@@ -31,7 +31,7 @@ const Bt = () => {
31
31
  }
32
32
  });
33
33
  }, [c, m]);
34
- const [I, C] = M(""), Oe = (e) => C(e.target.value), {
34
+ const [C, R] = k(""), Oe = (e) => R(e.target.value), {
35
35
  shouldBypassCaptcha: De,
36
36
  filters: ie,
37
37
  userProperties: $,
@@ -43,7 +43,7 @@ const Bt = () => {
43
43
  refreshAuthToken: ue,
44
44
  sessionToken: pe,
45
45
  refreshSession: de,
46
- getCaptchaHeader: x,
46
+ getCaptchaHeader: _,
47
47
  invalidateCaptcha: p,
48
48
  effectiveAuthToken: fe,
49
49
  applicableRefreshSession: Le
@@ -54,19 +54,19 @@ const Bt = () => {
54
54
  agentUrl: Be,
55
55
  context: he,
56
56
  headers: ve,
57
- appId: _,
57
+ appId: N,
58
58
  apiKey: U,
59
- files: R
60
- } = y, ye = i(x);
61
- ye.current = x;
59
+ files: S
60
+ } = I, ye = i(_);
61
+ ye.current = _;
62
62
  const Ie = Be || `${ge}/run/api/chat`, { loadConversation: Ce } = lt({
63
63
  baseUrl: ge,
64
- appId: _,
64
+ appId: N,
65
65
  authToken: fe,
66
- getCaptchaHeader: x,
66
+ getCaptchaHeader: _,
67
67
  invalidateCaptcha: p,
68
68
  refreshSession: Le
69
- }), [Ue, Re] = M(!1), z = i(null);
69
+ }), [Ue, Re] = k(!1), z = i(null);
70
70
  z.current = pe;
71
71
  const H = i(null);
72
72
  H.current = ce;
@@ -74,12 +74,12 @@ const Bt = () => {
74
74
  K.current = $ && Object.keys($).length > 0 ? $ : void 0;
75
75
  const q = i(void 0);
76
76
  q.current = B && Object.keys(B).length > 0 ? B : void 0;
77
- const v = i(0), j = i(null), G = i(null), S = i(void 0), ze = R?.map(
77
+ const v = i(0), j = i(null), G = i(null), y = i(void 0), ze = S?.map(
78
78
  (e) => `${e.filename ?? ""}:${e.mediaType}:${e.url.length}:${e.url.slice(0, 64)}:${e.url.slice(-32)}`
79
79
  ).join(`
80
80
  `) ?? "";
81
- T(() => {
82
- S.current = R?.length ? R : void 0;
81
+ M(() => {
82
+ y.current = S?.length ? S : void 0;
83
83
  }, [ze]);
84
84
  const Se = i(ve);
85
85
  Se.current = ve;
@@ -103,7 +103,7 @@ const Bt = () => {
103
103
  default:
104
104
  return ne;
105
105
  }
106
- }, [N, J] = M([]), Ke = _e(
106
+ }, [w, J] = k([]), Ke = _e(
107
107
  () => new nt({
108
108
  api: Ie,
109
109
  headers: () => {
@@ -112,7 +112,7 @@ const Bt = () => {
112
112
  "x-inkeep-client-timezone": Intl.DateTimeFormat().resolvedOptions().timeZone,
113
113
  "x-inkeep-client-timestamp": (/* @__PURE__ */ new Date()).toISOString(),
114
114
  "x-inkeep-invocation-type": "chat_widget",
115
- ..._ ? { "x-inkeep-app-id": _ } : {},
115
+ ...N ? { "x-inkeep-app-id": N } : {},
116
116
  ...e ? { Authorization: `Bearer ${e}` } : {},
117
117
  ...V.current ? { "inkeep-filters": V.current } : {},
118
118
  ...Se.current
@@ -142,9 +142,9 @@ const Bt = () => {
142
142
  requestContext: he
143
143
  }
144
144
  }),
145
- [Ie, he, _, U]
145
+ [Ie, he, N, U]
146
146
  ), {
147
- messages: w,
147
+ messages: A,
148
148
  sendMessage: W,
149
149
  addToolApprovalResponse: Q,
150
150
  status: we,
@@ -154,10 +154,10 @@ const Bt = () => {
154
154
  } = st({
155
155
  transport: Ke,
156
156
  onData(e) {
157
- F(e.type, e.data);
157
+ x(e.type, e.data);
158
158
  },
159
159
  async onFinish({ message: e }) {
160
- F("completion", { conversationId: c }), await m({
160
+ x("completion", { conversationId: c }), await m({
161
161
  eventName: "assistant_message_received",
162
162
  properties: {
163
163
  conversationId: c,
@@ -198,7 +198,7 @@ const Bt = () => {
198
198
  {
199
199
  id: s.messageId,
200
200
  parts: [
201
- ...s.content ? [{ type: "text", text: s.content }] : [],
201
+ ...s.content.trim() ? [{ type: "text", text: s.content }] : [],
202
202
  ...s.files ?? []
203
203
  ]
204
204
  },
@@ -210,7 +210,7 @@ const Bt = () => {
210
210
  if (!f) return o;
211
211
  const D = ne;
212
212
  return f.role === "user" ? o.push({
213
- id: k(16),
213
+ id: F(16),
214
214
  role: "assistant",
215
215
  parts: [{ type: "text", text: D }]
216
216
  }) : f.parts = [{ type: "text", text: D }], o;
@@ -224,7 +224,7 @@ const Bt = () => {
224
224
  eventName: "chat_error",
225
225
  properties: {
226
226
  conversationId: c,
227
- messageId: w.at(-1)?.id,
227
+ messageId: A.at(-1)?.id,
228
228
  error: e.message
229
229
  }
230
230
  }), t) {
@@ -236,55 +236,56 @@ const Bt = () => {
236
236
  return a.at(-1)?.role === "assistant" && (a = a.slice(0, -1)), a.at(-1)?.role === "user" && (a = a.slice(0, -1)), a;
237
237
  });
238
238
  const r = j.current?.content;
239
- r && C(r), ee.current = e;
239
+ r && R(r), ee.current = e;
240
240
  return;
241
241
  }
242
242
  d((r) => {
243
243
  const s = [...r], a = s[s.length - 1];
244
244
  return a && (a.role === "user" ? s.push({
245
- id: k(16),
245
+ id: F(16),
246
246
  role: "assistant",
247
247
  parts: [{ type: "text", text: l }]
248
248
  }) : a.parts = [{ type: "text", text: l }]), s;
249
249
  });
250
250
  }
251
251
  }), Ae = i(h);
252
- T(() => {
252
+ M(() => {
253
253
  const e = Ae.current;
254
- Ae.current = h, e !== h && (P(), A(null), d([]), g(""), C(""), J([]), p());
254
+ Ae.current = h, e !== h && (P(), b(null), d([]), g(""), R(""), J([]), p());
255
255
  }, [h, P, d, g, p]);
256
256
  const be = we === "submitted", Z = we === "streaming", qe = _e(() => {
257
257
  const e = (r) => {
258
258
  if (!r || typeof r != "object") return !1;
259
259
  const s = r;
260
260
  return typeof s.type == "string" && s.type.startsWith("tool-");
261
- }, t = [...w ?? []].reverse().find((r) => r.role === "assistant");
261
+ }, t = [...A ?? []].reverse().find((r) => r.role === "assistant");
262
262
  if (!t) return !1;
263
263
  const l = t.parts?.at(-1);
264
264
  return !(!e(l) || l.state !== "output-available" || !l.approval?.id || Z);
265
- }, [w, Z]), [je, X] = M(!1), Ee = Z || qe && !je, Te = be || Ee, Ge = w.length === 0, Y = !I.trim() && N.length === 0 || Te, Ve = ct("(max-width: 768px)"), [Je, A] = M(null), ee = i(null);
266
- T(() => {
265
+ }, [A, Z]), [je, X] = k(!1), Ee = Z || qe && !je, Te = be || Ee, Ge = A.length === 0, Y = !C.trim() && w.length === 0 || Te, Ve = ct("(max-width: 768px)"), [Je, b] = k(null), ee = i(null);
266
+ M(() => {
267
267
  if (O) {
268
268
  if (ee.current === O) {
269
269
  ee.current = null;
270
270
  return;
271
271
  }
272
- A(O);
272
+ b(O);
273
273
  }
274
274
  }, [O]);
275
- const We = () => A(null), { inputNotification: Qe, showInputNotification: te, clearInputNotification: Ze } = ht(), Me = i(null);
276
- T(() => {
277
- $e?.(I);
278
- }, [I]);
275
+ const We = () => b(null), { inputNotification: Qe, showInputNotification: te, clearInputNotification: Ze } = ht(), Me = i(null);
276
+ M(() => {
277
+ $e?.(C);
278
+ }, [C]);
279
279
  const Xe = (e) => {
280
280
  e.key === "Enter" && !e.shiftKey && !Y && !e.nativeEvent.isComposing && (e.preventDefault(), se());
281
- }, se = async (e = I) => {
282
- if (Y && (!e || e.trim().length === 0) && N.length === 0) return;
283
- const n = N;
284
- J([]), C(""), v.current = 0, G.current = null, X(!1);
281
+ }, se = async (e = C) => {
282
+ if (Y && (!e || e.trim().length === 0) && w.length === 0 || !e.trim() && !w.length && !y.current?.length)
283
+ return;
284
+ const n = w;
285
+ J([]), R(""), v.current = 0, G.current = null, X(!1);
285
286
  let t = c;
286
- t || (t = `conv_${k(16)}`, g(t));
287
- const l = k(21);
287
+ t || (t = `conv_${F(16)}`, g(t));
288
+ const l = F(21);
288
289
  Pe(t), await m({
289
290
  eventName: "user_message_submitted",
290
291
  properties: {
@@ -292,8 +293,8 @@ const Bt = () => {
292
293
  messageId: l
293
294
  }
294
295
  });
295
- const r = S.current;
296
- S.current = void 0;
296
+ const r = y.current;
297
+ y.current = void 0;
297
298
  let s = [];
298
299
  if (n.length > 0)
299
300
  try {
@@ -301,19 +302,19 @@ const Bt = () => {
301
302
  n.map((o) => {
302
303
  const f = rt(o);
303
304
  return new Promise((D, xe) => {
304
- const E = new FileReader();
305
- E.onload = () => {
306
- if (typeof E.result != "string") {
305
+ const T = new FileReader();
306
+ T.onload = () => {
307
+ if (typeof T.result != "string") {
307
308
  xe(new Error(`Failed to read file "${f.name}"`));
308
309
  return;
309
310
  }
310
311
  D({
311
312
  type: "file",
312
- url: E.result,
313
+ url: T.result,
313
314
  mediaType: f.type,
314
315
  filename: f.name
315
316
  });
316
- }, E.onerror = () => xe(new Error(`Failed to read file "${f.name}"`)), E.readAsDataURL(f);
317
+ }, T.onerror = () => xe(new Error(`Failed to read file "${f.name}"`)), T.readAsDataURL(f);
317
318
  });
318
319
  })
319
320
  );
@@ -333,10 +334,7 @@ const Bt = () => {
333
334
  messageId: l,
334
335
  body: { conversationId: t },
335
336
  files: a
336
- }, W(
337
- { id: l, parts: u },
338
- { body: { conversationId: t } }
339
- );
337
+ }, W({ id: l, parts: u }, { body: { conversationId: t } });
340
338
  }, Ye = L(
341
339
  (e) => {
342
340
  v.current = 0, G.current = e, X(!1), Q(e);
@@ -344,30 +342,30 @@ const Bt = () => {
344
342
  [Q]
345
343
  ), re = L(() => {
346
344
  X(!0), P().then(() => {
347
- F("aborted", { conversationId: c });
345
+ x("aborted", { conversationId: c });
348
346
  });
349
- }, [P, c, F]), ke = () => {
350
- We(), d([]), g(""), p(), S.current = R?.length ? R : void 0, m({
347
+ }, [P, c, x]), ke = () => {
348
+ We(), d([]), g(""), p(), y.current = S?.length ? S : void 0, m({
351
349
  eventName: "chat_clear_button_clicked",
352
350
  properties: {
353
351
  conversationId: c
354
352
  }
355
353
  });
356
- }, b = L(
354
+ }, E = L(
357
355
  (e, n) => {
358
- A(null), d(n), g(e), p(), S.current = void 0;
356
+ b(null), d(n), g(e), p(), y.current = void 0;
359
357
  },
360
358
  [d, g, p]
361
359
  ), Fe = L(
362
360
  async (e, n) => {
363
- re(), b(e, []), Re(!0);
361
+ re(), E(e, []), Re(!0);
364
362
  try {
365
363
  const t = await Ce(e, n);
366
364
  if (t === null) return !1;
367
365
  const r = t[t.length - 1]?.role === "user" ? [
368
366
  ...t,
369
367
  {
370
- id: k(16),
368
+ id: F(16),
371
369
  role: "assistant",
372
370
  parts: [
373
371
  {
@@ -377,24 +375,24 @@ const Bt = () => {
377
375
  ]
378
376
  }
379
377
  ] : t;
380
- return b(e, r), !0;
378
+ return E(e, r), !0;
381
379
  } finally {
382
380
  n?.aborted || Re(!1);
383
381
  }
384
382
  },
385
- [b, Ce, re]
383
+ [E, Ce, re]
386
384
  );
387
385
  ut({
388
- conversationId: y.conversationId,
386
+ conversationId: I.conversationId,
389
387
  effectiveAuthToken: fe,
390
388
  loadAndRestoreSession: Fe,
391
- onLoadFailed: () => b("", [])
389
+ onLoadFailed: () => E("", [])
392
390
  });
393
391
  const { openForm: et } = dt(), tt = ft();
394
- return ot(y.chatFunctionsRef, () => ({
392
+ return ot(I.chatFunctionsRef, () => ({
395
393
  submitMessage: se,
396
394
  updateInputMessage(e) {
397
- C(e);
395
+ R(e);
398
396
  },
399
397
  clearChat: ke,
400
398
  openForm: (e) => {
@@ -404,16 +402,16 @@ const Bt = () => {
404
402
  Me.current?.focus();
405
403
  }
406
404
  })), {
407
- messages: w,
405
+ messages: A,
408
406
  sendMessage: W,
409
407
  addToolApprovalResponse: Ye,
410
408
  isLoading: be,
411
409
  isStreaming: Ee,
412
410
  isBusy: Te,
413
411
  error: Je,
414
- setError: A,
412
+ setError: b,
415
413
  isSubmitDisabled: Y,
416
- input: I,
414
+ input: C,
417
415
  handleInputChange: Oe,
418
416
  handleInputKeyDown: Xe,
419
417
  handleSubmit: se,
@@ -421,16 +419,16 @@ const Bt = () => {
421
419
  clear: ke,
422
420
  inputRef: Me,
423
421
  isMobile: Ve,
424
- files: N,
422
+ files: w,
425
423
  setFiles: J,
426
424
  isNewChat: Ge,
427
425
  conversationId: c,
428
- restoreSession: b,
426
+ restoreSession: E,
429
427
  loadAndRestoreSession: Fe,
430
428
  isSessionLoading: Ue,
431
429
  authToken: h ? ce : pe,
432
430
  refreshSession: h ? ue : de,
433
- getCaptchaHeader: x,
431
+ getCaptchaHeader: _,
434
432
  invalidateCaptcha: p,
435
433
  inputNotification: Qe,
436
434
  showInputNotification: te,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/agents-ui",
3
- "version": "0.0.0-dev-20260513213554",
3
+ "version": "0.0.0-dev-20260514122955",
4
4
  "description": "",
5
5
  "homepage": "",
6
6
  "repository": {