@inkeep/agents-ui 0.0.0-dev-20260721212136 → 0.0.0-dev-20260721222136
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 Xe=require("@ai-sdk/react"),Ze=require("./file-upload-input.cjs"),et=require("ai"),t=require("react"),tt=require("../../providers/config-provider.cjs"),st=require("../../providers/chat-auth-provider.cjs"),rt=require("../../hooks/use-media-query.cjs"),nt=require("../../hooks/use-conversation-loader.cjs"),at=require("../../hooks/use-initial-conversation.cjs"),
|
|
2
|
-
`)??"";t.useEffect(()=>{v.current=T?.length?T:void 0},[xe]);const
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Xe=require("@ai-sdk/react"),Ze=require("./file-upload-input.cjs"),et=require("ai"),t=require("react"),tt=require("../../providers/config-provider.cjs"),st=require("../../providers/chat-auth-provider.cjs"),rt=require("../../hooks/use-media-query.cjs"),nt=require("../../hooks/use-conversation-loader.cjs"),at=require("../../hooks/use-initial-conversation.cjs"),O=require("../../utils/generate-uid.cjs"),ot=require("../../providers/base-events-provider.cjs"),it=require("../../providers/chat-form-provider.cjs"),ct=require("../../providers/widget-provider.cjs"),ut=require("@radix-ui/react-use-controllable-state"),lt=require("../../hooks/use-streaming-events.cjs"),dt=require("../../hooks/use-input-notification.cjs"),r=require("./chat-error-helpers.cjs"),ft=()=>{const{baseSettings:se,aiChatSettings:E}=tt.useInkeepConfig(),[u="",R]=ut.useControllableState({prop:E.conversationIdOverride,defaultProp:E.conversationIdOverride??""}),{logEvent:m}=ot.useBaseEvents(),{setConversationId:we,emitToParent:k}=lt.useStreamingEvents(),re=t.useRef(u);t.useEffect(()=>{const e=re.current;re.current=u,e!==u&&m({eventName:"chat_conversation_changed",properties:{conversationId:u,previousConversationId:e}})},[u,m]);const[I,_]=t.useState(""),Oe=e=>_(e.target.value),{shouldBypassCaptcha:ke,filters:ne,userProperties:B,analyticsProperties:D}=se,{authToken:ae,isAuthenticated:y,isAuthConfigured:oe,refreshAuthToken:ie,sessionToken:ce,refreshSession:ue,getCaptchaHeader:F,invalidateCaptcha:f,effectiveAuthToken:le,applicableRefreshSession:Fe}=st.useChatAuth(),{onInputMessageChange:Le,filters:de,baseUrl:fe,agentUrl:Pe,context:pe,headers:ge,appId:L,apiKey:U,files:T}=E,he=t.useRef(F);he.current=F;const me=Pe||`${fe}/run/api/chat`,{loadConversation:ve}=nt.useConversationLoader({baseUrl:fe,appId:L,authToken:le,getCaptchaHeader:F,invalidateCaptcha:f,refreshSession:Fe}),[Ne,Ee]=t.useState(!1),G=t.useRef(null);G.current=ce;const $=t.useRef(null);$.current=ae;const K=t.useRef(void 0);K.current=B&&Object.keys(B).length>0?B:void 0;const z=t.useRef(void 0);z.current=D&&Object.keys(D).length>0?D:void 0;const A=t.useRef(0),P=t.useRef(null),H=t.useRef(null),v=t.useRef(void 0),xe=T?.map(e=>`${e.filename??""}:${e.mediaType}:${e.url.length}:${e.url.slice(0,64)}:${e.url.slice(-32)}`).join(`
|
|
2
|
+
`)??"";t.useEffect(()=>{v.current=T?.length?T:void 0},[xe]);const Re=t.useRef(ge);Re.current=ge;const Y=t.useRef(void 0);Y.current=ne||de?JSON.stringify({...ne,...de}):void 0;const qe=e=>{if(r.isNetworkError(e))return P.current?.files?.length?r.PAYLOAD_TOO_LARGE_MESSAGE:r.NETWORK_ERROR_MESSAGE;switch(r.resolveHttpStatusCode(e)){case 400:try{const s=JSON.parse(e.message??"");return s.detail??s.error?.message??r.RECOVERABLE_FALLBACK_MESSAGE}catch{return e.message?.trim()||r.RECOVERABLE_FALLBACK_MESSAGE}case 401:return oe?"Authentication failed. Please try again.":r.DEFAULT_ERROR_MESSAGE;case 403:return`There seems to be a configuration error. Please contact ${se.organizationDisplayName??"Administrator"}`;case 413:return r.PAYLOAD_TOO_LARGE_MESSAGE;case 429:return r.RATE_LIMIT_MESSAGE;default:return r.DEFAULT_ERROR_MESSAGE}},[S,V]=t.useState([]),Be=t.useMemo(()=>new et.DefaultChatTransport({api:me,headers:()=>{const e=U??$.current??G.current;return{"x-inkeep-client-timezone":Intl.DateTimeFormat().resolvedOptions().timeZone,"x-inkeep-client-timestamp":new Date().toISOString(),"x-inkeep-invocation-type":"chat_widget",...L?{"x-inkeep-app-id":L}:{},...e?{Authorization:`Bearer ${e}`}:{},...Y.current?{"inkeep-filters":Y.current}:{},...Re.current}},prepareSendMessagesRequest:async e=>{const l=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,...K.current?{userProperties:K.current}:{},...z.current?{properties:z.current}:{}},headers:{...e.headers,...l}}},body:{requestContext:pe}}),[me,pe,L,U]),{messages:M,sendMessage:j,addToolApprovalResponse:Q,status:ye,setMessages:h,stop:N,error:x}=Xe.useChat({transport:Be,onData(e){k(e.type,e.data)},async onFinish({message:e}){k("completion",{conversationId:u}),await m({eventName:"assistant_message_received",properties:{conversationId:u,messageId:e.id}}),m({eventName:"assistant_answer_displayed",properties:{conversationId:u,messageId:e.id}})},onError(e){console.error("onError",{code:e.code,message:e.message});const l=ke||U?null:r.resolveStreamingAuthError(e);if(l!==null&&A.current<1){A.current++;const i=H.current,n=P.current;(async()=>{if(l==="session"&&oe){const a=await ie();if(!a)throw new Error("Auth token refresh failed");$.current=a}else if(l==="session"){const a=await ue();a&&(G.current=a)}else f();if(i){Q(i);return}n&&(h(a=>{let c=[...a];return c.at(-1)?.role==="assistant"&&(c=c.slice(0,-1)),c.at(-1)?.role==="user"&&(c=c.slice(0,-1)),c}),j({id:n.messageId,parts:[...n.content.trim()?[{type:"text",text:n.content}]:[],...n.files??[]]},{body:n.body}))})().catch(()=>{A.current=0,f(),h(a=>{const c=[...a],g=c[c.length-1];if(!g)return c;const d=r.DEFAULT_ERROR_MESSAGE;return g.role==="user"?c.push({id:O.generateUid(16),role:"assistant",parts:[{type:"text",text:d}]}):g.parts=[{type:"text",text:d}],c})});return}A.current=0,l!==null&&f();const s=r.isRecoverableError(e)||r.isNetworkError(e),o=qe(e);if(m({eventName:"chat_error",properties:{conversationId:u,messageId:M.at(-1)?.id,error:e.message}}),s){const i=o===r.PAYLOAD_TOO_LARGE_MESSAGE?"Message too large":o===r.RATE_LIMIT_MESSAGE?"Rate limit reached":"Request failed";q({title:i,message:o},r.RECOVERABLE_NOTIFICATION_DURATION_MS),h(p=>{let a=[...p];return a.at(-1)?.role==="assistant"&&(a=a.slice(0,-1)),a.at(-1)?.role==="user"&&(a=a.slice(0,-1)),a});const n=P.current?.content;n&&_(n),Z.current=e;return}h(i=>{const n=[...i],p=n[n.length-1];return p&&(p.role==="user"?n.push({id:O.generateUid(16),role:"assistant",parts:[{type:"text",text:o}]}):p.parts=[{type:"text",text:o}]),n})}}),Ae=t.useRef(y);t.useEffect(()=>{const e=Ae.current;Ae.current=y,e!==y&&(N(),b(null),h([]),R(""),_(""),V([]),f())},[y,N,h,R,f]);const Se=ye==="submitted",W=ye==="streaming",De=t.useMemo(()=>{const e=i=>{if(!i||typeof i!="object")return!1;const n=i;return typeof n.type=="string"&&n.type.startsWith("tool-")},s=[...M??[]].reverse().find(i=>i.role==="assistant");if(!s)return!1;const o=s.parts?.at(-1);return!(!e(o)||o.state!=="output-available"||!o.approval?.id||W)},[M,W]),[Ue,J]=t.useState(!1),Ce=W||De&&!Ue,Ie=Se||Ce,Ge=M.length===0,X=!I.trim()&&S.length===0||Ie,$e=rt.useMediaQuery("(max-width: 768px)"),[Ke,b]=t.useState(null),Z=t.useRef(null);t.useEffect(()=>{if(x){if(Z.current===x){Z.current=null;return}b(x)}},[x]);const ze=()=>b(null),{inputNotification:He,showInputNotification:q,clearInputNotification:Ye}=dt.useInputNotification(),_e=t.useRef(null);t.useEffect(()=>{Le?.(I)},[I]);const Ve=e=>{e.key==="Enter"&&!e.shiftKey&&!X&&!e.nativeEvent.isComposing&&(e.preventDefault(),ee())},ee=async(e=I)=>{if(X&&(!e||e.trim().length===0)&&S.length===0||!e.trim()&&!S.length&&!v.current?.length)return;if(r.estimateRequestBodyBytes({text:e,rawFileBytes:S.reduce((g,d)=>g+d.size,0),encodedPartsBytes:(v.current??[]).reduce((g,d)=>g+d.url.length,0)})>r.MAX_REQUEST_BODY_BYTES){q({title:"Message too large",message:r.PAYLOAD_TOO_LARGE_MESSAGE},r.RECOVERABLE_NOTIFICATION_DURATION_MS);return}const s=S;V([]),_(""),A.current=0,H.current=null,J(!1);let o=u;o||(o=`conv_${O.generateUid(16)}`,R(o));const i=O.generateUid(21);we(o),await m({eventName:"user_message_submitted",properties:{conversationId:o,messageId:i}});const n=v.current;v.current=void 0;let p=[];if(s.length>0)try{p=await Promise.all(s.map(g=>{const d=Ze.normalizeFileType(g);return new Promise((Je,be)=>{const w=new FileReader;w.onload=()=>{if(typeof w.result!="string"){be(new Error(`Failed to read file "${d.name}"`));return}Je({type:"file",url:w.result,mediaType:d.type,filename:d.name})},w.onerror=()=>be(new Error(`Failed to read file "${d.name}"`)),w.readAsDataURL(d)})}))}catch{q({title:"Failed to attach files",message:"Could not read one or more files. Please try again."});return}const a=p.length||n?.length?[...p,...n??[]]:void 0,c=[...e.trim()?[{type:"text",text:e}]:[],...a??[]];P.current={content:e,messageId:i,body:{conversationId:o},files:a},j({id:i,parts:c},{body:{conversationId:o}})},je=t.useCallback(e=>{A.current=0,H.current=e,J(!1),Q(e)},[Q]),te=t.useCallback(()=>{J(!0),N().then(()=>{k("aborted",{conversationId:u})})},[N,u,k]),Te=()=>{ze(),h([]),R(""),f(),v.current=T?.length?T:void 0,m({eventName:"chat_clear_button_clicked",properties:{conversationId:u}})},C=t.useCallback((e,l)=>{b(null),h(l),R(e),f(),v.current=void 0},[h,R,f]),Me=t.useCallback(async(e,l)=>{te(),C(e,[]),Ee(!0);try{const s=await ve(e,l);if(s===null)return!1;const i=s[s.length-1]?.role==="user"?[...s,{id:O.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 C(e,i),!0}finally{l?.aborted||Ee(!1)}},[C,ve,te]);at.useInitialConversation({conversationId:E.conversationId,fetchedConversation:E.fetchedConversation,effectiveAuthToken:le,restoreSession:C,loadAndRestoreSession:Me,onLoadFailed:()=>C("",[])});const{openForm:Qe}=it.useChatForm(),We=ct.useWidget();return t.useImperativeHandle(E.chatFunctionsRef,()=>({submitMessage:ee,updateInputMessage(e){_(e)},clearChat:Te,openForm:e=>{We?.setView("chat"),Qe(e,void 0)},focusInput:()=>{_e.current?.focus()}})),{messages:M,sendMessage:j,addToolApprovalResponse:je,isLoading:Se,isStreaming:Ce,isBusy:Ie,error:Ke,setError:b,isSubmitDisabled:X,input:I,handleInputChange:Oe,handleInputKeyDown:Ve,handleSubmit:ee,stop:te,clear:Te,inputRef:_e,isMobile:$e,files:S,setFiles:V,isNewChat:Ge,conversationId:u,restoreSession:C,loadAndRestoreSession:Me,isSessionLoading:Ne,authToken:y?ae:ce,refreshSession:y?ie:ue,getCaptchaHeader:F,invalidateCaptcha:f,inputNotification:He,showInputNotification:q,clearInputNotification:Ye}};exports.useInkeepChat=ft;
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useChat as
|
|
3
|
-
import { normalizeFileType as
|
|
4
|
-
import { DefaultChatTransport as
|
|
5
|
-
import { useRef as i, useEffect as _, useState as k, useMemo as Oe, useCallback as $, useImperativeHandle as
|
|
6
|
-
import { useInkeepConfig as
|
|
7
|
-
import { useChatAuth as
|
|
8
|
-
import { useMediaQuery as
|
|
9
|
-
import { useConversationLoader as
|
|
10
|
-
import { useInitialConversation as
|
|
2
|
+
import { useChat as it } from "@ai-sdk/react";
|
|
3
|
+
import { normalizeFileType as ct } from "./file-upload-input.js";
|
|
4
|
+
import { DefaultChatTransport as lt } from "ai";
|
|
5
|
+
import { useRef as i, useEffect as _, useState as k, useMemo as Oe, useCallback as $, useImperativeHandle as ut } from "react";
|
|
6
|
+
import { useInkeepConfig as dt } from "../../providers/config-provider.js";
|
|
7
|
+
import { useChatAuth as pt } from "../../providers/chat-auth-provider.js";
|
|
8
|
+
import { useMediaQuery as ft } from "../../hooks/use-media-query.js";
|
|
9
|
+
import { useConversationLoader as mt } from "../../hooks/use-conversation-loader.js";
|
|
10
|
+
import { useInitialConversation as gt } from "../../hooks/use-initial-conversation.js";
|
|
11
11
|
import { generateUid as F } from "../../utils/generate-uid.js";
|
|
12
|
-
import { useBaseEvents as
|
|
13
|
-
import { useChatForm as
|
|
14
|
-
import { useWidget as
|
|
15
|
-
import { useControllableState as
|
|
16
|
-
import { useStreamingEvents as
|
|
17
|
-
import { useInputNotification as
|
|
18
|
-
import { resolveStreamingAuthError as
|
|
12
|
+
import { useBaseEvents as ht } from "../../providers/base-events-provider.js";
|
|
13
|
+
import { useChatForm as vt } from "../../providers/chat-form-provider.js";
|
|
14
|
+
import { useWidget as yt } from "../../providers/widget-provider.js";
|
|
15
|
+
import { useControllableState as Rt } from "@radix-ui/react-use-controllable-state";
|
|
16
|
+
import { useStreamingEvents as It } from "../../hooks/use-streaming-events.js";
|
|
17
|
+
import { useInputNotification as Ct } from "../../hooks/use-input-notification.js";
|
|
18
|
+
import { resolveStreamingAuthError as Et, DEFAULT_ERROR_MESSAGE as oe, isRecoverableError as St, isNetworkError as Ne, RECOVERABLE_NOTIFICATION_DURATION_MS as Pe, PAYLOAD_TOO_LARGE_MESSAGE as U, RATE_LIMIT_MESSAGE as Be, NETWORK_ERROR_MESSAGE as At, resolveHttpStatusCode as wt, RECOVERABLE_FALLBACK_MESSAGE as De, estimateRequestBodyBytes as Tt, MAX_REQUEST_BODY_BYTES as bt } from "./chat-error-helpers.js";
|
|
19
19
|
const Ht = () => {
|
|
20
|
-
const { baseSettings: ae, aiChatSettings: v } =
|
|
20
|
+
const { baseSettings: ae, aiChatSettings: v } = dt(), [c = "", y] = Rt({
|
|
21
21
|
prop: v.conversationIdOverride,
|
|
22
22
|
defaultProp: v.conversationIdOverride ?? ""
|
|
23
|
-
}), { logEvent: g } =
|
|
23
|
+
}), { logEvent: g } = ht(), { setConversationId: Le, emitToParent: x } = It(), ie = i(c);
|
|
24
24
|
_(() => {
|
|
25
25
|
const e = ie.current;
|
|
26
26
|
ie.current = c, e !== c && g({
|
|
@@ -31,11 +31,11 @@ const Ht = () => {
|
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
}, [c, g]);
|
|
34
|
-
const [S, A] = k(""),
|
|
35
|
-
shouldBypassCaptcha:
|
|
34
|
+
const [S, A] = k(""), $e = (e) => A(e.target.value), {
|
|
35
|
+
shouldBypassCaptcha: Ue,
|
|
36
36
|
filters: ce,
|
|
37
|
-
userProperties:
|
|
38
|
-
analyticsProperties:
|
|
37
|
+
userProperties: z,
|
|
38
|
+
analyticsProperties: G
|
|
39
39
|
} = ae, {
|
|
40
40
|
authToken: le,
|
|
41
41
|
isAuthenticated: R,
|
|
@@ -44,81 +44,81 @@ const Ht = () => {
|
|
|
44
44
|
sessionToken: pe,
|
|
45
45
|
refreshSession: fe,
|
|
46
46
|
getCaptchaHeader: O,
|
|
47
|
-
invalidateCaptcha:
|
|
47
|
+
invalidateCaptcha: d,
|
|
48
48
|
effectiveAuthToken: me,
|
|
49
|
-
applicableRefreshSession:
|
|
50
|
-
} =
|
|
51
|
-
onInputMessageChange:
|
|
49
|
+
applicableRefreshSession: ze
|
|
50
|
+
} = pt(), {
|
|
51
|
+
onInputMessageChange: Ge,
|
|
52
52
|
filters: ge,
|
|
53
53
|
baseUrl: he,
|
|
54
|
-
agentUrl:
|
|
54
|
+
agentUrl: Ke,
|
|
55
55
|
context: ve,
|
|
56
56
|
headers: ye,
|
|
57
57
|
appId: N,
|
|
58
|
-
apiKey:
|
|
58
|
+
apiKey: K,
|
|
59
59
|
files: w
|
|
60
60
|
} = v, Re = i(O);
|
|
61
61
|
Re.current = O;
|
|
62
|
-
const Ie =
|
|
62
|
+
const Ie = Ke || `${he}/run/api/chat`, { loadConversation: Ce } = mt({
|
|
63
63
|
baseUrl: he,
|
|
64
64
|
appId: N,
|
|
65
65
|
authToken: me,
|
|
66
66
|
getCaptchaHeader: O,
|
|
67
|
-
invalidateCaptcha:
|
|
68
|
-
refreshSession:
|
|
69
|
-
}), [
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
const H = i(void 0);
|
|
74
|
-
H.current = U && Object.keys(U).length > 0 ? U : void 0;
|
|
67
|
+
invalidateCaptcha: d,
|
|
68
|
+
refreshSession: ze
|
|
69
|
+
}), [qe, Ee] = k(!1), q = i(null);
|
|
70
|
+
q.current = pe;
|
|
71
|
+
const H = i(null);
|
|
72
|
+
H.current = le;
|
|
75
73
|
const j = i(void 0);
|
|
76
74
|
j.current = z && Object.keys(z).length > 0 ? z : void 0;
|
|
77
|
-
const
|
|
75
|
+
const V = i(void 0);
|
|
76
|
+
V.current = G && Object.keys(G).length > 0 ? G : void 0;
|
|
77
|
+
const I = i(0), P = i(null), W = i(null), h = i(void 0), He = w?.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
81
|
_(() => {
|
|
82
82
|
h.current = w?.length ? w : void 0;
|
|
83
|
-
}, [
|
|
83
|
+
}, [He]);
|
|
84
84
|
const Se = i(ye);
|
|
85
85
|
Se.current = ye;
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
const
|
|
86
|
+
const Y = i(void 0);
|
|
87
|
+
Y.current = ce || ge ? JSON.stringify({ ...ce, ...ge }) : void 0;
|
|
88
|
+
const je = (e) => {
|
|
89
89
|
if (Ne(e))
|
|
90
|
-
return P.current?.files?.length ?
|
|
91
|
-
switch (
|
|
90
|
+
return P.current?.files?.length ? U : At;
|
|
91
|
+
switch (wt(e)) {
|
|
92
92
|
case 400:
|
|
93
93
|
try {
|
|
94
94
|
const t = JSON.parse(e.message ?? "");
|
|
95
|
-
return t.detail ?? t.error?.message ??
|
|
95
|
+
return t.detail ?? t.error?.message ?? De;
|
|
96
96
|
} catch {
|
|
97
|
-
return e.message?.trim() ||
|
|
97
|
+
return e.message?.trim() || De;
|
|
98
98
|
}
|
|
99
99
|
case 401:
|
|
100
|
-
return ue ? "Authentication failed. Please try again." :
|
|
100
|
+
return ue ? "Authentication failed. Please try again." : oe;
|
|
101
101
|
case 403:
|
|
102
102
|
return `There seems to be a configuration error. Please contact ${ae.organizationDisplayName ?? "Administrator"}`;
|
|
103
103
|
case 413:
|
|
104
|
-
return
|
|
104
|
+
return U;
|
|
105
105
|
case 429:
|
|
106
|
-
return
|
|
106
|
+
return Be;
|
|
107
107
|
default:
|
|
108
|
-
return
|
|
108
|
+
return oe;
|
|
109
109
|
}
|
|
110
|
-
}, [C,
|
|
111
|
-
() => new
|
|
110
|
+
}, [C, J] = k([]), Ve = Oe(
|
|
111
|
+
() => new lt({
|
|
112
112
|
api: Ie,
|
|
113
113
|
headers: () => {
|
|
114
|
-
const e =
|
|
114
|
+
const e = K ?? H.current ?? q.current;
|
|
115
115
|
return {
|
|
116
116
|
"x-inkeep-client-timezone": Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
117
117
|
"x-inkeep-client-timestamp": (/* @__PURE__ */ new Date()).toISOString(),
|
|
118
118
|
"x-inkeep-invocation-type": "chat_widget",
|
|
119
119
|
...N ? { "x-inkeep-app-id": N } : {},
|
|
120
120
|
...e ? { Authorization: `Bearer ${e}` } : {},
|
|
121
|
-
...
|
|
121
|
+
...Y.current ? { "inkeep-filters": Y.current } : {},
|
|
122
122
|
...Se.current
|
|
123
123
|
};
|
|
124
124
|
},
|
|
@@ -133,8 +133,8 @@ const Ht = () => {
|
|
|
133
133
|
messages: t ? [t] : [],
|
|
134
134
|
trigger: e.trigger,
|
|
135
135
|
messageId: e.messageId,
|
|
136
|
-
...
|
|
137
|
-
...
|
|
136
|
+
...j.current ? { userProperties: j.current } : {},
|
|
137
|
+
...V.current ? { properties: V.current } : {}
|
|
138
138
|
},
|
|
139
139
|
headers: {
|
|
140
140
|
...e.headers,
|
|
@@ -146,17 +146,17 @@ const Ht = () => {
|
|
|
146
146
|
requestContext: ve
|
|
147
147
|
}
|
|
148
148
|
}),
|
|
149
|
-
[Ie, ve, N,
|
|
149
|
+
[Ie, ve, N, K]
|
|
150
150
|
), {
|
|
151
151
|
messages: T,
|
|
152
|
-
sendMessage:
|
|
153
|
-
addToolApprovalResponse:
|
|
152
|
+
sendMessage: Q,
|
|
153
|
+
addToolApprovalResponse: X,
|
|
154
154
|
status: Ae,
|
|
155
155
|
setMessages: m,
|
|
156
156
|
stop: B,
|
|
157
157
|
error: D
|
|
158
|
-
} =
|
|
159
|
-
transport:
|
|
158
|
+
} = it({
|
|
159
|
+
transport: Ve,
|
|
160
160
|
onData(e) {
|
|
161
161
|
x(e.type, e.data);
|
|
162
162
|
},
|
|
@@ -177,53 +177,53 @@ const Ht = () => {
|
|
|
177
177
|
},
|
|
178
178
|
onError(e) {
|
|
179
179
|
console.error("onError", { code: e.code, message: e.message });
|
|
180
|
-
const l =
|
|
180
|
+
const l = Ue || K ? null : Et(e);
|
|
181
181
|
if (l !== null && I.current < 1) {
|
|
182
182
|
I.current++;
|
|
183
|
-
const
|
|
183
|
+
const o = W.current, s = P.current;
|
|
184
184
|
(async () => {
|
|
185
185
|
if (l === "session" && ue) {
|
|
186
|
-
const
|
|
187
|
-
if (!
|
|
188
|
-
|
|
186
|
+
const r = await de();
|
|
187
|
+
if (!r) throw new Error("Auth token refresh failed");
|
|
188
|
+
H.current = r;
|
|
189
189
|
} else if (l === "session") {
|
|
190
|
-
const
|
|
191
|
-
|
|
190
|
+
const r = await fe();
|
|
191
|
+
r && (q.current = r);
|
|
192
192
|
} else
|
|
193
|
-
|
|
194
|
-
if (
|
|
195
|
-
|
|
193
|
+
d();
|
|
194
|
+
if (o) {
|
|
195
|
+
X(o);
|
|
196
196
|
return;
|
|
197
197
|
}
|
|
198
|
-
|
|
199
|
-
let a = [...
|
|
198
|
+
s && (m((r) => {
|
|
199
|
+
let a = [...r];
|
|
200
200
|
return a.at(-1)?.role === "assistant" && (a = a.slice(0, -1)), a.at(-1)?.role === "user" && (a = a.slice(0, -1)), a;
|
|
201
|
-
}),
|
|
201
|
+
}), Q(
|
|
202
202
|
{
|
|
203
|
-
id:
|
|
203
|
+
id: s.messageId,
|
|
204
204
|
parts: [
|
|
205
|
-
...
|
|
206
|
-
...
|
|
205
|
+
...s.content.trim() ? [{ type: "text", text: s.content }] : [],
|
|
206
|
+
...s.files ?? []
|
|
207
207
|
]
|
|
208
208
|
},
|
|
209
|
-
{ body:
|
|
209
|
+
{ body: s.body }
|
|
210
210
|
));
|
|
211
211
|
})().catch(() => {
|
|
212
|
-
I.current = 0,
|
|
213
|
-
const a = [...
|
|
212
|
+
I.current = 0, d(), m((r) => {
|
|
213
|
+
const a = [...r], f = a[a.length - 1];
|
|
214
214
|
if (!f) return a;
|
|
215
|
-
const
|
|
215
|
+
const u = oe;
|
|
216
216
|
return f.role === "user" ? a.push({
|
|
217
217
|
id: F(16),
|
|
218
218
|
role: "assistant",
|
|
219
|
-
parts: [{ type: "text", text:
|
|
220
|
-
}) : f.parts = [{ type: "text", text:
|
|
219
|
+
parts: [{ type: "text", text: u }]
|
|
220
|
+
}) : f.parts = [{ type: "text", text: u }], a;
|
|
221
221
|
});
|
|
222
222
|
});
|
|
223
223
|
return;
|
|
224
224
|
}
|
|
225
|
-
I.current = 0, l !== null &&
|
|
226
|
-
const t =
|
|
225
|
+
I.current = 0, l !== null && d();
|
|
226
|
+
const t = St(e) || Ne(e), n = je(e);
|
|
227
227
|
if (g({
|
|
228
228
|
eventName: "chat_error",
|
|
229
229
|
properties: {
|
|
@@ -233,106 +233,106 @@ const Ht = () => {
|
|
|
233
233
|
}
|
|
234
234
|
}), t) {
|
|
235
235
|
L(
|
|
236
|
-
{ title: "Request failed", message: n },
|
|
236
|
+
{ title: n === U ? "Message too large" : n === Be ? "Rate limit reached" : "Request failed", message: n },
|
|
237
237
|
Pe
|
|
238
|
-
), m((
|
|
239
|
-
let
|
|
240
|
-
return
|
|
238
|
+
), m((p) => {
|
|
239
|
+
let r = [...p];
|
|
240
|
+
return r.at(-1)?.role === "assistant" && (r = r.slice(0, -1)), r.at(-1)?.role === "user" && (r = r.slice(0, -1)), r;
|
|
241
241
|
});
|
|
242
242
|
const s = P.current?.content;
|
|
243
|
-
s && A(s),
|
|
243
|
+
s && A(s), se.current = e;
|
|
244
244
|
return;
|
|
245
245
|
}
|
|
246
|
-
m((
|
|
247
|
-
const
|
|
248
|
-
return
|
|
246
|
+
m((o) => {
|
|
247
|
+
const s = [...o], p = s[s.length - 1];
|
|
248
|
+
return p && (p.role === "user" ? s.push({
|
|
249
249
|
id: F(16),
|
|
250
250
|
role: "assistant",
|
|
251
251
|
parts: [{ type: "text", text: n }]
|
|
252
|
-
}) :
|
|
252
|
+
}) : p.parts = [{ type: "text", text: n }]), s;
|
|
253
253
|
});
|
|
254
254
|
}
|
|
255
255
|
}), we = i(R);
|
|
256
256
|
_(() => {
|
|
257
257
|
const e = we.current;
|
|
258
|
-
we.current = R, e !== R && (B(), b(null), m([]), y(""), A(""),
|
|
259
|
-
}, [R, B, m, y,
|
|
260
|
-
const Te = Ae === "submitted",
|
|
261
|
-
const e = (
|
|
262
|
-
if (!
|
|
263
|
-
const
|
|
264
|
-
return typeof
|
|
265
|
-
}, t = [...T ?? []].reverse().find((
|
|
258
|
+
we.current = R, e !== R && (B(), b(null), m([]), y(""), A(""), J([]), d());
|
|
259
|
+
}, [R, B, m, y, d]);
|
|
260
|
+
const Te = Ae === "submitted", Z = Ae === "streaming", We = Oe(() => {
|
|
261
|
+
const e = (o) => {
|
|
262
|
+
if (!o || typeof o != "object") return !1;
|
|
263
|
+
const s = o;
|
|
264
|
+
return typeof s.type == "string" && s.type.startsWith("tool-");
|
|
265
|
+
}, t = [...T ?? []].reverse().find((o) => o.role === "assistant");
|
|
266
266
|
if (!t) return !1;
|
|
267
267
|
const n = t.parts?.at(-1);
|
|
268
|
-
return !(!e(n) || n.state !== "output-available" || !n.approval?.id ||
|
|
269
|
-
}, [T,
|
|
268
|
+
return !(!e(n) || n.state !== "output-available" || !n.approval?.id || Z);
|
|
269
|
+
}, [T, Z]), [Ye, ee] = k(!1), be = Z || We && !Ye, Me = Te || be, Je = T.length === 0, te = !S.trim() && C.length === 0 || Me, Qe = ft("(max-width: 768px)"), [Xe, b] = k(null), se = i(null);
|
|
270
270
|
_(() => {
|
|
271
271
|
if (D) {
|
|
272
|
-
if (
|
|
273
|
-
|
|
272
|
+
if (se.current === D) {
|
|
273
|
+
se.current = null;
|
|
274
274
|
return;
|
|
275
275
|
}
|
|
276
276
|
b(D);
|
|
277
277
|
}
|
|
278
278
|
}, [D]);
|
|
279
|
-
const
|
|
279
|
+
const Ze = () => b(null), { inputNotification: et, showInputNotification: L, clearInputNotification: tt } = Ct(), _e = i(null);
|
|
280
280
|
_(() => {
|
|
281
|
-
|
|
281
|
+
Ge?.(S);
|
|
282
282
|
}, [S]);
|
|
283
|
-
const
|
|
284
|
-
e.key === "Enter" && !e.shiftKey && !
|
|
285
|
-
},
|
|
286
|
-
if (
|
|
283
|
+
const st = (e) => {
|
|
284
|
+
e.key === "Enter" && !e.shiftKey && !te && !e.nativeEvent.isComposing && (e.preventDefault(), re());
|
|
285
|
+
}, re = async (e = S) => {
|
|
286
|
+
if (te && (!e || e.trim().length === 0) && C.length === 0 || !e.trim() && !C.length && !h.current?.length)
|
|
287
287
|
return;
|
|
288
288
|
if (Tt({
|
|
289
289
|
text: e,
|
|
290
|
-
rawFileBytes: C.reduce((f,
|
|
290
|
+
rawFileBytes: C.reduce((f, u) => f + u.size, 0),
|
|
291
291
|
encodedPartsBytes: (h.current ?? []).reduce(
|
|
292
|
-
(f,
|
|
292
|
+
(f, u) => f + u.url.length,
|
|
293
293
|
0
|
|
294
294
|
)
|
|
295
295
|
}) > bt) {
|
|
296
296
|
L(
|
|
297
|
-
{ title: "Message too large", message:
|
|
297
|
+
{ title: "Message too large", message: U },
|
|
298
298
|
Pe
|
|
299
299
|
);
|
|
300
300
|
return;
|
|
301
301
|
}
|
|
302
302
|
const t = C;
|
|
303
|
-
|
|
303
|
+
J([]), A(""), I.current = 0, W.current = null, ee(!1);
|
|
304
304
|
let n = c;
|
|
305
305
|
n || (n = `conv_${F(16)}`, y(n));
|
|
306
|
-
const
|
|
307
|
-
|
|
306
|
+
const o = F(21);
|
|
307
|
+
Le(n), await g({
|
|
308
308
|
eventName: "user_message_submitted",
|
|
309
309
|
properties: {
|
|
310
310
|
conversationId: n,
|
|
311
|
-
messageId:
|
|
311
|
+
messageId: o
|
|
312
312
|
}
|
|
313
313
|
});
|
|
314
|
-
const
|
|
314
|
+
const s = h.current;
|
|
315
315
|
h.current = void 0;
|
|
316
|
-
let
|
|
316
|
+
let p = [];
|
|
317
317
|
if (t.length > 0)
|
|
318
318
|
try {
|
|
319
|
-
|
|
319
|
+
p = await Promise.all(
|
|
320
320
|
t.map((f) => {
|
|
321
|
-
const
|
|
322
|
-
return new Promise((
|
|
321
|
+
const u = ct(f);
|
|
322
|
+
return new Promise((at, xe) => {
|
|
323
323
|
const M = new FileReader();
|
|
324
324
|
M.onload = () => {
|
|
325
325
|
if (typeof M.result != "string") {
|
|
326
|
-
xe(new Error(`Failed to read file "${
|
|
326
|
+
xe(new Error(`Failed to read file "${u.name}"`));
|
|
327
327
|
return;
|
|
328
328
|
}
|
|
329
|
-
|
|
329
|
+
at({
|
|
330
330
|
type: "file",
|
|
331
331
|
url: M.result,
|
|
332
|
-
mediaType:
|
|
333
|
-
filename:
|
|
332
|
+
mediaType: u.type,
|
|
333
|
+
filename: u.name
|
|
334
334
|
});
|
|
335
|
-
}, M.onerror = () => xe(new Error(`Failed to read file "${
|
|
335
|
+
}, M.onerror = () => xe(new Error(`Failed to read file "${u.name}"`)), M.readAsDataURL(u);
|
|
336
336
|
});
|
|
337
337
|
})
|
|
338
338
|
);
|
|
@@ -343,27 +343,27 @@ const Ht = () => {
|
|
|
343
343
|
});
|
|
344
344
|
return;
|
|
345
345
|
}
|
|
346
|
-
const
|
|
346
|
+
const r = p.length || s?.length ? [...p, ...s ?? []] : void 0, a = [
|
|
347
347
|
...e.trim() ? [{ type: "text", text: e }] : [],
|
|
348
|
-
...
|
|
348
|
+
...r ?? []
|
|
349
349
|
];
|
|
350
350
|
P.current = {
|
|
351
351
|
content: e,
|
|
352
|
-
messageId:
|
|
352
|
+
messageId: o,
|
|
353
353
|
body: { conversationId: n },
|
|
354
|
-
files:
|
|
355
|
-
},
|
|
356
|
-
},
|
|
354
|
+
files: r
|
|
355
|
+
}, Q({ id: o, parts: a }, { body: { conversationId: n } });
|
|
356
|
+
}, rt = $(
|
|
357
357
|
(e) => {
|
|
358
|
-
I.current = 0,
|
|
358
|
+
I.current = 0, W.current = e, ee(!1), X(e);
|
|
359
359
|
},
|
|
360
|
-
[
|
|
361
|
-
),
|
|
362
|
-
|
|
360
|
+
[X]
|
|
361
|
+
), ne = $(() => {
|
|
362
|
+
ee(!0), B().then(() => {
|
|
363
363
|
x("aborted", { conversationId: c });
|
|
364
364
|
});
|
|
365
365
|
}, [B, c, x]), ke = () => {
|
|
366
|
-
|
|
366
|
+
Ze(), m([]), y(""), d(), h.current = w?.length ? w : void 0, g({
|
|
367
367
|
eventName: "chat_clear_button_clicked",
|
|
368
368
|
properties: {
|
|
369
369
|
conversationId: c
|
|
@@ -371,16 +371,16 @@ const Ht = () => {
|
|
|
371
371
|
});
|
|
372
372
|
}, E = $(
|
|
373
373
|
(e, l) => {
|
|
374
|
-
b(null), m(l), y(e),
|
|
374
|
+
b(null), m(l), y(e), d(), h.current = void 0;
|
|
375
375
|
},
|
|
376
|
-
[m, y,
|
|
376
|
+
[m, y, d]
|
|
377
377
|
), Fe = $(
|
|
378
378
|
async (e, l) => {
|
|
379
|
-
|
|
379
|
+
ne(), E(e, []), Ee(!0);
|
|
380
380
|
try {
|
|
381
381
|
const t = await Ce(e, l);
|
|
382
382
|
if (t === null) return !1;
|
|
383
|
-
const
|
|
383
|
+
const o = t[t.length - 1]?.role === "user" ? [
|
|
384
384
|
...t,
|
|
385
385
|
{
|
|
386
386
|
id: F(16),
|
|
@@ -393,14 +393,14 @@ const Ht = () => {
|
|
|
393
393
|
]
|
|
394
394
|
}
|
|
395
395
|
] : t;
|
|
396
|
-
return E(e,
|
|
396
|
+
return E(e, o), !0;
|
|
397
397
|
} finally {
|
|
398
398
|
l?.aborted || Ee(!1);
|
|
399
399
|
}
|
|
400
400
|
},
|
|
401
|
-
[E, Ce,
|
|
401
|
+
[E, Ce, ne]
|
|
402
402
|
);
|
|
403
|
-
|
|
403
|
+
gt({
|
|
404
404
|
conversationId: v.conversationId,
|
|
405
405
|
fetchedConversation: v.fetchedConversation,
|
|
406
406
|
effectiveAuthToken: me,
|
|
@@ -408,51 +408,51 @@ const Ht = () => {
|
|
|
408
408
|
loadAndRestoreSession: Fe,
|
|
409
409
|
onLoadFailed: () => E("", [])
|
|
410
410
|
});
|
|
411
|
-
const { openForm:
|
|
412
|
-
return
|
|
413
|
-
submitMessage:
|
|
411
|
+
const { openForm: nt } = vt(), ot = yt();
|
|
412
|
+
return ut(v.chatFunctionsRef, () => ({
|
|
413
|
+
submitMessage: re,
|
|
414
414
|
updateInputMessage(e) {
|
|
415
415
|
A(e);
|
|
416
416
|
},
|
|
417
417
|
clearChat: ke,
|
|
418
418
|
openForm: (e) => {
|
|
419
|
-
|
|
419
|
+
ot?.setView("chat"), nt(e, void 0);
|
|
420
420
|
},
|
|
421
421
|
focusInput: () => {
|
|
422
422
|
_e.current?.focus();
|
|
423
423
|
}
|
|
424
424
|
})), {
|
|
425
425
|
messages: T,
|
|
426
|
-
sendMessage:
|
|
427
|
-
addToolApprovalResponse:
|
|
426
|
+
sendMessage: Q,
|
|
427
|
+
addToolApprovalResponse: rt,
|
|
428
428
|
isLoading: Te,
|
|
429
429
|
isStreaming: be,
|
|
430
430
|
isBusy: Me,
|
|
431
|
-
error:
|
|
431
|
+
error: Xe,
|
|
432
432
|
setError: b,
|
|
433
|
-
isSubmitDisabled:
|
|
433
|
+
isSubmitDisabled: te,
|
|
434
434
|
input: S,
|
|
435
|
-
handleInputChange:
|
|
436
|
-
handleInputKeyDown:
|
|
437
|
-
handleSubmit:
|
|
438
|
-
stop:
|
|
435
|
+
handleInputChange: $e,
|
|
436
|
+
handleInputKeyDown: st,
|
|
437
|
+
handleSubmit: re,
|
|
438
|
+
stop: ne,
|
|
439
439
|
clear: ke,
|
|
440
440
|
inputRef: _e,
|
|
441
|
-
isMobile:
|
|
441
|
+
isMobile: Qe,
|
|
442
442
|
files: C,
|
|
443
|
-
setFiles:
|
|
444
|
-
isNewChat:
|
|
443
|
+
setFiles: J,
|
|
444
|
+
isNewChat: Je,
|
|
445
445
|
conversationId: c,
|
|
446
446
|
restoreSession: E,
|
|
447
447
|
loadAndRestoreSession: Fe,
|
|
448
|
-
isSessionLoading:
|
|
448
|
+
isSessionLoading: qe,
|
|
449
449
|
authToken: R ? le : pe,
|
|
450
450
|
refreshSession: R ? de : fe,
|
|
451
451
|
getCaptchaHeader: O,
|
|
452
|
-
invalidateCaptcha:
|
|
453
|
-
inputNotification:
|
|
452
|
+
invalidateCaptcha: d,
|
|
453
|
+
inputNotification: et,
|
|
454
454
|
showInputNotification: L,
|
|
455
|
-
clearInputNotification:
|
|
455
|
+
clearInputNotification: tt
|
|
456
456
|
};
|
|
457
457
|
};
|
|
458
458
|
export {
|