@inkeep/agents-ui 0.15.20 → 0.15.21
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/primitives/components/embedded-chat/use-inkeep-chat.cjs +2 -2
- package/dist/primitives/components/embedded-chat/use-inkeep-chat.js +231 -212
- package/dist/primitives/hooks/use-anonymous-session.cjs +1 -1
- package/dist/primitives/hooks/use-anonymous-session.d.ts +2 -1
- package/dist/primitives/hooks/use-anonymous-session.js +79 -65
- package/dist/primitives/hooks/use-auth-token.cjs +1 -0
- package/dist/primitives/hooks/use-auth-token.d.ts +5 -0
- package/dist/primitives/hooks/use-auth-token.js +54 -0
- package/dist/primitives/providers/base-events-provider.cjs +1 -1
- package/dist/primitives/providers/base-events-provider.js +1 -1
- package/dist/primitives/providers/chat-history-provider.cjs +1 -1
- package/dist/primitives/providers/chat-history-provider.js +90 -85
- package/dist/types/config/base.d.ts +7 -0
- package/package.json +1 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const He=require("@ai-sdk/react"),We=require("ai"),t=require("react"),$e=require("../modal/modal-provider.cjs"),je=require("../../providers/chat-bubble-provider.cjs"),ze=require("../../providers/sidebar-chat-provider.cjs"),Je=require("../../providers/config-provider.cjs"),Ke=require("./use-captcha.cjs"),Ge=require("../../hooks/use-media-query.cjs"),Qe=require("../../hooks/use-anonymous-session.cjs"),Ve=require("../../hooks/use-auth-token.cjs"),Ze=require("../../hooks/use-conversation-loader.cjs"),x=require("../../utils/generate-uid.cjs"),Xe=require("../../providers/base-events-provider.cjs"),Ye=require("../../providers/chat-form-provider.cjs"),et=require("../../providers/widget-provider.cjs"),tt=require("@radix-ui/react-use-controllable-state"),st=require("../../hooks/use-streaming-events.cjs"),rt=require("../../hooks/use-inkeep-api-client.cjs");function nt(f){const h=f.message??"";let s=Number(f.code)||Number(f.statusCode);if(Number.isNaN(s))try{s=Number(JSON.parse(h).status)}catch{}const l=rt.parseAuthError(s,{detail:h});return l!==null?l:s===401?"session":null}const P=`Hmm..
|
|
2
2
|
|
|
3
|
-
It seems I might be having some issues right now. Please clear the chat and try again.`,
|
|
3
|
+
It seems I might be having some issues right now. Please clear the chat and try again.`,at=()=>{const{baseSettings:f,aiChatSettings:h}=Je.useInkeepConfig(),[s="",l]=tt.useControllableState({prop:h.conversationId,defaultProp:h.conversationId??""}),ve=$e.useModal(),ye=je.useOptionalChatBubble(),be=ze.useOptionalSidebarChat(),{logEvent:g}=Xe.useBaseEvents(),{setConversationId:Ce,emitToParent:k}=st.useStreamingEvents(),Q=t.useRef(s);t.useEffect(()=>{const e=Q.current;Q.current=s,e!==s&&g({eventName:"chat_conversation_changed",properties:{conversationId:s,previousConversationId:e}})},[s,g]);const[y,A]=t.useState(""),Se=e=>A(e.target.value),{shouldBypassCaptcha:V,filters:Z,privacyPreferences:Re,userProperties:N}=f,{authToken:I,refreshToken:X}=Ve.useAuthToken(),Y=!!f.getAuthToken,d=!!I,{onInputMessageChange:ke,filters:ee,baseUrl:E,agentUrl:Ae,context:te,headers:se,appId:b,apiKey:m}=h,Ie=ve?.isOpen??ye?.isOpen??be?.isOpen??!0,{getCaptchaHeader:C,invalidate:c}=Ke.useCaptcha({baseUrl:E,shouldBypassCaptcha:V||!!m,shouldMakeInitialRequest:Ie}),re=t.useRef(C);re.current=C;const ne=Ae||`${E}/run/api/chat`,{sessionToken:O,refreshSession:_}=Qe.useAnonymousSession({baseUrl:E,appId:b,getCaptchaHeader:C,invalidateCaptcha:c,optOutAllAnalytics:Re?.optOutAllAnalytics,enabled:!d}),{loadConversation:ae}=Ze.useConversationLoader({baseUrl:E,appId:b,authToken:m??(d?I:O),getCaptchaHeader:C,invalidateCaptcha:c,refreshSession:m||d?void 0:_}),[Ee,oe]=t.useState(!1),F=t.useRef(null);F.current=O;const U=t.useRef(null);U.current=I;const D=t.useRef(void 0);D.current=N&&Object.keys(N).length>0?JSON.stringify(N):void 0;const v=t.useRef(0),ie=t.useRef(null),B=t.useRef(null),ue=t.useRef(se);ue.current=se;const L=t.useRef(void 0);L.current=Z||ee?JSON.stringify({...Z,...ee}):void 0;const we=e=>{switch(e.code){case 400:return e.message;case 401:return Y?"Authentication failed. Please try again.":P;case 403:return`There seems to be a configuration error. Please contact ${f.organizationDisplayName??"Administrator"}`;default:return P}},[Te,S]=t.useState([]),[Me,w]=t.useState(null),qe=t.useMemo(()=>new We.DefaultChatTransport({api:ne,headers:()=>{const e=m??U.current??F.current;return{"x-inkeep-client-timezone":Intl.DateTimeFormat().resolvedOptions().timeZone,"x-inkeep-client-timestamp":new Date().toISOString(),...b?{"x-inkeep-app-id":b}:{},...e?{Authorization:`Bearer ${e}`}:{},...L.current?{"inkeep-filters":L.current}:{},...D.current?{"x-inkeep-user-properties":D.current}:{},...ue.current}},prepareSendMessagesRequest:async e=>{const r=await re.current();return{body:{...e.body,id:e.id,messages:e.messages,trigger:e.trigger,messageId:e.messageId},headers:{...e.headers,...r}}},body:{requestContext:te}}),[ne,te,b,m]),{messages:T,sendMessage:H,addToolApprovalResponse:W,status:ce,setMessages:p,stop:M,error:$}=He.useChat({transport:qe,onData(e){k(e.type,e.data)},async onFinish(){k("completion",{conversationId:s}),await g({eventName:"assistant_message_received",properties:{conversationId:s}}),g({eventName:"assistant_answer_displayed",properties:{conversationId:s}})},onError(e){console.error("onError",{code:e.code,message:e.message});const r=V||m?null:nt(e);if(r!==null&&v.current<1){v.current++;const o=B.current,a=ie.current;(async()=>{if(r==="session"&&Y){const n=await X();if(!n)throw new Error("Auth token refresh failed");U.current=n}else if(r==="session"){const n=await _();n&&(F.current=n)}else c();if(o){W(o);return}a&&(p(n=>{let u=[...n];return u.at(-1)?.role==="assistant"&&(u=u.slice(0,-1)),u.at(-1)?.role==="user"&&(u=u.slice(0,-1)),u}),H({text:a.content},{body:a.body}))})().catch(()=>{v.current=0,c(),p(n=>{const u=[...n],G=u[u.length-1];if(!G)return u;const me=P;return G.role==="user"?u.push({id:x.generateUid(16),role:"assistant",parts:[{type:"text",text:me}]}):G.parts=[{type:"text",text:me}],u})});return}v.current=0,r!==null&&c(),g({eventName:"chat_error",properties:{conversationId:s,error:e.message}}),p(o=>{const a=[...o],i=a[a.length-1];if(i){const n=we(e);i.role==="user"?a.push({id:x.generateUid(16),role:"assistant",parts:[{type:"text",text:n}]}):i.parts=[{type:"text",text:n}]}return a})}}),le=t.useRef(d);t.useEffect(()=>{const e=le.current;le.current=d,e!==d&&(M(),R(null),p([]),l(""),A(""),S([]),w(null),c())},[d,M,p,l,c]);const de=ce==="submitted",j=ce==="streaming",xe=t.useMemo(()=>{const e=i=>{if(!i||typeof i!="object")return!1;const n=i;return typeof n.type=="string"&&n.type.startsWith("tool-")},o=[...T??[]].reverse().find(i=>i.role==="assistant");if(!o)return!1;const a=o.parts?.at(-1);return!(!e(a)||a.state!=="output-available"||!a.approval?.id||j)},[T,j]),pe=j||xe,fe=de||pe,Pe=T.length===0,z=!y.trim()||fe,Ne=Ge.useMediaQuery("(max-width: 768px)"),[Oe,R]=t.useState(null);t.useEffect(()=>{$&&R($)},[$]);const _e=()=>R(null),he=t.useRef(null);t.useEffect(()=>{ke?.(y)},[y]);const Fe=e=>{e.key==="Enter"&&!e.shiftKey&&!z&&!e.nativeEvent.isComposing&&(e.preventDefault(),J())},J=async(e=y)=>{if(z&&(!e||e.trim().length===0))return;S([]),A(""),v.current=0,B.current=null,await g({eventName:"user_message_submitted",properties:{conversationId:s}});let r=s;r||(r=`conv_${x.generateUid(16)}`,l(r)),Ce(r),ie.current={content:e,body:{conversationId:r}},H({text:e},{body:{conversationId:r}})},Ue=t.useCallback(e=>{v.current=0,B.current=e,W(e)},[W]),K=t.useCallback(()=>{M().then(()=>{k("aborted",{conversationId:s})})},[M,s,k]),ge=()=>{_e(),p([]),l(""),S([]),w(null),c(),g({eventName:"chat_clear_button_clicked",properties:{conversationId:s}})},q=t.useCallback((e,r)=>{R(null),p(r),l(e),S([]),w(null),c()},[p,l,c]),De=t.useCallback(async(e,r)=>{K(),q(e,[]),oe(!0);try{const o=await ae(e,r),a=o?.[o.length-1],i=o!==null&&a?.role==="user"?[...o,{id:x.generateUid(16),role:"assistant",parts:[{type:"text",text:"This session was interrupted. Please check back in a few minutes or start a new conversation."}]}]:o;i!==null&&q(e,i)}finally{r?.aborted||oe(!1)}},[q,ae,K]),{openForm:Be}=Ye.useChatForm(),Le=et.useWidget();return t.useImperativeHandle(h.chatFunctionsRef,()=>({submitMessage:J,updateInputMessage(e){A(e)},clearChat:ge,openForm:e=>{Le?.setView("chat"),Be(e,void 0)},focusInput:()=>{he.current?.focus()}})),{messages:T,sendMessage:H,addToolApprovalResponse:Ue,isLoading:de,isStreaming:pe,isBusy:fe,error:Oe,setError:R,isSubmitDisabled:z,input:y,handleInputChange:Se,handleInputKeyDown:Fe,handleSubmit:J,stop:K,clear:ge,inputRef:he,isMobile:Ne,messageAttachments:Te,setMessageAttachments:S,selectedWorkflow:Me,setSelectedWorkflow:w,isNewChat:Pe,conversationId:s,restoreSession:q,loadAndRestoreSession:De,isSessionLoading:Ee,sessionToken:d?I:O,refreshSession:d?X:_,getCaptchaHeader:C,invalidateCaptcha:c}};exports.DEFAULT_ERROR_MESSAGE=P;exports.useInkeepChat=at;
|
|
@@ -1,108 +1,118 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useChat as
|
|
3
|
-
import { DefaultChatTransport as
|
|
4
|
-
import { useRef as
|
|
5
|
-
import { useModal as
|
|
6
|
-
import { useOptionalChatBubble as
|
|
7
|
-
import { useOptionalSidebarChat as
|
|
8
|
-
import { useInkeepConfig as
|
|
9
|
-
import { useCaptcha as
|
|
10
|
-
import { useMediaQuery as
|
|
11
|
-
import { useAnonymousSession as
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
2
|
+
import { useChat as Je } from "@ai-sdk/react";
|
|
3
|
+
import { DefaultChatTransport as Ke } from "ai";
|
|
4
|
+
import { useRef as c, useEffect as O, useState as A, useMemo as Ce, useCallback as _, useImperativeHandle as je } from "react";
|
|
5
|
+
import { useModal as Ge } from "../modal/modal-provider.js";
|
|
6
|
+
import { useOptionalChatBubble as Qe } from "../../providers/chat-bubble-provider.js";
|
|
7
|
+
import { useOptionalSidebarChat as Ve } from "../../providers/sidebar-chat-provider.js";
|
|
8
|
+
import { useInkeepConfig as Ze } from "../../providers/config-provider.js";
|
|
9
|
+
import { useCaptcha as Xe } from "./use-captcha.js";
|
|
10
|
+
import { useMediaQuery as Ye } from "../../hooks/use-media-query.js";
|
|
11
|
+
import { useAnonymousSession as et } from "../../hooks/use-anonymous-session.js";
|
|
12
|
+
import { useAuthToken as tt } from "../../hooks/use-auth-token.js";
|
|
13
|
+
import { useConversationLoader as st } from "../../hooks/use-conversation-loader.js";
|
|
14
|
+
import { generateUid as F } from "../../utils/generate-uid.js";
|
|
15
|
+
import { useBaseEvents as rt } from "../../providers/base-events-provider.js";
|
|
16
|
+
import { useChatForm as nt } from "../../providers/chat-form-provider.js";
|
|
17
|
+
import { useWidget as ot } from "../../providers/widget-provider.js";
|
|
18
|
+
import { useControllableState as at } from "@radix-ui/react-use-controllable-state";
|
|
19
|
+
import { useStreamingEvents as it } from "../../hooks/use-streaming-events.js";
|
|
20
|
+
import { parseAuthError as ct } from "../../hooks/use-inkeep-api-client.js";
|
|
21
|
+
function ut(m) {
|
|
22
|
+
const f = m.message ?? "";
|
|
23
|
+
let t = Number(m.code) || Number(m.statusCode);
|
|
23
24
|
if (Number.isNaN(t))
|
|
24
25
|
try {
|
|
25
|
-
t = Number(JSON.parse(
|
|
26
|
+
t = Number(JSON.parse(f).status);
|
|
26
27
|
} catch {
|
|
27
28
|
}
|
|
28
|
-
const
|
|
29
|
-
return
|
|
29
|
+
const l = ct(t, { detail: f });
|
|
30
|
+
return l !== null ? l : t === 401 ? "session" : null;
|
|
30
31
|
}
|
|
31
|
-
const
|
|
32
|
+
const Z = `Hmm..
|
|
32
33
|
|
|
33
|
-
It seems I might be having some issues right now. Please clear the chat and try again.`,
|
|
34
|
-
const { baseSettings:
|
|
35
|
-
prop:
|
|
36
|
-
defaultProp:
|
|
37
|
-
}),
|
|
38
|
-
|
|
39
|
-
const e =
|
|
40
|
-
|
|
34
|
+
It seems I might be having some issues right now. Please clear the chat and try again.`, xt = () => {
|
|
35
|
+
const { baseSettings: m, aiChatSettings: f } = Ze(), [t = "", l] = at({
|
|
36
|
+
prop: f.conversationId,
|
|
37
|
+
defaultProp: f.conversationId ?? ""
|
|
38
|
+
}), Se = Ge(), ke = Qe(), Ae = Ve(), { logEvent: h } = rt(), { setConversationId: Ie, emitToParent: I } = it(), X = c(t);
|
|
39
|
+
O(() => {
|
|
40
|
+
const e = X.current;
|
|
41
|
+
X.current = t, e !== t && h({
|
|
41
42
|
eventName: "chat_conversation_changed",
|
|
42
43
|
properties: {
|
|
43
44
|
conversationId: t,
|
|
44
45
|
previousConversationId: e
|
|
45
46
|
}
|
|
46
47
|
});
|
|
47
|
-
}, [t,
|
|
48
|
-
const [
|
|
49
|
-
onInputMessageChange:
|
|
50
|
-
filters:
|
|
51
|
-
baseUrl:
|
|
52
|
-
agentUrl:
|
|
53
|
-
context:
|
|
54
|
-
headers:
|
|
55
|
-
appId:
|
|
56
|
-
apiKey:
|
|
57
|
-
} =
|
|
58
|
-
baseUrl:
|
|
59
|
-
shouldBypassCaptcha:
|
|
60
|
-
shouldMakeInitialRequest:
|
|
61
|
-
}),
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
baseUrl:
|
|
65
|
-
appId:
|
|
66
|
-
getCaptchaHeader:
|
|
67
|
-
invalidateCaptcha:
|
|
68
|
-
optOutAllAnalytics:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
refreshSession:
|
|
77
|
-
}), [
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
const
|
|
48
|
+
}, [t, h]);
|
|
49
|
+
const [y, w] = A(""), we = (e) => w(e.target.value), { shouldBypassCaptcha: Y, filters: ee, privacyPreferences: Re, userProperties: P } = m, { authToken: R, refreshToken: te } = tt(), se = !!m.getAuthToken, p = !!R, {
|
|
50
|
+
onInputMessageChange: Te,
|
|
51
|
+
filters: re,
|
|
52
|
+
baseUrl: T,
|
|
53
|
+
agentUrl: Me,
|
|
54
|
+
context: ne,
|
|
55
|
+
headers: oe,
|
|
56
|
+
appId: b,
|
|
57
|
+
apiKey: g
|
|
58
|
+
} = f, xe = Se?.isOpen ?? ke?.isOpen ?? Ae?.isOpen ?? !0, { getCaptchaHeader: C, invalidate: u } = Xe({
|
|
59
|
+
baseUrl: T,
|
|
60
|
+
shouldBypassCaptcha: Y || !!g,
|
|
61
|
+
shouldMakeInitialRequest: xe
|
|
62
|
+
}), ae = c(C);
|
|
63
|
+
ae.current = C;
|
|
64
|
+
const ie = Me || `${T}/run/api/chat`, { sessionToken: D, refreshSession: B } = et({
|
|
65
|
+
baseUrl: T,
|
|
66
|
+
appId: b,
|
|
67
|
+
getCaptchaHeader: C,
|
|
68
|
+
invalidateCaptcha: u,
|
|
69
|
+
optOutAllAnalytics: Re?.optOutAllAnalytics,
|
|
70
|
+
enabled: !p
|
|
71
|
+
}), { loadConversation: ce } = st({
|
|
72
|
+
baseUrl: T,
|
|
73
|
+
appId: b,
|
|
74
|
+
authToken: g ?? (p ? R : D),
|
|
75
|
+
getCaptchaHeader: C,
|
|
76
|
+
invalidateCaptcha: u,
|
|
77
|
+
refreshSession: g || p ? void 0 : B
|
|
78
|
+
}), [Ee, ue] = A(!1), H = c(null);
|
|
79
|
+
H.current = D;
|
|
80
|
+
const L = c(null);
|
|
81
|
+
L.current = R;
|
|
82
|
+
const U = c(void 0);
|
|
83
|
+
U.current = P && Object.keys(P).length > 0 ? JSON.stringify(P) : void 0;
|
|
84
|
+
const v = c(0), le = c(null), W = c(null), pe = c(oe);
|
|
85
|
+
pe.current = oe;
|
|
86
|
+
const $ = c(void 0);
|
|
87
|
+
$.current = ee || re ? JSON.stringify({ ...ee, ...re }) : void 0;
|
|
88
|
+
const Ne = (e) => {
|
|
84
89
|
switch (e.code) {
|
|
85
90
|
case 400:
|
|
86
91
|
return e.message;
|
|
92
|
+
case 401:
|
|
93
|
+
return se ? "Authentication failed. Please try again." : Z;
|
|
87
94
|
case 403:
|
|
88
|
-
return `There seems to be a configuration error. Please contact ${
|
|
95
|
+
return `There seems to be a configuration error. Please contact ${m.organizationDisplayName ?? "Administrator"}`;
|
|
89
96
|
default:
|
|
90
|
-
return
|
|
97
|
+
return Z;
|
|
91
98
|
}
|
|
92
|
-
}, [
|
|
93
|
-
() => new
|
|
94
|
-
api:
|
|
95
|
-
headers: () =>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
}, [Oe, S] = A([]), [_e, M] = A(null), Fe = Ce(
|
|
100
|
+
() => new Ke({
|
|
101
|
+
api: ie,
|
|
102
|
+
headers: () => {
|
|
103
|
+
const e = g ?? L.current ?? H.current;
|
|
104
|
+
return {
|
|
105
|
+
"x-inkeep-client-timezone": Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
106
|
+
"x-inkeep-client-timestamp": (/* @__PURE__ */ new Date()).toISOString(),
|
|
107
|
+
...b ? { "x-inkeep-app-id": b } : {},
|
|
108
|
+
...e ? { Authorization: `Bearer ${e}` } : {},
|
|
109
|
+
...$.current ? { "inkeep-filters": $.current } : {},
|
|
110
|
+
...U.current ? { "x-inkeep-user-properties": U.current } : {},
|
|
111
|
+
...pe.current
|
|
112
|
+
};
|
|
113
|
+
},
|
|
104
114
|
prepareSendMessagesRequest: async (e) => {
|
|
105
|
-
const s = await
|
|
115
|
+
const s = await ae.current();
|
|
106
116
|
return {
|
|
107
117
|
body: {
|
|
108
118
|
...e.body,
|
|
@@ -118,30 +128,30 @@ It seems I might be having some issues right now. Please clear the chat and try
|
|
|
118
128
|
};
|
|
119
129
|
},
|
|
120
130
|
body: {
|
|
121
|
-
requestContext:
|
|
131
|
+
requestContext: ne
|
|
122
132
|
}
|
|
123
133
|
}),
|
|
124
|
-
[
|
|
134
|
+
[ie, ne, b, g]
|
|
125
135
|
), {
|
|
126
|
-
messages:
|
|
127
|
-
sendMessage:
|
|
128
|
-
addToolApprovalResponse:
|
|
129
|
-
status:
|
|
130
|
-
setMessages:
|
|
131
|
-
stop:
|
|
132
|
-
error:
|
|
133
|
-
} =
|
|
134
|
-
transport:
|
|
136
|
+
messages: x,
|
|
137
|
+
sendMessage: q,
|
|
138
|
+
addToolApprovalResponse: z,
|
|
139
|
+
status: de,
|
|
140
|
+
setMessages: d,
|
|
141
|
+
stop: E,
|
|
142
|
+
error: J
|
|
143
|
+
} = Je({
|
|
144
|
+
transport: Fe,
|
|
135
145
|
onData(e) {
|
|
136
|
-
|
|
146
|
+
I(e.type, e.data);
|
|
137
147
|
},
|
|
138
148
|
async onFinish() {
|
|
139
|
-
|
|
149
|
+
I("completion", { conversationId: t }), await h({
|
|
140
150
|
eventName: "assistant_message_received",
|
|
141
151
|
properties: {
|
|
142
152
|
conversationId: t
|
|
143
153
|
}
|
|
144
|
-
}),
|
|
154
|
+
}), h({
|
|
145
155
|
eventName: "assistant_answer_displayed",
|
|
146
156
|
properties: {
|
|
147
157
|
conversationId: t
|
|
@@ -150,178 +160,187 @@ It seems I might be having some issues right now. Please clear the chat and try
|
|
|
150
160
|
},
|
|
151
161
|
onError(e) {
|
|
152
162
|
console.error("onError", { code: e.code, message: e.message });
|
|
153
|
-
const s =
|
|
154
|
-
if (s !== null &&
|
|
155
|
-
|
|
156
|
-
const
|
|
163
|
+
const s = Y || g ? null : ut(e);
|
|
164
|
+
if (s !== null && v.current < 1) {
|
|
165
|
+
v.current++;
|
|
166
|
+
const o = W.current, n = le.current;
|
|
157
167
|
(async () => {
|
|
158
|
-
if (s === "session") {
|
|
159
|
-
const
|
|
160
|
-
|
|
168
|
+
if (s === "session" && se) {
|
|
169
|
+
const r = await te();
|
|
170
|
+
if (!r) throw new Error("Auth token refresh failed");
|
|
171
|
+
L.current = r;
|
|
172
|
+
} else if (s === "session") {
|
|
173
|
+
const r = await B();
|
|
174
|
+
r && (H.current = r);
|
|
161
175
|
} else
|
|
162
|
-
|
|
163
|
-
if (
|
|
164
|
-
|
|
176
|
+
u();
|
|
177
|
+
if (o) {
|
|
178
|
+
z(o);
|
|
165
179
|
return;
|
|
166
180
|
}
|
|
167
|
-
|
|
168
|
-
let
|
|
169
|
-
return
|
|
170
|
-
}),
|
|
181
|
+
n && (d((r) => {
|
|
182
|
+
let i = [...r];
|
|
183
|
+
return i.at(-1)?.role === "assistant" && (i = i.slice(0, -1)), i.at(-1)?.role === "user" && (i = i.slice(0, -1)), i;
|
|
184
|
+
}), q({ text: n.content }, { body: n.body }));
|
|
171
185
|
})().catch(() => {
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
if (!
|
|
175
|
-
const
|
|
176
|
-
return
|
|
177
|
-
id:
|
|
186
|
+
v.current = 0, u(), d((r) => {
|
|
187
|
+
const i = [...r], V = i[i.length - 1];
|
|
188
|
+
if (!V) return i;
|
|
189
|
+
const be = Z;
|
|
190
|
+
return V.role === "user" ? i.push({
|
|
191
|
+
id: F(16),
|
|
178
192
|
role: "assistant",
|
|
179
|
-
parts: [{ type: "text", text:
|
|
180
|
-
}) :
|
|
193
|
+
parts: [{ type: "text", text: be }]
|
|
194
|
+
}) : V.parts = [{ type: "text", text: be }], i;
|
|
181
195
|
});
|
|
182
196
|
});
|
|
183
197
|
return;
|
|
184
198
|
}
|
|
185
|
-
|
|
199
|
+
v.current = 0, s !== null && u(), h({
|
|
186
200
|
eventName: "chat_error",
|
|
187
201
|
properties: {
|
|
188
202
|
conversationId: t,
|
|
189
203
|
error: e.message
|
|
190
204
|
}
|
|
191
|
-
}),
|
|
192
|
-
const
|
|
193
|
-
if (
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
id:
|
|
205
|
+
}), d((o) => {
|
|
206
|
+
const n = [...o], a = n[n.length - 1];
|
|
207
|
+
if (a) {
|
|
208
|
+
const r = Ne(e);
|
|
209
|
+
a.role === "user" ? n.push({
|
|
210
|
+
id: F(16),
|
|
197
211
|
role: "assistant",
|
|
198
|
-
parts: [{ type: "text", text:
|
|
199
|
-
}) :
|
|
212
|
+
parts: [{ type: "text", text: r }]
|
|
213
|
+
}) : a.parts = [{ type: "text", text: r }];
|
|
200
214
|
}
|
|
201
|
-
return
|
|
215
|
+
return n;
|
|
202
216
|
});
|
|
203
217
|
}
|
|
204
|
-
}),
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
218
|
+
}), me = c(p);
|
|
219
|
+
O(() => {
|
|
220
|
+
const e = me.current;
|
|
221
|
+
me.current = p, e !== p && (E(), k(null), d([]), l(""), w(""), S([]), M(null), u());
|
|
222
|
+
}, [p, E, d, l, u]);
|
|
223
|
+
const fe = de === "submitted", K = de === "streaming", Pe = Ce(() => {
|
|
224
|
+
const e = (a) => {
|
|
225
|
+
if (!a || typeof a != "object") return !1;
|
|
226
|
+
const r = a;
|
|
227
|
+
return typeof r.type == "string" && r.type.startsWith("tool-");
|
|
228
|
+
}, o = [...x ?? []].reverse().find((a) => a.role === "assistant");
|
|
229
|
+
if (!o) return !1;
|
|
230
|
+
const n = o.parts?.at(-1);
|
|
231
|
+
return !(!e(n) || n.state !== "output-available" || !n.approval?.id || K);
|
|
232
|
+
}, [x, K]), he = K || Pe, ge = fe || he, De = x.length === 0, j = !y.trim() || ge, Be = Ye("(max-width: 768px)"), [He, k] = A(null);
|
|
233
|
+
O(() => {
|
|
234
|
+
J && k(J);
|
|
235
|
+
}, [J]);
|
|
236
|
+
const Le = () => k(null), ve = c(null);
|
|
237
|
+
O(() => {
|
|
238
|
+
Te?.(y);
|
|
239
|
+
}, [y]);
|
|
240
|
+
const Ue = (e) => {
|
|
241
|
+
e.key === "Enter" && !e.shiftKey && !j && !e.nativeEvent.isComposing && (e.preventDefault(), G());
|
|
242
|
+
}, G = async (e = y) => {
|
|
243
|
+
if (j && (!e || e.trim().length === 0)) return;
|
|
244
|
+
S([]), w(""), v.current = 0, W.current = null, await h({
|
|
226
245
|
eventName: "user_message_submitted",
|
|
227
246
|
properties: {
|
|
228
247
|
conversationId: t
|
|
229
248
|
}
|
|
230
249
|
});
|
|
231
250
|
let s = t;
|
|
232
|
-
s || (s = `conv_${
|
|
251
|
+
s || (s = `conv_${F(16)}`, l(s)), Ie(s), le.current = {
|
|
233
252
|
content: e,
|
|
234
253
|
body: { conversationId: s }
|
|
235
|
-
},
|
|
254
|
+
}, q(
|
|
236
255
|
{ text: e },
|
|
237
256
|
{
|
|
238
257
|
body: { conversationId: s }
|
|
239
258
|
}
|
|
240
259
|
);
|
|
241
|
-
},
|
|
260
|
+
}, We = _(
|
|
242
261
|
(e) => {
|
|
243
|
-
|
|
262
|
+
v.current = 0, W.current = e, z(e);
|
|
244
263
|
},
|
|
245
|
-
[
|
|
246
|
-
),
|
|
247
|
-
|
|
248
|
-
|
|
264
|
+
[z]
|
|
265
|
+
), Q = _(() => {
|
|
266
|
+
E().then(() => {
|
|
267
|
+
I("aborted", { conversationId: t });
|
|
249
268
|
});
|
|
250
|
-
}, [
|
|
251
|
-
|
|
269
|
+
}, [E, t, I]), ye = () => {
|
|
270
|
+
Le(), d([]), l(""), S([]), M(null), u(), h({
|
|
252
271
|
eventName: "chat_clear_button_clicked",
|
|
253
272
|
properties: {
|
|
254
273
|
conversationId: t
|
|
255
274
|
}
|
|
256
275
|
});
|
|
257
|
-
},
|
|
276
|
+
}, N = _(
|
|
258
277
|
(e, s) => {
|
|
259
|
-
|
|
278
|
+
k(null), d(s), l(e), S([]), M(null), u();
|
|
260
279
|
},
|
|
261
|
-
[
|
|
262
|
-
),
|
|
280
|
+
[d, l, u]
|
|
281
|
+
), $e = _(
|
|
263
282
|
async (e, s) => {
|
|
264
|
-
|
|
283
|
+
Q(), N(e, []), ue(!0);
|
|
265
284
|
try {
|
|
266
|
-
const
|
|
267
|
-
id:
|
|
285
|
+
const o = await ce(e, s), n = o?.[o.length - 1], a = o !== null && n?.role === "user" ? [...o, {
|
|
286
|
+
id: F(16),
|
|
268
287
|
role: "assistant",
|
|
269
288
|
parts: [{ type: "text", text: "This session was interrupted. Please check back in a few minutes or start a new conversation." }]
|
|
270
|
-
}] :
|
|
271
|
-
|
|
289
|
+
}] : o;
|
|
290
|
+
a !== null && N(e, a);
|
|
272
291
|
} finally {
|
|
273
|
-
s?.aborted ||
|
|
292
|
+
s?.aborted || ue(!1);
|
|
274
293
|
}
|
|
275
294
|
},
|
|
276
|
-
[
|
|
277
|
-
), { openForm:
|
|
278
|
-
return
|
|
279
|
-
submitMessage:
|
|
295
|
+
[N, ce, Q]
|
|
296
|
+
), { openForm: qe } = nt(), ze = ot();
|
|
297
|
+
return je(f.chatFunctionsRef, () => ({
|
|
298
|
+
submitMessage: G,
|
|
280
299
|
updateInputMessage(e) {
|
|
281
|
-
|
|
300
|
+
w(e);
|
|
282
301
|
},
|
|
283
|
-
clearChat:
|
|
302
|
+
clearChat: ye,
|
|
284
303
|
openForm: (e) => {
|
|
285
|
-
|
|
304
|
+
ze?.setView("chat"), qe(e, void 0);
|
|
286
305
|
},
|
|
287
306
|
focusInput: () => {
|
|
288
|
-
|
|
307
|
+
ve.current?.focus();
|
|
289
308
|
}
|
|
290
309
|
})), {
|
|
291
|
-
messages:
|
|
292
|
-
sendMessage:
|
|
293
|
-
addToolApprovalResponse:
|
|
294
|
-
isLoading:
|
|
295
|
-
isStreaming:
|
|
296
|
-
isBusy:
|
|
297
|
-
error:
|
|
298
|
-
setError:
|
|
299
|
-
isSubmitDisabled:
|
|
300
|
-
input:
|
|
301
|
-
handleInputChange:
|
|
302
|
-
handleInputKeyDown:
|
|
303
|
-
handleSubmit:
|
|
304
|
-
stop:
|
|
305
|
-
clear:
|
|
306
|
-
inputRef:
|
|
307
|
-
isMobile:
|
|
310
|
+
messages: x,
|
|
311
|
+
sendMessage: q,
|
|
312
|
+
addToolApprovalResponse: We,
|
|
313
|
+
isLoading: fe,
|
|
314
|
+
isStreaming: he,
|
|
315
|
+
isBusy: ge,
|
|
316
|
+
error: He,
|
|
317
|
+
setError: k,
|
|
318
|
+
isSubmitDisabled: j,
|
|
319
|
+
input: y,
|
|
320
|
+
handleInputChange: we,
|
|
321
|
+
handleInputKeyDown: Ue,
|
|
322
|
+
handleSubmit: G,
|
|
323
|
+
stop: Q,
|
|
324
|
+
clear: ye,
|
|
325
|
+
inputRef: ve,
|
|
326
|
+
isMobile: Be,
|
|
308
327
|
// Additional state for attachments and workflow
|
|
309
|
-
messageAttachments:
|
|
310
|
-
setMessageAttachments:
|
|
311
|
-
selectedWorkflow:
|
|
312
|
-
setSelectedWorkflow:
|
|
313
|
-
isNewChat:
|
|
328
|
+
messageAttachments: Oe,
|
|
329
|
+
setMessageAttachments: S,
|
|
330
|
+
selectedWorkflow: _e,
|
|
331
|
+
setSelectedWorkflow: M,
|
|
332
|
+
isNewChat: De,
|
|
314
333
|
conversationId: t,
|
|
315
|
-
restoreSession:
|
|
316
|
-
loadAndRestoreSession:
|
|
317
|
-
isSessionLoading:
|
|
318
|
-
sessionToken:
|
|
319
|
-
refreshSession:
|
|
320
|
-
getCaptchaHeader:
|
|
321
|
-
invalidateCaptcha:
|
|
334
|
+
restoreSession: N,
|
|
335
|
+
loadAndRestoreSession: $e,
|
|
336
|
+
isSessionLoading: Ee,
|
|
337
|
+
sessionToken: p ? R : D,
|
|
338
|
+
refreshSession: p ? te : B,
|
|
339
|
+
getCaptchaHeader: C,
|
|
340
|
+
invalidateCaptcha: u
|
|
322
341
|
};
|
|
323
342
|
};
|
|
324
343
|
export {
|
|
325
|
-
|
|
326
|
-
|
|
344
|
+
Z as DEFAULT_ERROR_MESSAGE,
|
|
345
|
+
xt as useInkeepChat
|
|
327
346
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react"),
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react"),j=require("./use-local-storage.cjs"),p=require("./use-inkeep-api-client.cjs"),_=30*1e3,q=2147483647,P=()=>{},B=async()=>({});function x(s){return new Date(s.expiresAt).getTime()-_<=Date.now()}const W=({baseUrl:s,appId:t,getCaptchaHeader:$,invalidateCaptcha:D,optOutAllAnalytics:m,enabled:n=!0})=>{const F=n&&t&&!m?`inkeep_session_${t}`:null,[c,h]=j.useLocalStorage(F),E=e.useRef(n);e.useEffect(()=>{const r=E.current;if(E.current=n,r&&!n&&t&&!m){try{localStorage.removeItem(`inkeep_session_${t}`)}catch{}h(null)}},[n,t,m,h]);const{fetchWithAuth:v}=p.useInkeepApiClient({appId:t,authToken:void 0,getCaptchaHeader:$??B,invalidateCaptcha:D??P}),R=e.useRef(s);R.current=s;const y=e.useRef(t);y.current=t;const f=e.useRef(c);f.current=c;const T=e.useRef(h);T.current=h;const g=e.useRef(v);g.current=v;const a=e.useRef(null),w=e.useRef(n);w.current=n;const o=e.useCallback(async r=>{if(!w.current||!R.current||!y.current)return null;if(!r&&a.current)return a.current;const u=`${R.current}/run/auth/apps/${y.current}/anonymous-session`,l=(async()=>{try{const i={"Content-Type":"application/json"},M=f.current?.token;M&&(i.Authorization=`Bearer ${M}`);const A=await g.current(u,{method:"POST",headers:i,signal:r});if(!A.ok)throw new Error(`Failed to fetch anonymous session: ${A.status}`);const S=await A.json();return T.current({token:S.token,expiresAt:S.expiresAt}),S.token}catch(i){return i instanceof Error&&i.name==="AbortError"||console.error("[anonymous-session] fetch failed",i),null}finally{r||(a.current=null)}})();return r||(a.current=l),l},[]),C=e.useRef(!1);e.useEffect(()=>{if(!n||!s||!t)return;const r=!C.current;if(C.current=!0,!r&&f.current&&!x(f.current)||a.current)return;const u=new AbortController;return o(u.signal),()=>u.abort()},[s,t,n,o]),e.useEffect(()=>{if(!n||!s||!t||!c?.expiresAt)return;const k=new Date(c.expiresAt).getTime()-_-Date.now();if(k<=0)return;const l=setTimeout(()=>o(),Math.min(k,q));return()=>clearTimeout(l)},[s,t,n,c?.expiresAt,o]),e.useEffect(()=>{if(!n||!s||!t)return;const r=()=>{if(document.visibilityState!=="visible")return;const u=f.current;(!u||x(u))&&o()};return document.addEventListener("visibilitychange",r),()=>document.removeEventListener("visibilitychange",r)},[s,t,n,o]);const L=e.useCallback(()=>o(),[o]);return{sessionToken:c?.token??null,refreshSession:L}};exports.useAnonymousSession=W;
|
|
@@ -4,8 +4,9 @@ interface UseAnonymousSessionOptions {
|
|
|
4
4
|
getCaptchaHeader?: () => Promise<Record<string, string>>;
|
|
5
5
|
invalidateCaptcha?: () => void;
|
|
6
6
|
optOutAllAnalytics?: boolean;
|
|
7
|
+
enabled?: boolean;
|
|
7
8
|
}
|
|
8
|
-
export declare const useAnonymousSession: ({ baseUrl, appId, getCaptchaHeader, invalidateCaptcha, optOutAllAnalytics, }: UseAnonymousSessionOptions) => {
|
|
9
|
+
export declare const useAnonymousSession: ({ baseUrl, appId, getCaptchaHeader, invalidateCaptcha, optOutAllAnalytics, enabled, }: UseAnonymousSessionOptions) => {
|
|
9
10
|
sessionToken: string | null;
|
|
10
11
|
refreshSession: () => Promise<string | null>;
|
|
11
12
|
};
|
|
@@ -1,82 +1,96 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useRef as
|
|
3
|
-
import { useLocalStorage as
|
|
4
|
-
import { useInkeepApiClient as
|
|
5
|
-
const
|
|
6
|
-
},
|
|
7
|
-
function
|
|
8
|
-
return new Date(
|
|
2
|
+
import { useRef as o, useEffect as l, useCallback as g } from "react";
|
|
3
|
+
import { useLocalStorage as B } from "./use-local-storage.js";
|
|
4
|
+
import { useInkeepApiClient as P } from "./use-inkeep-api-client.js";
|
|
5
|
+
const p = 30 * 1e3, W = 2147483647, X = () => {
|
|
6
|
+
}, z = async () => ({});
|
|
7
|
+
function $(n) {
|
|
8
|
+
return new Date(n.expiresAt).getTime() - p <= Date.now();
|
|
9
9
|
}
|
|
10
|
-
const
|
|
11
|
-
baseUrl:
|
|
10
|
+
const Y = ({
|
|
11
|
+
baseUrl: n,
|
|
12
12
|
appId: e,
|
|
13
|
-
getCaptchaHeader:
|
|
14
|
-
invalidateCaptcha:
|
|
15
|
-
optOutAllAnalytics:
|
|
13
|
+
getCaptchaHeader: D,
|
|
14
|
+
invalidateCaptcha: F,
|
|
15
|
+
optOutAllAnalytics: k,
|
|
16
|
+
enabled: t = !0
|
|
16
17
|
}) => {
|
|
17
|
-
const
|
|
18
|
+
const L = t && e && !k ? `inkeep_session_${e}` : null, [c, h] = B(L), S = o(t);
|
|
19
|
+
l(() => {
|
|
20
|
+
const r = S.current;
|
|
21
|
+
if (S.current = t, r && !t && e && !k) {
|
|
22
|
+
try {
|
|
23
|
+
localStorage.removeItem(`inkeep_session_${e}`);
|
|
24
|
+
} catch {
|
|
25
|
+
}
|
|
26
|
+
h(null);
|
|
27
|
+
}
|
|
28
|
+
}, [t, e, k, h]);
|
|
29
|
+
const { fetchWithAuth: T } = P({
|
|
18
30
|
appId: e,
|
|
19
31
|
authToken: void 0,
|
|
20
|
-
getCaptchaHeader:
|
|
21
|
-
invalidateCaptcha:
|
|
22
|
-
}),
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
getCaptchaHeader: D ?? z,
|
|
33
|
+
invalidateCaptcha: F ?? X
|
|
34
|
+
}), y = o(n);
|
|
35
|
+
y.current = n;
|
|
36
|
+
const A = o(e);
|
|
37
|
+
A.current = e;
|
|
38
|
+
const f = o(c);
|
|
39
|
+
f.current = c;
|
|
40
|
+
const w = o(h);
|
|
41
|
+
w.current = h;
|
|
42
|
+
const x = o(T);
|
|
43
|
+
x.current = T;
|
|
44
|
+
const a = o(null), M = o(t);
|
|
45
|
+
M.current = t;
|
|
46
|
+
const s = g(async (r) => {
|
|
47
|
+
if (!M.current || !y.current || !A.current) return null;
|
|
48
|
+
if (!r && a.current)
|
|
49
|
+
return a.current;
|
|
50
|
+
const i = `${y.current}/run/auth/apps/${A.current}/anonymous-session`, m = (async () => {
|
|
37
51
|
try {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
const
|
|
52
|
+
const u = { "Content-Type": "application/json" }, _ = f.current?.token;
|
|
53
|
+
_ && (u.Authorization = `Bearer ${_}`);
|
|
54
|
+
const v = await x.current(i, {
|
|
41
55
|
method: "POST",
|
|
42
|
-
headers:
|
|
43
|
-
signal:
|
|
56
|
+
headers: u,
|
|
57
|
+
signal: r
|
|
44
58
|
});
|
|
45
|
-
if (!
|
|
46
|
-
const
|
|
47
|
-
return
|
|
48
|
-
} catch (
|
|
49
|
-
return
|
|
59
|
+
if (!v.ok) throw new Error(`Failed to fetch anonymous session: ${v.status}`);
|
|
60
|
+
const E = await v.json();
|
|
61
|
+
return w.current({ token: E.token, expiresAt: E.expiresAt }), E.token;
|
|
62
|
+
} catch (u) {
|
|
63
|
+
return u instanceof Error && u.name === "AbortError" || console.error("[anonymous-session] fetch failed", u), null;
|
|
50
64
|
} finally {
|
|
51
|
-
|
|
65
|
+
r || (a.current = null);
|
|
52
66
|
}
|
|
53
67
|
})();
|
|
54
|
-
return
|
|
55
|
-
}, []),
|
|
56
|
-
|
|
57
|
-
if (!t || !e) return;
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
60
|
-
const
|
|
61
|
-
return
|
|
62
|
-
}, [
|
|
63
|
-
if (!t || !e || !
|
|
64
|
-
const
|
|
65
|
-
if (
|
|
66
|
-
const
|
|
67
|
-
return () => clearTimeout(
|
|
68
|
-
}, [
|
|
69
|
-
if (!t || !e) return;
|
|
70
|
-
const
|
|
68
|
+
return r || (a.current = m), m;
|
|
69
|
+
}, []), C = o(!1);
|
|
70
|
+
l(() => {
|
|
71
|
+
if (!t || !n || !e) return;
|
|
72
|
+
const r = !C.current;
|
|
73
|
+
if (C.current = !0, !r && f.current && !$(f.current) || a.current) return;
|
|
74
|
+
const i = new AbortController();
|
|
75
|
+
return s(i.signal), () => i.abort();
|
|
76
|
+
}, [n, e, t, s]), l(() => {
|
|
77
|
+
if (!t || !n || !e || !c?.expiresAt) return;
|
|
78
|
+
const R = new Date(c.expiresAt).getTime() - p - Date.now();
|
|
79
|
+
if (R <= 0) return;
|
|
80
|
+
const m = setTimeout(() => s(), Math.min(R, W));
|
|
81
|
+
return () => clearTimeout(m);
|
|
82
|
+
}, [n, e, t, c?.expiresAt, s]), l(() => {
|
|
83
|
+
if (!t || !n || !e) return;
|
|
84
|
+
const r = () => {
|
|
71
85
|
if (document.visibilityState !== "visible") return;
|
|
72
|
-
const
|
|
73
|
-
(!
|
|
86
|
+
const i = f.current;
|
|
87
|
+
(!i || $(i)) && s();
|
|
74
88
|
};
|
|
75
|
-
return document.addEventListener("visibilitychange",
|
|
76
|
-
}, [
|
|
77
|
-
const
|
|
78
|
-
return { sessionToken:
|
|
89
|
+
return document.addEventListener("visibilitychange", r), () => document.removeEventListener("visibilitychange", r);
|
|
90
|
+
}, [n, e, t, s]);
|
|
91
|
+
const j = g(() => s(), [s]);
|
|
92
|
+
return { sessionToken: c?.token ?? null, refreshSession: j };
|
|
79
93
|
};
|
|
80
94
|
export {
|
|
81
|
-
|
|
95
|
+
Y as useAnonymousSession
|
|
82
96
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react"),T=require("../providers/config-provider.cjs"),p=30*1e3,y=2147483647;function d(c){try{const e=c.split(".")[1];if(!e)return null;const n=JSON.parse(atob(e.replace(/-/g,"+").replace(/_/g,"/")));return typeof n.exp=="number"?n.exp*1e3:null}catch{return null}}const A=()=>{const{baseSettings:c}=T.useInkeepConfig(),{getAuthToken:e}=c,[n,l]=t.useState(null),[h,f]=t.useState(!!e),o=t.useRef(null),i=t.useRef(e);i.current=e;const u=t.useCallback(async()=>{const s=i.current;if(!s)return null;if(o.current)return o.current;const a=(async()=>{try{const r=await s();return l(r),r}catch(r){return console.error("[useAuthToken] getAuthToken failed",r),l(null),null}finally{o.current=null,f(!1)}})();return o.current=a,a},[]);t.useEffect(()=>{if(!e){l(null),f(!1);return}u()},[e,u]),t.useEffect(()=>{if(!e||!n)return;const s=d(n);if(!s)return;const r=s-p-Date.now();if(r<=0)return;const k=setTimeout(()=>u(),Math.min(r,y));return()=>clearTimeout(k)},[e,n,u]);const g=t.useCallback(async()=>i.current?u():null,[u]);return{authToken:n,isLoading:h,refreshToken:g}};exports.useAuthToken=A;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState as f, useRef as h, useCallback as p, useEffect as k } from "react";
|
|
3
|
+
import { useInkeepConfig as y } from "../providers/config-provider.js";
|
|
4
|
+
const A = 30 * 1e3, d = 2147483647;
|
|
5
|
+
function M(s) {
|
|
6
|
+
try {
|
|
7
|
+
const e = s.split(".")[1];
|
|
8
|
+
if (!e) return null;
|
|
9
|
+
const t = JSON.parse(atob(e.replace(/-/g, "+").replace(/_/g, "/")));
|
|
10
|
+
return typeof t.exp == "number" ? t.exp * 1e3 : null;
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const E = () => {
|
|
16
|
+
const { baseSettings: s } = y(), { getAuthToken: e } = s, [t, c] = f(null), [T, a] = f(!!e), o = h(null), l = h(e);
|
|
17
|
+
l.current = e;
|
|
18
|
+
const r = p(async () => {
|
|
19
|
+
const u = l.current;
|
|
20
|
+
if (!u) return null;
|
|
21
|
+
if (o.current) return o.current;
|
|
22
|
+
const i = (async () => {
|
|
23
|
+
try {
|
|
24
|
+
const n = await u();
|
|
25
|
+
return c(n), n;
|
|
26
|
+
} catch (n) {
|
|
27
|
+
return console.error("[useAuthToken] getAuthToken failed", n), c(null), null;
|
|
28
|
+
} finally {
|
|
29
|
+
o.current = null, a(!1);
|
|
30
|
+
}
|
|
31
|
+
})();
|
|
32
|
+
return o.current = i, i;
|
|
33
|
+
}, []);
|
|
34
|
+
k(() => {
|
|
35
|
+
if (!e) {
|
|
36
|
+
c(null), a(!1);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
r();
|
|
40
|
+
}, [e, r]), k(() => {
|
|
41
|
+
if (!e || !t) return;
|
|
42
|
+
const u = M(t);
|
|
43
|
+
if (!u) return;
|
|
44
|
+
const n = u - A - Date.now();
|
|
45
|
+
if (n <= 0) return;
|
|
46
|
+
const m = setTimeout(() => r(), Math.min(n, d));
|
|
47
|
+
return () => clearTimeout(m);
|
|
48
|
+
}, [e, t, r]);
|
|
49
|
+
const g = p(async () => l.current ? r() : null, [r]);
|
|
50
|
+
return { authToken: t, isLoading: T, refreshToken: g };
|
|
51
|
+
};
|
|
52
|
+
export {
|
|
53
|
+
E as useAuthToken
|
|
54
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("react/jsx-runtime"),t=require("react"),l=require("./config-provider.cjs"),a=t.createContext(void 0),p=({children:e})=>{const{baseSettings:s,componentType:n}=l.useInkeepConfig(),{tags:o,analyticsProperties:r}=s,i=t.useMemo(()=>({widgetLibraryVersion:"0.15.
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("react/jsx-runtime"),t=require("react"),l=require("./config-provider.cjs"),a=t.createContext(void 0),p=({children:e})=>{const{baseSettings:s,componentType:n}=l.useInkeepConfig(),{tags:o,analyticsProperties:r}=s,i=t.useMemo(()=>({widgetLibraryVersion:"0.15.21",componentType:n,tags:o}),[n,o]),u={logEvent:t.useCallback(async c=>{const v={...i,...c.properties,...r},d={eventName:c.eventName,properties:v};return s.onEvent?.(d)},[s,i,r])};return E.jsx(a.Provider,{value:u,children:e})},g=()=>{const e=t.useContext(a);if(!e)throw new Error("useBaseEvents must be used within a BaseEventsProvider");return e};exports.BaseEventsProvider=p;exports.useBaseEvents=g;
|
|
@@ -5,7 +5,7 @@ import { useInkeepConfig as g } from "./config-provider.js";
|
|
|
5
5
|
const a = d(void 0), P = ({ children: e }) => {
|
|
6
6
|
const { baseSettings: t, componentType: o } = g(), { tags: s, analyticsProperties: n } = t, r = u(
|
|
7
7
|
() => ({
|
|
8
|
-
widgetLibraryVersion: "0.15.
|
|
8
|
+
widgetLibraryVersion: "0.15.21",
|
|
9
9
|
componentType: o,
|
|
10
10
|
tags: s
|
|
11
11
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const te=require("react/jsx-runtime"),e=require("react"),se=require("../components/embedded-chat/chat-provider.cjs"),ne=require("./config-provider.cjs"),re=require("../hooks/use-inkeep-api-client.cjs"),Z=e.createContext(void 0),U=25;function oe(t){const{stop:u,clear:f,conversationId:l,isStreaming:R,loadAndRestoreSession:H,sessionToken:r,refreshSession:_,getCaptchaHeader:z,invalidateCaptcha:B}=se.useChat(),{aiChatSettings:J,baseSettings:Q}=ne.useInkeepConfig(),{baseUrl:S,appId:I,apiKey:V}=J,i=!!Q.getAuthToken,a=!V&&!!I&&(!!r||i),v=r,{fetchWithAuth:P}=re.useInkeepApiClient({appId:I,authToken:v,getCaptchaHeader:z,invalidateCaptcha:B,refreshSession:_}),[b,k]=e.useState(!1),[E,x]=e.useState([]),[w,m]=e.useState(!1),[T,q]=e.useState(0),[A,j]=e.useState(!1),h=e.useRef(!1),M=e.useRef(null),$=e.useRef(i),L=e.useRef(r);e.useEffect(()=>{const n=$.current,s=L.current;$.current=i,L.current=r,(n!==i||s!==null&&r!==null&&s!==r)&&(x([]),q(0),j(!1),h.current=!1)},[i,r]);const O=e.useRef([]);O.current=E;const D=e.useRef(P);D.current=P;const c=e.useCallback(async(n,s=!1)=>{if(!(!S||!v||!a)){s||m(!0);try{const C=`${S}/run/v1/conversations?page=${n+1}&limit=${U}`,g=await D.current(C);if(!g.ok)throw new Error(`Failed to fetch conversations: ${g.status}`);const W=await g.json(),p=(W.data??[]).map(o=>({id:o.id,title:o.title??"",createdAt:new Date(o.createdAt),updatedAt:new Date(o.updatedAt)}));x(o=>{if(n===0&&!s)return p;if(n===0&&s){const d=new Set(p.map(y=>y.id));return[...p,...o.slice(U).filter(y=>!d.has(y.id))]}const ee=new Set(o.map(d=>d.id));return[...o,...p.filter(d=>!ee.has(d.id))]});const{page:G,pages:K}=W.pagination??{};j(G!=null&&K!=null?G<K:!1),s||q(n)}catch(C){console.error("[useChatHistory] Failed to load conversations:",C)}finally{m(!1)}}},[S,v,a]);e.useEffect(()=>{!b||!r&&!i||!a||(t==="stack"?c(0):h.current||(h.current=!0,c(0)))},[b,r,i,a,t,c]);const F=e.useRef("");e.useEffect(()=>{a&&t==="sidepane"&&(!l||!R||h.current&&F.current!==l&&(O.current.some(n=>n.id===l)||(F.current=l,c(0,!0))))},[l,a,t,c,R]);const X=e.useCallback(()=>{!w&&A&&c(T+1)},[w,A,T,c]),Y=e.useCallback(()=>{u(),f(),t!=="sidepane"&&k(!1)},[t,u,f]),N=e.useCallback(async n=>{M.current?.abort();const s=new AbortController;M.current=s,await H(n,s.signal),!s.signal.aborted&&t!=="sidepane"&&k(!1)},[t,H]);return{isEnabled:a,isOpen:b,setIsOpen:k,sessions:E,isLoading:w,hasMore:A,loadMore:X,startNewConversation:Y,loadSession:N}}const ie=({layout:t,children:u})=>{const f=oe(t);return te.jsx(Z.Provider,{value:f,children:typeof u=="function"?u(f):u})},ae=()=>{const t=e.useContext(Z);if(!t)throw new Error("useChatHistory must be used within a ChatHistoryProvider");return t};exports.ChatHistoryProvider=ie;exports.useChatHistory=ae;
|
|
@@ -1,105 +1,110 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as
|
|
3
|
-
import { createContext as
|
|
4
|
-
import { useChat as
|
|
5
|
-
import { useInkeepConfig as
|
|
6
|
-
import { useInkeepApiClient as
|
|
7
|
-
const
|
|
8
|
-
function
|
|
2
|
+
import { jsx as re } from "react/jsx-runtime";
|
|
3
|
+
import { createContext as oe, useContext as ie, useState as h, useRef as c, useEffect as y, useCallback as S } from "react";
|
|
4
|
+
import { useChat as ae } from "../components/embedded-chat/chat-provider.js";
|
|
5
|
+
import { useInkeepConfig as ce } from "./config-provider.js";
|
|
6
|
+
import { useInkeepApiClient as ue } from "../hooks/use-inkeep-api-client.js";
|
|
7
|
+
const B = oe(void 0), z = 25;
|
|
8
|
+
function fe(e) {
|
|
9
9
|
const {
|
|
10
|
-
stop:
|
|
11
|
-
clear:
|
|
12
|
-
conversationId:
|
|
13
|
-
isStreaming:
|
|
14
|
-
loadAndRestoreSession:
|
|
15
|
-
sessionToken:
|
|
16
|
-
refreshSession:
|
|
17
|
-
getCaptchaHeader:
|
|
18
|
-
invalidateCaptcha:
|
|
19
|
-
} =
|
|
20
|
-
appId:
|
|
21
|
-
authToken:
|
|
22
|
-
getCaptchaHeader:
|
|
23
|
-
invalidateCaptcha:
|
|
24
|
-
refreshSession:
|
|
25
|
-
}), [
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
10
|
+
stop: u,
|
|
11
|
+
clear: f,
|
|
12
|
+
conversationId: d,
|
|
13
|
+
isStreaming: P,
|
|
14
|
+
loadAndRestoreSession: x,
|
|
15
|
+
sessionToken: s,
|
|
16
|
+
refreshSession: J,
|
|
17
|
+
getCaptchaHeader: Q,
|
|
18
|
+
invalidateCaptcha: V
|
|
19
|
+
} = ae(), { aiChatSettings: X, baseSettings: Y } = ce(), { baseUrl: w, appId: E, apiKey: N } = X, o = !!Y.getAuthToken, i = !N && !!E && (!!s || o), m = s, { fetchWithAuth: R } = ue({
|
|
20
|
+
appId: E,
|
|
21
|
+
authToken: m,
|
|
22
|
+
getCaptchaHeader: Q,
|
|
23
|
+
invalidateCaptcha: V,
|
|
24
|
+
refreshSession: J
|
|
25
|
+
}), [A, k] = h(!1), [T, $] = h([]), [b, L] = h(!1), [M, j] = h(0), [I, D] = h(!1), p = c(!1), F = c(null), O = c(o), W = c(s);
|
|
26
|
+
y(() => {
|
|
27
|
+
const n = O.current, t = W.current;
|
|
28
|
+
O.current = o, W.current = s, (n !== o || t !== null && s !== null && t !== s) && ($([]), j(0), D(!1), p.current = !1);
|
|
29
|
+
}, [o, s]);
|
|
30
|
+
const G = c([]);
|
|
31
|
+
G.current = T;
|
|
32
|
+
const K = c(R);
|
|
33
|
+
K.current = R;
|
|
34
|
+
const a = S(
|
|
35
|
+
async (n, t = !1) => {
|
|
36
|
+
if (!(!w || !m || !i)) {
|
|
37
|
+
t || L(!0);
|
|
33
38
|
try {
|
|
34
|
-
const
|
|
35
|
-
if (!
|
|
36
|
-
const
|
|
37
|
-
id:
|
|
38
|
-
title:
|
|
39
|
-
createdAt: new Date(
|
|
40
|
-
updatedAt: new Date(
|
|
39
|
+
const C = `${w}/run/v1/conversations?page=${n + 1}&limit=${z}`, g = await K.current(C);
|
|
40
|
+
if (!g.ok) throw new Error(`Failed to fetch conversations: ${g.status}`);
|
|
41
|
+
const Z = await g.json(), v = (Z.data ?? []).map((r) => ({
|
|
42
|
+
id: r.id,
|
|
43
|
+
title: r.title ?? "",
|
|
44
|
+
createdAt: new Date(r.createdAt),
|
|
45
|
+
updatedAt: new Date(r.updatedAt)
|
|
41
46
|
}));
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
if (
|
|
45
|
-
const
|
|
46
|
-
return [...
|
|
47
|
+
$((r) => {
|
|
48
|
+
if (n === 0 && !t) return v;
|
|
49
|
+
if (n === 0 && t) {
|
|
50
|
+
const l = new Set(v.map((H) => H.id));
|
|
51
|
+
return [...v, ...r.slice(z).filter((H) => !l.has(H.id))];
|
|
47
52
|
}
|
|
48
|
-
const
|
|
49
|
-
return [...
|
|
53
|
+
const se = new Set(r.map((l) => l.id));
|
|
54
|
+
return [...r, ...v.filter((l) => !se.has(l.id))];
|
|
50
55
|
});
|
|
51
|
-
const { page:
|
|
52
|
-
|
|
53
|
-
} catch (
|
|
54
|
-
console.error("[useChatHistory] Failed to load conversations:",
|
|
56
|
+
const { page: _, pages: q } = Z.pagination ?? {};
|
|
57
|
+
D(_ != null && q != null ? _ < q : !1), t || j(n);
|
|
58
|
+
} catch (C) {
|
|
59
|
+
console.error("[useChatHistory] Failed to load conversations:", C);
|
|
55
60
|
} finally {
|
|
56
|
-
|
|
61
|
+
L(!1);
|
|
57
62
|
}
|
|
58
63
|
}
|
|
59
64
|
},
|
|
60
|
-
[
|
|
65
|
+
[w, m, i]
|
|
61
66
|
);
|
|
62
|
-
|
|
63
|
-
!
|
|
64
|
-
}, [
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}, [
|
|
69
|
-
const
|
|
70
|
-
!
|
|
71
|
-
}, [
|
|
72
|
-
|
|
73
|
-
}, [
|
|
74
|
-
async (
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
67
|
+
y(() => {
|
|
68
|
+
!A || !s && !o || !i || (e === "stack" ? a(0) : p.current || (p.current = !0, a(0)));
|
|
69
|
+
}, [A, s, o, i, e, a]);
|
|
70
|
+
const U = c("");
|
|
71
|
+
y(() => {
|
|
72
|
+
i && e === "sidepane" && (!d || !P || p.current && U.current !== d && (G.current.some((n) => n.id === d) || (U.current = d, a(0, !0))));
|
|
73
|
+
}, [d, i, e, a, P]);
|
|
74
|
+
const ee = S(() => {
|
|
75
|
+
!b && I && a(M + 1);
|
|
76
|
+
}, [b, I, M, a]), te = S(() => {
|
|
77
|
+
u(), f(), e !== "sidepane" && k(!1);
|
|
78
|
+
}, [e, u, f]), ne = S(
|
|
79
|
+
async (n) => {
|
|
80
|
+
F.current?.abort();
|
|
81
|
+
const t = new AbortController();
|
|
82
|
+
F.current = t, await x(n, t.signal), !t.signal.aborted && e !== "sidepane" && k(!1);
|
|
78
83
|
},
|
|
79
|
-
[
|
|
84
|
+
[e, x]
|
|
80
85
|
);
|
|
81
86
|
return {
|
|
82
|
-
isEnabled:
|
|
83
|
-
isOpen:
|
|
84
|
-
setIsOpen:
|
|
85
|
-
sessions:
|
|
86
|
-
isLoading:
|
|
87
|
-
hasMore:
|
|
88
|
-
loadMore:
|
|
89
|
-
startNewConversation:
|
|
90
|
-
loadSession:
|
|
87
|
+
isEnabled: i,
|
|
88
|
+
isOpen: A,
|
|
89
|
+
setIsOpen: k,
|
|
90
|
+
sessions: T,
|
|
91
|
+
isLoading: b,
|
|
92
|
+
hasMore: I,
|
|
93
|
+
loadMore: ee,
|
|
94
|
+
startNewConversation: te,
|
|
95
|
+
loadSession: ne
|
|
91
96
|
};
|
|
92
97
|
}
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
return /* @__PURE__ */
|
|
96
|
-
},
|
|
97
|
-
const
|
|
98
|
-
if (!
|
|
98
|
+
const ve = ({ layout: e, children: u }) => {
|
|
99
|
+
const f = fe(e);
|
|
100
|
+
return /* @__PURE__ */ re(B.Provider, { value: f, children: typeof u == "function" ? u(f) : u });
|
|
101
|
+
}, Se = () => {
|
|
102
|
+
const e = ie(B);
|
|
103
|
+
if (!e)
|
|
99
104
|
throw new Error("useChatHistory must be used within a ChatHistoryProvider");
|
|
100
|
-
return
|
|
105
|
+
return e;
|
|
101
106
|
};
|
|
102
107
|
export {
|
|
103
|
-
|
|
104
|
-
|
|
108
|
+
ve as ChatHistoryProvider,
|
|
109
|
+
Se as useChatHistory
|
|
105
110
|
};
|
|
@@ -59,8 +59,15 @@ export interface InkeepBaseSettings {
|
|
|
59
59
|
/**
|
|
60
60
|
* Authentication token for the current user.
|
|
61
61
|
* Used for authenticated API requests if required.
|
|
62
|
+
* @deprecated Use getAuthToken instead for automatic token refresh on 401.
|
|
62
63
|
*/
|
|
63
64
|
userAuthToken?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Async callback that returns a JWT for authenticated chat sessions.
|
|
67
|
+
* When provided, the widget uses JWT-based auth instead of anonymous sessions.
|
|
68
|
+
* The callback is re-invoked automatically on 401 responses to refresh the token.
|
|
69
|
+
*/
|
|
70
|
+
getAuthToken?: () => Promise<string>;
|
|
64
71
|
/**
|
|
65
72
|
* Additional properties to be sent with analytics events.
|
|
66
73
|
* These properties will be merged with the event properties.
|