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