@paymanai/payman-ask-sdk 4.0.21 → 4.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +394 -422
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +136 -164
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +24 -147
- package/dist/index.native.js.map +1 -1
- package/dist/styles.css +30 -0
- package/dist/styles.css.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React = require('react');
|
|
4
4
|
var framerMotion = require('framer-motion');
|
|
5
5
|
var clsx = require('clsx');
|
|
6
6
|
var tailwindMerge = require('tailwind-merge');
|
|
@@ -33,6 +33,7 @@ function _interopNamespace(e) {
|
|
|
33
33
|
return Object.freeze(n);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
36
37
|
var Sentry__namespace = /*#__PURE__*/_interopNamespace(Sentry);
|
|
37
38
|
var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
|
|
38
39
|
var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
|
|
@@ -736,8 +737,7 @@ function buildRequestBody(config, userMessage, sessionId, options) {
|
|
|
736
737
|
sessionAttributes,
|
|
737
738
|
analysisMode: options?.analysisMode,
|
|
738
739
|
locale: resolveLocale(config.locale),
|
|
739
|
-
timezone: resolveTimezone(config.timezone)
|
|
740
|
-
...options?.attachments?.length ? { attachments: options.attachments } : {}
|
|
740
|
+
timezone: resolveTimezone(config.timezone)
|
|
741
741
|
};
|
|
742
742
|
}
|
|
743
743
|
function resolveLocale(configured) {
|
|
@@ -782,7 +782,6 @@ function buildResolveImagesUrl(config) {
|
|
|
782
782
|
const basePath = normalizedEndpointPath.endsWith("/stream") ? normalizedEndpointPath.slice(0, -"/stream".length) : normalizedEndpointPath;
|
|
783
783
|
return `${config.api.baseUrl}${basePath}/resolve-image-urls`;
|
|
784
784
|
}
|
|
785
|
-
var NGROK_SKIP_BROWSER_WARNING = "ngrok-skip-browser-warning";
|
|
786
785
|
function buildRequestHeaders(config) {
|
|
787
786
|
const headers = {
|
|
788
787
|
...config.api.headers
|
|
@@ -790,9 +789,6 @@ function buildRequestHeaders(config) {
|
|
|
790
789
|
if (config.api.authToken) {
|
|
791
790
|
headers.Authorization = `Bearer ${config.api.authToken}`;
|
|
792
791
|
}
|
|
793
|
-
if (!headers[NGROK_SKIP_BROWSER_WARNING]) {
|
|
794
|
-
headers[NGROK_SKIP_BROWSER_WARNING] = "true";
|
|
795
|
-
}
|
|
796
792
|
return headers;
|
|
797
793
|
}
|
|
798
794
|
var RAG_IMAGE_REGEX = /\/api\/rag\/chunks\/[^"'\s]+\/image/;
|
|
@@ -845,12 +841,12 @@ async function resolveRagImageUrls(config, content, signal) {
|
|
|
845
841
|
}
|
|
846
842
|
var FRIENDLY_ERROR_MESSAGE = "Oops, something went wrong. Please try again.";
|
|
847
843
|
function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForResponse) {
|
|
848
|
-
const abortControllerRef =
|
|
849
|
-
const configRef =
|
|
844
|
+
const abortControllerRef = React.useRef(null);
|
|
845
|
+
const configRef = React.useRef(config);
|
|
850
846
|
configRef.current = config;
|
|
851
|
-
const callbacksRef =
|
|
847
|
+
const callbacksRef = React.useRef(callbacks);
|
|
852
848
|
callbacksRef.current = callbacks;
|
|
853
|
-
const startStream =
|
|
849
|
+
const startStream = React.useCallback(
|
|
854
850
|
async (userMessage, streamingId, sessionId, externalAbortController, options) => {
|
|
855
851
|
abortControllerRef.current?.abort();
|
|
856
852
|
const abortController = externalAbortController ?? new AbortController();
|
|
@@ -1049,7 +1045,7 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1049
1045
|
},
|
|
1050
1046
|
[setMessages, setIsWaitingForResponse]
|
|
1051
1047
|
);
|
|
1052
|
-
const cancelStream =
|
|
1048
|
+
const cancelStream = React.useCallback(() => {
|
|
1053
1049
|
abortControllerRef.current?.abort();
|
|
1054
1050
|
}, []);
|
|
1055
1051
|
return {
|
|
@@ -1073,81 +1069,6 @@ function createCancelledMessageUpdate(steps, currentMessage) {
|
|
|
1073
1069
|
currentMessage: currentMessage || "Thinking..."
|
|
1074
1070
|
};
|
|
1075
1071
|
}
|
|
1076
|
-
var DEFAULT_SIGNED_URL_ENDPOINT = "/api/files/signed-url";
|
|
1077
|
-
function fileExtension(filename) {
|
|
1078
|
-
const ext = filename.split(".").pop()?.toLowerCase().replace(/^\./, "");
|
|
1079
|
-
return ext && ext.length > 0 ? ext : "bin";
|
|
1080
|
-
}
|
|
1081
|
-
function resolveMimeType(file) {
|
|
1082
|
-
if (file.type && file.type.trim().length > 0) return file.type;
|
|
1083
|
-
const ext = fileExtension(file.name);
|
|
1084
|
-
const byExt = {
|
|
1085
|
-
pdf: "application/pdf",
|
|
1086
|
-
png: "image/png",
|
|
1087
|
-
jpg: "image/jpeg",
|
|
1088
|
-
jpeg: "image/jpeg",
|
|
1089
|
-
gif: "image/gif",
|
|
1090
|
-
webp: "image/webp"
|
|
1091
|
-
};
|
|
1092
|
-
return byExt[ext] ?? "application/octet-stream";
|
|
1093
|
-
}
|
|
1094
|
-
function buildSignedUrlEndpoint(config, ext) {
|
|
1095
|
-
const endpoint = config.api.signedUrlEndpoint || DEFAULT_SIGNED_URL_ENDPOINT;
|
|
1096
|
-
const queryParams = new URLSearchParams({ extn: ext.replace(/^\./, "") });
|
|
1097
|
-
return `${config.api.baseUrl}${endpoint}?${queryParams.toString()}`;
|
|
1098
|
-
}
|
|
1099
|
-
async function requestSignedUrl(config, ext, signal) {
|
|
1100
|
-
const url = buildSignedUrlEndpoint(config, ext);
|
|
1101
|
-
const headers = buildRequestHeaders(config);
|
|
1102
|
-
const response = await fetch(url, {
|
|
1103
|
-
method: "GET",
|
|
1104
|
-
headers,
|
|
1105
|
-
signal
|
|
1106
|
-
});
|
|
1107
|
-
if (!response.ok) {
|
|
1108
|
-
const errorText = await response.text().catch(() => "");
|
|
1109
|
-
throw new Error(
|
|
1110
|
-
errorText ? `Failed to get upload URL (${response.status}): ${errorText}` : `Failed to get upload URL (${response.status})`
|
|
1111
|
-
);
|
|
1112
|
-
}
|
|
1113
|
-
const data = await response.json();
|
|
1114
|
-
if (!data.key || !data.url) {
|
|
1115
|
-
throw new Error("Signed URL response missing key or url");
|
|
1116
|
-
}
|
|
1117
|
-
return { key: data.key, url: data.url };
|
|
1118
|
-
}
|
|
1119
|
-
async function uploadToSignedUrl(signedUrl, file, mimeType, signal) {
|
|
1120
|
-
const response = await fetch(signedUrl, {
|
|
1121
|
-
method: "PUT",
|
|
1122
|
-
headers: {
|
|
1123
|
-
"Content-Type": mimeType,
|
|
1124
|
-
"x-ms-blob-type": "BlockBlob"
|
|
1125
|
-
},
|
|
1126
|
-
body: file,
|
|
1127
|
-
signal
|
|
1128
|
-
});
|
|
1129
|
-
if (!response.ok) {
|
|
1130
|
-
const errorText = await response.text().catch(() => "");
|
|
1131
|
-
throw new Error(
|
|
1132
|
-
errorText ? `Failed to upload file (${response.status}): ${errorText}` : `Failed to upload file (${response.status})`
|
|
1133
|
-
);
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
async function uploadAttachment(config, file, signal) {
|
|
1137
|
-
const ext = fileExtension(file.name);
|
|
1138
|
-
const mimeType = resolveMimeType(file);
|
|
1139
|
-
const { key, url } = await requestSignedUrl(config, ext, signal);
|
|
1140
|
-
await uploadToSignedUrl(url, file, mimeType, signal);
|
|
1141
|
-
return {
|
|
1142
|
-
tempKey: key,
|
|
1143
|
-
filename: file.name,
|
|
1144
|
-
mimeType
|
|
1145
|
-
};
|
|
1146
|
-
}
|
|
1147
|
-
async function uploadAttachments(config, files, signal) {
|
|
1148
|
-
const uploads = files.map((file) => uploadAttachment(config, file, signal));
|
|
1149
|
-
return Promise.all(uploads);
|
|
1150
|
-
}
|
|
1151
1072
|
var UserActionStaleError = class extends Error {
|
|
1152
1073
|
constructor(userActionId, message = "User action is no longer actionable") {
|
|
1153
1074
|
super(message);
|
|
@@ -1184,6 +1105,9 @@ async function cancelUserAction(config, userActionId) {
|
|
|
1184
1105
|
async function resendUserAction(config, userActionId) {
|
|
1185
1106
|
return sendUserActionRequest(config, userActionId, "resend");
|
|
1186
1107
|
}
|
|
1108
|
+
async function expireUserAction(config, userActionId) {
|
|
1109
|
+
return sendUserActionRequest(config, userActionId, "expired");
|
|
1110
|
+
}
|
|
1187
1111
|
var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
|
|
1188
1112
|
function upsertPrompt(prompts, req) {
|
|
1189
1113
|
const active = { ...req, status: "pending" };
|
|
@@ -1212,45 +1136,25 @@ function getStoredOrInitialMessages(config) {
|
|
|
1212
1136
|
function getSessionIdFromMessages(messages) {
|
|
1213
1137
|
return messages.find((message) => message.sessionId)?.sessionId;
|
|
1214
1138
|
}
|
|
1215
|
-
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "gif", "webp", "avif"]);
|
|
1216
|
-
function attachmentKindFromFile(file) {
|
|
1217
|
-
const ext = file.name.split(".").pop()?.toLowerCase() ?? "";
|
|
1218
|
-
if (IMAGE_EXTENSIONS.has(ext) || file.type.startsWith("image/")) return "image";
|
|
1219
|
-
return "file";
|
|
1220
|
-
}
|
|
1221
|
-
function buildMessageAttachments(files) {
|
|
1222
|
-
return files.map((file, index) => {
|
|
1223
|
-
const kind = attachmentKindFromFile(file);
|
|
1224
|
-
return {
|
|
1225
|
-
id: `att-${Date.now()}-${index}`,
|
|
1226
|
-
filename: file.name,
|
|
1227
|
-
mimeType: file.type || "application/octet-stream",
|
|
1228
|
-
// Blob URL for all local files so PDFs/docs stay previewable after send.
|
|
1229
|
-
previewUrl: URL.createObjectURL(file),
|
|
1230
|
-
kind
|
|
1231
|
-
};
|
|
1232
|
-
});
|
|
1233
|
-
}
|
|
1234
1139
|
function useChatV2(config, callbacks = {}) {
|
|
1235
|
-
const [messages, setMessages] =
|
|
1236
|
-
const [isWaitingForResponse, setIsWaitingForResponse] =
|
|
1140
|
+
const [messages, setMessages] = React.useState(() => getStoredOrInitialMessages(config));
|
|
1141
|
+
const [isWaitingForResponse, setIsWaitingForResponse] = React.useState(() => {
|
|
1237
1142
|
if (!config.userId) return false;
|
|
1238
1143
|
return activeStreamStore.get(config.userId)?.isWaiting ?? false;
|
|
1239
1144
|
});
|
|
1240
|
-
const
|
|
1241
|
-
const sessionIdRef = react.useRef(
|
|
1145
|
+
const sessionIdRef = React.useRef(
|
|
1242
1146
|
getSessionIdFromMessages(getStoredOrInitialMessages(config)) ?? config.initialSessionId ?? void 0
|
|
1243
1147
|
);
|
|
1244
|
-
const prevUserIdRef =
|
|
1245
|
-
const streamUserIdRef =
|
|
1246
|
-
const subscriptionPrevUserIdRef =
|
|
1247
|
-
const callbacksRef =
|
|
1148
|
+
const prevUserIdRef = React.useRef(config.userId);
|
|
1149
|
+
const streamUserIdRef = React.useRef(void 0);
|
|
1150
|
+
const subscriptionPrevUserIdRef = React.useRef(config.userId);
|
|
1151
|
+
const callbacksRef = React.useRef(callbacks);
|
|
1248
1152
|
callbacksRef.current = callbacks;
|
|
1249
|
-
const configRef =
|
|
1153
|
+
const configRef = React.useRef(config);
|
|
1250
1154
|
configRef.current = config;
|
|
1251
|
-
const messagesRef =
|
|
1155
|
+
const messagesRef = React.useRef(messages);
|
|
1252
1156
|
messagesRef.current = messages;
|
|
1253
|
-
const storeAwareSetMessages =
|
|
1157
|
+
const storeAwareSetMessages = React.useCallback(
|
|
1254
1158
|
(updater) => {
|
|
1255
1159
|
const streamUserId = streamUserIdRef.current;
|
|
1256
1160
|
const currentUserId = configRef.current.userId;
|
|
@@ -1265,7 +1169,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1265
1169
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1266
1170
|
[]
|
|
1267
1171
|
);
|
|
1268
|
-
const storeAwareSetIsWaiting =
|
|
1172
|
+
const storeAwareSetIsWaiting = React.useCallback(
|
|
1269
1173
|
(waiting) => {
|
|
1270
1174
|
const streamUserId = streamUserIdRef.current;
|
|
1271
1175
|
const currentUserId = configRef.current.userId;
|
|
@@ -1280,8 +1184,8 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1280
1184
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1281
1185
|
[]
|
|
1282
1186
|
);
|
|
1283
|
-
const [userActionState, setUserActionState] =
|
|
1284
|
-
const wrappedCallbacks =
|
|
1187
|
+
const [userActionState, setUserActionState] = React.useState(EMPTY_USER_ACTION_STATE);
|
|
1188
|
+
const wrappedCallbacks = React.useMemo(() => ({
|
|
1285
1189
|
...callbacksRef.current,
|
|
1286
1190
|
onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
|
|
1287
1191
|
onStreamStart: () => callbacksRef.current.onStreamStart?.(),
|
|
@@ -1310,47 +1214,23 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1310
1214
|
storeAwareSetMessages,
|
|
1311
1215
|
storeAwareSetIsWaiting
|
|
1312
1216
|
);
|
|
1313
|
-
const sendMessage =
|
|
1217
|
+
const sendMessage = React.useCallback(
|
|
1314
1218
|
async (userMessage, options) => {
|
|
1315
|
-
|
|
1316
|
-
const files = options?.files ?? [];
|
|
1317
|
-
const hasPreuploadedAttachments = (options?.attachments?.length ?? 0) > 0;
|
|
1318
|
-
if (!trimmedMessage && files.length === 0 && !hasPreuploadedAttachments) return;
|
|
1319
|
-
let streamAttachments = options?.attachments;
|
|
1320
|
-
if (!streamAttachments && files.length > 0) {
|
|
1321
|
-
setIsUploadingAttachments(true);
|
|
1322
|
-
try {
|
|
1323
|
-
streamAttachments = await uploadAttachments(configRef.current, files);
|
|
1324
|
-
} catch (error) {
|
|
1325
|
-
if (error.name !== "AbortError") {
|
|
1326
|
-
callbacksRef.current.onError?.(error);
|
|
1327
|
-
}
|
|
1328
|
-
throw error;
|
|
1329
|
-
} finally {
|
|
1330
|
-
setIsUploadingAttachments(false);
|
|
1331
|
-
}
|
|
1332
|
-
}
|
|
1219
|
+
if (!userMessage.trim()) return;
|
|
1333
1220
|
if (!sessionIdRef.current && configRef.current.autoGenerateSessionId !== false) {
|
|
1334
1221
|
sessionIdRef.current = generateId();
|
|
1335
1222
|
callbacksRef.current.onSessionIdChange?.(sessionIdRef.current);
|
|
1336
1223
|
}
|
|
1337
|
-
const messageAttachments = files.length > 0 ? buildMessageAttachments(files) : streamAttachments?.length ? streamAttachments.map((attachment, index) => ({
|
|
1338
|
-
id: `att-${Date.now()}-${index}`,
|
|
1339
|
-
filename: attachment.filename,
|
|
1340
|
-
mimeType: attachment.mimeType,
|
|
1341
|
-
kind: attachment.mimeType.startsWith("image/") ? "image" : "file"
|
|
1342
|
-
})) : void 0;
|
|
1343
1224
|
const userMessageId = `user-${Date.now()}`;
|
|
1344
1225
|
const userMsg = {
|
|
1345
1226
|
id: userMessageId,
|
|
1346
1227
|
sessionId: sessionIdRef.current,
|
|
1347
1228
|
role: "user",
|
|
1348
|
-
content:
|
|
1349
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1350
|
-
attachments: messageAttachments
|
|
1229
|
+
content: userMessage,
|
|
1230
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1351
1231
|
};
|
|
1352
1232
|
setMessages((prev) => [...prev, userMsg]);
|
|
1353
|
-
callbacksRef.current.onMessageSent?.(
|
|
1233
|
+
callbacksRef.current.onMessageSent?.(userMessage);
|
|
1354
1234
|
setIsWaitingForResponse(true);
|
|
1355
1235
|
callbacksRef.current.onStreamStart?.();
|
|
1356
1236
|
const streamingId = `assistant-${Date.now()}`;
|
|
@@ -1377,14 +1257,11 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1377
1257
|
activeStreamStore.start(userId, abortController, initialMessages);
|
|
1378
1258
|
}
|
|
1379
1259
|
const newSessionId = await startStream(
|
|
1380
|
-
|
|
1260
|
+
userMessage,
|
|
1381
1261
|
streamingId,
|
|
1382
1262
|
sessionIdRef.current,
|
|
1383
1263
|
abortController,
|
|
1384
|
-
|
|
1385
|
-
analysisMode: options?.analysisMode,
|
|
1386
|
-
attachments: streamAttachments
|
|
1387
|
-
}
|
|
1264
|
+
options
|
|
1388
1265
|
);
|
|
1389
1266
|
const finalStreamUserId = streamUserIdRef.current ?? userId;
|
|
1390
1267
|
if (finalStreamUserId) {
|
|
@@ -1397,16 +1274,16 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1397
1274
|
},
|
|
1398
1275
|
[startStream]
|
|
1399
1276
|
);
|
|
1400
|
-
const clearMessages =
|
|
1277
|
+
const clearMessages = React.useCallback(() => {
|
|
1401
1278
|
if (configRef.current.userId) {
|
|
1402
1279
|
chatStore.delete(configRef.current.userId);
|
|
1403
1280
|
}
|
|
1404
1281
|
setMessages([]);
|
|
1405
1282
|
}, []);
|
|
1406
|
-
const prependMessages =
|
|
1283
|
+
const prependMessages = React.useCallback((msgs) => {
|
|
1407
1284
|
setMessages((prev) => [...msgs, ...prev]);
|
|
1408
1285
|
}, []);
|
|
1409
|
-
const cancelStream =
|
|
1286
|
+
const cancelStream = React.useCallback(() => {
|
|
1410
1287
|
const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
|
|
1411
1288
|
if (streamUserId) {
|
|
1412
1289
|
activeStreamStore.abort(streamUserId);
|
|
@@ -1430,7 +1307,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1430
1307
|
})
|
|
1431
1308
|
);
|
|
1432
1309
|
}, [cancelStreamManager]);
|
|
1433
|
-
const resetSession =
|
|
1310
|
+
const resetSession = React.useCallback(() => {
|
|
1434
1311
|
const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
|
|
1435
1312
|
if (streamUserId) {
|
|
1436
1313
|
activeStreamStore.abort(streamUserId);
|
|
@@ -1445,13 +1322,13 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1445
1322
|
setIsWaitingForResponse(false);
|
|
1446
1323
|
setUserActionState(EMPTY_USER_ACTION_STATE);
|
|
1447
1324
|
}, []);
|
|
1448
|
-
const getSessionId =
|
|
1325
|
+
const getSessionId = React.useCallback(() => {
|
|
1449
1326
|
return sessionIdRef.current;
|
|
1450
1327
|
}, []);
|
|
1451
|
-
const getMessages =
|
|
1328
|
+
const getMessages = React.useCallback(() => {
|
|
1452
1329
|
return messages;
|
|
1453
1330
|
}, [messages]);
|
|
1454
|
-
const setPromptStatus =
|
|
1331
|
+
const setPromptStatus = React.useCallback(
|
|
1455
1332
|
(userActionId, status) => {
|
|
1456
1333
|
setUserActionState((prev) => ({
|
|
1457
1334
|
...prev,
|
|
@@ -1462,13 +1339,13 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1462
1339
|
},
|
|
1463
1340
|
[]
|
|
1464
1341
|
);
|
|
1465
|
-
const removePrompt =
|
|
1342
|
+
const removePrompt = React.useCallback((userActionId) => {
|
|
1466
1343
|
setUserActionState((prev) => ({
|
|
1467
1344
|
...prev,
|
|
1468
1345
|
prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
|
|
1469
1346
|
}));
|
|
1470
1347
|
}, []);
|
|
1471
|
-
const submitUserAction2 =
|
|
1348
|
+
const submitUserAction2 = React.useCallback(
|
|
1472
1349
|
async (userActionId, content) => {
|
|
1473
1350
|
setPromptStatus(userActionId, "submitting");
|
|
1474
1351
|
try {
|
|
@@ -1486,7 +1363,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1486
1363
|
},
|
|
1487
1364
|
[removePrompt, setPromptStatus]
|
|
1488
1365
|
);
|
|
1489
|
-
const cancelUserAction2 =
|
|
1366
|
+
const cancelUserAction2 = React.useCallback(
|
|
1490
1367
|
async (userActionId) => {
|
|
1491
1368
|
setPromptStatus(userActionId, "submitting");
|
|
1492
1369
|
try {
|
|
@@ -1504,7 +1381,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1504
1381
|
},
|
|
1505
1382
|
[removePrompt, setPromptStatus]
|
|
1506
1383
|
);
|
|
1507
|
-
const resendUserAction2 =
|
|
1384
|
+
const resendUserAction2 = React.useCallback(
|
|
1508
1385
|
async (userActionId) => {
|
|
1509
1386
|
setPromptStatus(userActionId, "submitting");
|
|
1510
1387
|
try {
|
|
@@ -1522,13 +1399,26 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1522
1399
|
},
|
|
1523
1400
|
[setPromptStatus]
|
|
1524
1401
|
);
|
|
1525
|
-
const
|
|
1402
|
+
const expireUserAction2 = React.useCallback(
|
|
1403
|
+
async (userActionId) => {
|
|
1404
|
+
setPromptStatus(userActionId, "expired");
|
|
1405
|
+
try {
|
|
1406
|
+
await expireUserAction(configRef.current, userActionId);
|
|
1407
|
+
} catch (error) {
|
|
1408
|
+
if (error instanceof UserActionStaleError) return;
|
|
1409
|
+
callbacksRef.current.onError?.(error);
|
|
1410
|
+
throw error;
|
|
1411
|
+
}
|
|
1412
|
+
},
|
|
1413
|
+
[setPromptStatus]
|
|
1414
|
+
);
|
|
1415
|
+
const dismissNotification = React.useCallback((id) => {
|
|
1526
1416
|
setUserActionState((prev) => ({
|
|
1527
1417
|
...prev,
|
|
1528
1418
|
notifications: prev.notifications.filter((n) => n.id !== id)
|
|
1529
1419
|
}));
|
|
1530
1420
|
}, []);
|
|
1531
|
-
|
|
1421
|
+
React.useEffect(() => {
|
|
1532
1422
|
const prevSubscriptionUserId = subscriptionPrevUserIdRef.current;
|
|
1533
1423
|
subscriptionPrevUserIdRef.current = config.userId;
|
|
1534
1424
|
const { userId } = config;
|
|
@@ -1547,7 +1437,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1547
1437
|
}
|
|
1548
1438
|
return unsubscribe;
|
|
1549
1439
|
}, [config.userId]);
|
|
1550
|
-
|
|
1440
|
+
React.useEffect(() => {
|
|
1551
1441
|
if (!config.userId) return;
|
|
1552
1442
|
if (prevUserIdRef.current !== config.userId) return;
|
|
1553
1443
|
const toSave = messages.filter((m) => !m.isStreaming);
|
|
@@ -1555,26 +1445,14 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1555
1445
|
chatStore.set(config.userId, toSave);
|
|
1556
1446
|
}
|
|
1557
1447
|
}, [messages, config.userId]);
|
|
1558
|
-
|
|
1448
|
+
React.useEffect(() => {
|
|
1559
1449
|
if (!config.userId || activeStreamStore.has(config.userId)) return;
|
|
1560
1450
|
if (!config.initialMessages?.length || messagesRef.current.length > 0) return;
|
|
1561
1451
|
chatStore.set(config.userId, config.initialMessages);
|
|
1562
1452
|
setMessages(config.initialMessages);
|
|
1563
1453
|
sessionIdRef.current = getSessionIdFromMessages(config.initialMessages) ?? config.initialSessionId;
|
|
1564
1454
|
}, [config.initialMessages, config.initialSessionId, config.userId]);
|
|
1565
|
-
|
|
1566
|
-
react.useEffect(() => {
|
|
1567
|
-
if (config.userId) return;
|
|
1568
|
-
if (!config.initialMessages?.length) return;
|
|
1569
|
-
const sessionId = config.initialSessionId;
|
|
1570
|
-
if (hydratedSessionIdRef.current === sessionId && messagesRef.current.length > 0) {
|
|
1571
|
-
return;
|
|
1572
|
-
}
|
|
1573
|
-
hydratedSessionIdRef.current = sessionId;
|
|
1574
|
-
setMessages(config.initialMessages);
|
|
1575
|
-
sessionIdRef.current = getSessionIdFromMessages(config.initialMessages) ?? sessionId;
|
|
1576
|
-
}, [config.initialMessages, config.initialSessionId, config.userId]);
|
|
1577
|
-
react.useEffect(() => {
|
|
1455
|
+
React.useEffect(() => {
|
|
1578
1456
|
const prevUserId = prevUserIdRef.current;
|
|
1579
1457
|
prevUserIdRef.current = config.userId;
|
|
1580
1458
|
if (prevUserId === config.userId) return;
|
|
@@ -1608,12 +1486,12 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1608
1486
|
getSessionId,
|
|
1609
1487
|
getMessages,
|
|
1610
1488
|
isWaitingForResponse,
|
|
1611
|
-
isUploadingAttachments,
|
|
1612
1489
|
sessionId: sessionIdRef.current,
|
|
1613
1490
|
userActionState,
|
|
1614
1491
|
submitUserAction: submitUserAction2,
|
|
1615
1492
|
cancelUserAction: cancelUserAction2,
|
|
1616
1493
|
resendUserAction: resendUserAction2,
|
|
1494
|
+
expireUserAction: expireUserAction2,
|
|
1617
1495
|
dismissNotification
|
|
1618
1496
|
};
|
|
1619
1497
|
}
|
|
@@ -1622,12 +1500,12 @@ function getSpeechRecognition() {
|
|
|
1622
1500
|
return window.SpeechRecognition || window.webkitSpeechRecognition || null;
|
|
1623
1501
|
}
|
|
1624
1502
|
function useVoice(config = {}, callbacks = {}) {
|
|
1625
|
-
const [voiceState, setVoiceState] =
|
|
1626
|
-
const [transcribedText, setTranscribedText] =
|
|
1627
|
-
const [isAvailable, setIsAvailable] =
|
|
1628
|
-
const [isRecording, setIsRecording] =
|
|
1629
|
-
const recognitionRef =
|
|
1630
|
-
const autoStopTimerRef =
|
|
1503
|
+
const [voiceState, setVoiceState] = React.useState("idle");
|
|
1504
|
+
const [transcribedText, setTranscribedText] = React.useState("");
|
|
1505
|
+
const [isAvailable, setIsAvailable] = React.useState(false);
|
|
1506
|
+
const [isRecording, setIsRecording] = React.useState(false);
|
|
1507
|
+
const recognitionRef = React.useRef(null);
|
|
1508
|
+
const autoStopTimerRef = React.useRef(null);
|
|
1631
1509
|
const {
|
|
1632
1510
|
lang = "en-US",
|
|
1633
1511
|
interimResults = true,
|
|
@@ -1636,14 +1514,14 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1636
1514
|
autoStopAfterSilence
|
|
1637
1515
|
} = config;
|
|
1638
1516
|
const { onStart, onEnd, onResult, onError, onStateChange } = callbacks;
|
|
1639
|
-
|
|
1517
|
+
React.useEffect(() => {
|
|
1640
1518
|
const SpeechRecognitionAPI = getSpeechRecognition();
|
|
1641
1519
|
setIsAvailable(SpeechRecognitionAPI !== null);
|
|
1642
1520
|
}, []);
|
|
1643
|
-
|
|
1521
|
+
React.useEffect(() => {
|
|
1644
1522
|
onStateChange?.(voiceState);
|
|
1645
1523
|
}, [voiceState, onStateChange]);
|
|
1646
|
-
const requestPermissions =
|
|
1524
|
+
const requestPermissions = React.useCallback(async () => {
|
|
1647
1525
|
try {
|
|
1648
1526
|
const result = await navigator.mediaDevices.getUserMedia({
|
|
1649
1527
|
audio: true
|
|
@@ -1660,7 +1538,7 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1660
1538
|
};
|
|
1661
1539
|
}
|
|
1662
1540
|
}, []);
|
|
1663
|
-
const getPermissions =
|
|
1541
|
+
const getPermissions = React.useCallback(async () => {
|
|
1664
1542
|
if (typeof navigator === "undefined" || !navigator.permissions) {
|
|
1665
1543
|
return {
|
|
1666
1544
|
granted: false,
|
|
@@ -1682,13 +1560,13 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1682
1560
|
};
|
|
1683
1561
|
}
|
|
1684
1562
|
}, []);
|
|
1685
|
-
const clearAutoStopTimer =
|
|
1563
|
+
const clearAutoStopTimer = React.useCallback(() => {
|
|
1686
1564
|
if (autoStopTimerRef.current) {
|
|
1687
1565
|
clearTimeout(autoStopTimerRef.current);
|
|
1688
1566
|
autoStopTimerRef.current = null;
|
|
1689
1567
|
}
|
|
1690
1568
|
}, []);
|
|
1691
|
-
const resetAutoStopTimer =
|
|
1569
|
+
const resetAutoStopTimer = React.useCallback(() => {
|
|
1692
1570
|
clearAutoStopTimer();
|
|
1693
1571
|
if (autoStopAfterSilence && autoStopAfterSilence > 0) {
|
|
1694
1572
|
autoStopTimerRef.current = setTimeout(() => {
|
|
@@ -1698,7 +1576,7 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1698
1576
|
}, autoStopAfterSilence);
|
|
1699
1577
|
}
|
|
1700
1578
|
}, [autoStopAfterSilence, clearAutoStopTimer, isRecording]);
|
|
1701
|
-
const stopRecording =
|
|
1579
|
+
const stopRecording = React.useCallback(() => {
|
|
1702
1580
|
if (recognitionRef.current) {
|
|
1703
1581
|
try {
|
|
1704
1582
|
recognitionRef.current.stop();
|
|
@@ -1710,7 +1588,7 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1710
1588
|
setIsRecording(false);
|
|
1711
1589
|
setVoiceState("idle");
|
|
1712
1590
|
}, [clearAutoStopTimer]);
|
|
1713
|
-
const startRecording =
|
|
1591
|
+
const startRecording = React.useCallback(async () => {
|
|
1714
1592
|
const SpeechRecognitionAPI = getSpeechRecognition();
|
|
1715
1593
|
if (!SpeechRecognitionAPI) {
|
|
1716
1594
|
onError?.("Speech recognition not supported in this browser");
|
|
@@ -1800,15 +1678,15 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1800
1678
|
resetAutoStopTimer,
|
|
1801
1679
|
clearAutoStopTimer
|
|
1802
1680
|
]);
|
|
1803
|
-
const clearTranscript =
|
|
1681
|
+
const clearTranscript = React.useCallback(() => {
|
|
1804
1682
|
setTranscribedText("");
|
|
1805
1683
|
}, []);
|
|
1806
|
-
const reset =
|
|
1684
|
+
const reset = React.useCallback(() => {
|
|
1807
1685
|
stopRecording();
|
|
1808
1686
|
setTranscribedText("");
|
|
1809
1687
|
setVoiceState("idle");
|
|
1810
1688
|
}, [stopRecording]);
|
|
1811
|
-
|
|
1689
|
+
React.useEffect(() => {
|
|
1812
1690
|
return () => {
|
|
1813
1691
|
if (recognitionRef.current) {
|
|
1814
1692
|
try {
|
|
@@ -1948,9 +1826,9 @@ function buildContent(schema, values) {
|
|
|
1948
1826
|
}
|
|
1949
1827
|
return content;
|
|
1950
1828
|
}
|
|
1951
|
-
var PaymanChatContext =
|
|
1829
|
+
var PaymanChatContext = React.createContext(void 0);
|
|
1952
1830
|
function usePaymanChat() {
|
|
1953
|
-
const context =
|
|
1831
|
+
const context = React.useContext(PaymanChatContext);
|
|
1954
1832
|
if (!context) {
|
|
1955
1833
|
throw new Error("usePaymanChat must be used within a PaymanChat component");
|
|
1956
1834
|
}
|
|
@@ -2208,8 +2086,8 @@ function ImageLightbox({
|
|
|
2208
2086
|
alt = "",
|
|
2209
2087
|
onClose
|
|
2210
2088
|
}) {
|
|
2211
|
-
const [isMounted, setIsMounted] =
|
|
2212
|
-
const [isImageLoaded, setIsImageLoaded] =
|
|
2089
|
+
const [isMounted, setIsMounted] = React.useState(false);
|
|
2090
|
+
const [isImageLoaded, setIsImageLoaded] = React.useState(false);
|
|
2213
2091
|
const overlayStyle = {
|
|
2214
2092
|
position: "fixed",
|
|
2215
2093
|
inset: 0,
|
|
@@ -2230,14 +2108,14 @@ function ImageLightbox({
|
|
|
2230
2108
|
justifyContent: "center",
|
|
2231
2109
|
overflow: "hidden"
|
|
2232
2110
|
};
|
|
2233
|
-
|
|
2111
|
+
React.useEffect(() => {
|
|
2234
2112
|
setIsMounted(true);
|
|
2235
2113
|
return () => setIsMounted(false);
|
|
2236
2114
|
}, []);
|
|
2237
|
-
|
|
2115
|
+
React.useEffect(() => {
|
|
2238
2116
|
setIsImageLoaded(false);
|
|
2239
2117
|
}, [src]);
|
|
2240
|
-
|
|
2118
|
+
React.useEffect(() => {
|
|
2241
2119
|
if (typeof document === "undefined") return;
|
|
2242
2120
|
const previousOverflow = document.body.style.overflow;
|
|
2243
2121
|
document.body.style.overflow = "hidden";
|
|
@@ -2245,7 +2123,7 @@ function ImageLightbox({
|
|
|
2245
2123
|
document.body.style.overflow = previousOverflow;
|
|
2246
2124
|
};
|
|
2247
2125
|
}, []);
|
|
2248
|
-
|
|
2126
|
+
React.useEffect(() => {
|
|
2249
2127
|
if (typeof document === "undefined") return;
|
|
2250
2128
|
const handleKeyDown = (event) => {
|
|
2251
2129
|
if (event.key === "Escape") {
|
|
@@ -2341,15 +2219,15 @@ function MarkdownImage({
|
|
|
2341
2219
|
maxHeight: "18rem",
|
|
2342
2220
|
objectFit: "contain"
|
|
2343
2221
|
};
|
|
2344
|
-
const [isLoaded, setIsLoaded] =
|
|
2345
|
-
const [hasError, setHasError] =
|
|
2346
|
-
const [isLightboxOpen, setIsLightboxOpen] =
|
|
2347
|
-
const isUnresolvedRagImage =
|
|
2222
|
+
const [isLoaded, setIsLoaded] = React.useState(false);
|
|
2223
|
+
const [hasError, setHasError] = React.useState(false);
|
|
2224
|
+
const [isLightboxOpen, setIsLightboxOpen] = React.useState(false);
|
|
2225
|
+
const isUnresolvedRagImage = React.useMemo(
|
|
2348
2226
|
() => src ? isUnresolvedRagImageSource(src) : false,
|
|
2349
2227
|
[src]
|
|
2350
2228
|
);
|
|
2351
2229
|
const isResolvingRagImage = isResolving && isUnresolvedRagImage;
|
|
2352
|
-
|
|
2230
|
+
React.useEffect(() => {
|
|
2353
2231
|
setIsLoaded(false);
|
|
2354
2232
|
setHasError(false);
|
|
2355
2233
|
setIsLightboxOpen(false);
|
|
@@ -2476,9 +2354,9 @@ function AgentMessage({
|
|
|
2476
2354
|
const hasTraceData = !!(message.tracingData || message.executionId) && !isStreaming;
|
|
2477
2355
|
const isCancelled = message.isCancelled ?? false;
|
|
2478
2356
|
const currentExecutingStepId = message.currentExecutingStepId;
|
|
2479
|
-
const [isStepsExpanded, setIsStepsExpanded] =
|
|
2480
|
-
const wasStreamingRef =
|
|
2481
|
-
|
|
2357
|
+
const [isStepsExpanded, setIsStepsExpanded] = React.useState(false);
|
|
2358
|
+
const wasStreamingRef = React.useRef(isStreaming);
|
|
2359
|
+
React.useEffect(() => {
|
|
2482
2360
|
if (isStreaming && hasSteps) {
|
|
2483
2361
|
setIsStepsExpanded(true);
|
|
2484
2362
|
}
|
|
@@ -2495,13 +2373,13 @@ function AgentMessage({
|
|
|
2495
2373
|
const completedWithNoContent = !isStreaming && !isCancelled && content.length === 0 && (message.streamProgress === "completed" || message.streamProgress === "error");
|
|
2496
2374
|
const conflictErrorMessage = getConflictErrorMessage(message.errorDetails);
|
|
2497
2375
|
const isError = !!conflictErrorMessage || (isFriendlyWorkflowError(message.errorDetails) || looksLikeRawError(content)) && !hasMeaningfulContent || completedWithNoContent;
|
|
2498
|
-
const currentStep =
|
|
2376
|
+
const currentStep = React.useMemo(
|
|
2499
2377
|
() => message.steps?.find(
|
|
2500
2378
|
(s) => s.id === currentExecutingStepId && s.status === "in_progress"
|
|
2501
2379
|
),
|
|
2502
2380
|
[message.steps, currentExecutingStepId]
|
|
2503
2381
|
);
|
|
2504
|
-
const markdownRenderers =
|
|
2382
|
+
const markdownRenderers = React.useMemo(
|
|
2505
2383
|
() => createMarkdownComponents({
|
|
2506
2384
|
isResolvingImages: message.isResolvingImages
|
|
2507
2385
|
}),
|
|
@@ -2575,8 +2453,8 @@ function AgentMessage({
|
|
|
2575
2453
|
}) })
|
|
2576
2454
|
}
|
|
2577
2455
|
) });
|
|
2578
|
-
const stepsToggleRef =
|
|
2579
|
-
const handleStepsToggle =
|
|
2456
|
+
const stepsToggleRef = React.useRef(null);
|
|
2457
|
+
const handleStepsToggle = React.useCallback(() => {
|
|
2580
2458
|
setIsStepsExpanded((prev) => {
|
|
2581
2459
|
const next = !prev;
|
|
2582
2460
|
if (next) {
|
|
@@ -2904,23 +2782,23 @@ function MessageList({
|
|
|
2904
2782
|
isLoadingMoreMessages = false,
|
|
2905
2783
|
hasMoreMessages = false
|
|
2906
2784
|
}) {
|
|
2907
|
-
const scrollRef =
|
|
2908
|
-
const isNearBottomRef =
|
|
2909
|
-
const [showScrollBtn, setShowScrollBtn] =
|
|
2910
|
-
const prevMessageCountRef =
|
|
2911
|
-
const scrollHeightBeforePrependRef =
|
|
2912
|
-
const firstMessageIdRef =
|
|
2913
|
-
const getDistanceFromBottom =
|
|
2785
|
+
const scrollRef = React.useRef(null);
|
|
2786
|
+
const isNearBottomRef = React.useRef(true);
|
|
2787
|
+
const [showScrollBtn, setShowScrollBtn] = React.useState(false);
|
|
2788
|
+
const prevMessageCountRef = React.useRef(messages.length);
|
|
2789
|
+
const scrollHeightBeforePrependRef = React.useRef(null);
|
|
2790
|
+
const firstMessageIdRef = React.useRef(messages[0]?.id);
|
|
2791
|
+
const getDistanceFromBottom = React.useCallback(() => {
|
|
2914
2792
|
const el = scrollRef.current;
|
|
2915
2793
|
if (!el) return 0;
|
|
2916
2794
|
return el.scrollHeight - el.scrollTop - el.clientHeight;
|
|
2917
2795
|
}, []);
|
|
2918
|
-
const scrollToBottom =
|
|
2796
|
+
const scrollToBottom = React.useCallback((behavior = "smooth") => {
|
|
2919
2797
|
const el = scrollRef.current;
|
|
2920
2798
|
if (!el) return;
|
|
2921
2799
|
el.scrollTo({ top: el.scrollHeight, behavior });
|
|
2922
2800
|
}, []);
|
|
2923
|
-
const handleScroll =
|
|
2801
|
+
const handleScroll = React.useCallback(() => {
|
|
2924
2802
|
const el = scrollRef.current;
|
|
2925
2803
|
if (!el) return;
|
|
2926
2804
|
const distance = getDistanceFromBottom();
|
|
@@ -2932,7 +2810,7 @@ function MessageList({
|
|
|
2932
2810
|
onLoadMoreMessages();
|
|
2933
2811
|
}
|
|
2934
2812
|
}, [getDistanceFromBottom, hasMoreMessages, isLoadingMoreMessages, onLoadMoreMessages]);
|
|
2935
|
-
|
|
2813
|
+
React.useLayoutEffect(() => {
|
|
2936
2814
|
const el = scrollRef.current;
|
|
2937
2815
|
const prevHeight = scrollHeightBeforePrependRef.current;
|
|
2938
2816
|
const newFirstId = messages[0]?.id;
|
|
@@ -2942,25 +2820,25 @@ function MessageList({
|
|
|
2942
2820
|
}
|
|
2943
2821
|
firstMessageIdRef.current = newFirstId;
|
|
2944
2822
|
}, [messages]);
|
|
2945
|
-
|
|
2823
|
+
React.useEffect(() => {
|
|
2946
2824
|
const prevCount = prevMessageCountRef.current;
|
|
2947
2825
|
prevMessageCountRef.current = messages.length;
|
|
2948
2826
|
if (messages.length > prevCount && isNearBottomRef.current) {
|
|
2949
2827
|
requestAnimationFrame(() => scrollToBottom());
|
|
2950
2828
|
}
|
|
2951
2829
|
}, [messages.length, scrollToBottom]);
|
|
2952
|
-
|
|
2830
|
+
React.useEffect(() => {
|
|
2953
2831
|
const lastMsg = messages[messages.length - 1];
|
|
2954
2832
|
if (!lastMsg?.isStreaming) return;
|
|
2955
2833
|
if (!isNearBottomRef.current) return;
|
|
2956
2834
|
requestAnimationFrame(() => scrollToBottom());
|
|
2957
2835
|
});
|
|
2958
|
-
|
|
2836
|
+
React.useEffect(() => {
|
|
2959
2837
|
if (messages.length > 0) {
|
|
2960
2838
|
setTimeout(() => scrollToBottom("instant"), 50);
|
|
2961
2839
|
}
|
|
2962
2840
|
}, []);
|
|
2963
|
-
|
|
2841
|
+
React.useEffect(() => {
|
|
2964
2842
|
const handleStepsToggle = () => {
|
|
2965
2843
|
requestAnimationFrame(() => {
|
|
2966
2844
|
requestAnimationFrame(() => {
|
|
@@ -2977,7 +2855,7 @@ function MessageList({
|
|
|
2977
2855
|
return () => el.removeEventListener("payman-steps-toggle", handleStepsToggle);
|
|
2978
2856
|
}
|
|
2979
2857
|
}, [getDistanceFromBottom, scrollToBottom]);
|
|
2980
|
-
const handleScrollToBottom =
|
|
2858
|
+
const handleScrollToBottom = React.useCallback(() => {
|
|
2981
2859
|
scrollToBottom();
|
|
2982
2860
|
}, [scrollToBottom]);
|
|
2983
2861
|
if (isLoading) {
|
|
@@ -3110,7 +2988,7 @@ function ResetSessionConfirmModal({
|
|
|
3110
2988
|
onClose,
|
|
3111
2989
|
onConfirm
|
|
3112
2990
|
}) {
|
|
3113
|
-
const handleKeyDown =
|
|
2991
|
+
const handleKeyDown = React.useCallback(
|
|
3114
2992
|
(event) => {
|
|
3115
2993
|
if (event.key === "Escape") {
|
|
3116
2994
|
onClose();
|
|
@@ -3118,7 +2996,7 @@ function ResetSessionConfirmModal({
|
|
|
3118
2996
|
},
|
|
3119
2997
|
[onClose]
|
|
3120
2998
|
);
|
|
3121
|
-
|
|
2999
|
+
React.useEffect(() => {
|
|
3122
3000
|
if (!isOpen || typeof document === "undefined") return;
|
|
3123
3001
|
document.addEventListener("keydown", handleKeyDown);
|
|
3124
3002
|
const previousOverflow = document.body.style.overflow;
|
|
@@ -3224,14 +3102,14 @@ function UserMessageV2({
|
|
|
3224
3102
|
retryDisabled = false,
|
|
3225
3103
|
actions
|
|
3226
3104
|
}) {
|
|
3227
|
-
const [copied, setCopied] =
|
|
3228
|
-
const [toast, setToast] =
|
|
3229
|
-
const copyResetTimerRef =
|
|
3230
|
-
const toastTimerRef =
|
|
3105
|
+
const [copied, setCopied] = React.useState(false);
|
|
3106
|
+
const [toast, setToast] = React.useState(null);
|
|
3107
|
+
const copyResetTimerRef = React.useRef(null);
|
|
3108
|
+
const toastTimerRef = React.useRef(null);
|
|
3231
3109
|
const showCopyAction = actions?.copy ?? true;
|
|
3232
3110
|
const showEditAction = actions?.edit ?? false;
|
|
3233
3111
|
const showRetryAction = actions?.retry ?? false;
|
|
3234
|
-
|
|
3112
|
+
React.useEffect(() => {
|
|
3235
3113
|
return () => {
|
|
3236
3114
|
if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
|
|
3237
3115
|
if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
|
|
@@ -3387,18 +3265,18 @@ function MarkdownImageV2({
|
|
|
3387
3265
|
onImageClick
|
|
3388
3266
|
}) {
|
|
3389
3267
|
const cachedAlready = src ? loadedImageCache.has(src) : false;
|
|
3390
|
-
const [isVisible, setIsVisible] =
|
|
3391
|
-
const [isLoaded, setIsLoaded] =
|
|
3392
|
-
const [hasError, setHasError] =
|
|
3393
|
-
const [retryCount, setRetryCount] =
|
|
3394
|
-
const sentinelRef =
|
|
3395
|
-
const prevLoadedRef =
|
|
3396
|
-
const isUnresolvedRag =
|
|
3268
|
+
const [isVisible, setIsVisible] = React.useState(cachedAlready);
|
|
3269
|
+
const [isLoaded, setIsLoaded] = React.useState(cachedAlready);
|
|
3270
|
+
const [hasError, setHasError] = React.useState(false);
|
|
3271
|
+
const [retryCount, setRetryCount] = React.useState(0);
|
|
3272
|
+
const sentinelRef = React.useRef(null);
|
|
3273
|
+
const prevLoadedRef = React.useRef(cachedAlready);
|
|
3274
|
+
const isUnresolvedRag = React.useMemo(
|
|
3397
3275
|
() => src ? isUnresolvedRagImageSource2(src) : false,
|
|
3398
3276
|
[src]
|
|
3399
3277
|
);
|
|
3400
3278
|
const isResolvingRag = Boolean(isResolving && isUnresolvedRag);
|
|
3401
|
-
|
|
3279
|
+
React.useEffect(() => {
|
|
3402
3280
|
if (src && loadedImageCache.has(src)) {
|
|
3403
3281
|
setIsLoaded(true);
|
|
3404
3282
|
setIsVisible(true);
|
|
@@ -3407,7 +3285,7 @@ function MarkdownImageV2({
|
|
|
3407
3285
|
setHasError(false);
|
|
3408
3286
|
setRetryCount(0);
|
|
3409
3287
|
}, [src]);
|
|
3410
|
-
|
|
3288
|
+
React.useEffect(() => {
|
|
3411
3289
|
const el = sentinelRef.current;
|
|
3412
3290
|
if (!el || !src) return;
|
|
3413
3291
|
const rect = el.getBoundingClientRect();
|
|
@@ -3528,9 +3406,88 @@ function MarkdownImageV2({
|
|
|
3528
3406
|
}
|
|
3529
3407
|
) });
|
|
3530
3408
|
}
|
|
3531
|
-
|
|
3409
|
+
var RAG_SOURCE_CLASS = "payman-v2-rag-source";
|
|
3410
|
+
var RAG_FOLLOW_UP_CLASS = "payman-v2-rag-follow-up";
|
|
3411
|
+
var SOURCE_PATTERN = /^Sources?:\s*\S/i;
|
|
3412
|
+
var MAX_FOLLOW_UP_LENGTH = 320;
|
|
3413
|
+
var HR_PATTERN = /^-{3,}$|^_{3,}$|^\*{3,}$/;
|
|
3414
|
+
function normalizeRagParagraphText(text) {
|
|
3415
|
+
return text.replace(/\s+/g, " ").trim();
|
|
3416
|
+
}
|
|
3417
|
+
function isRagSourceParagraph(text) {
|
|
3418
|
+
return SOURCE_PATTERN.test(normalizeRagParagraphText(text));
|
|
3419
|
+
}
|
|
3420
|
+
function isRagFollowUpCandidate(text) {
|
|
3421
|
+
const normalized = normalizeRagParagraphText(text);
|
|
3422
|
+
return normalized.length > 0 && normalized.length <= MAX_FOLLOW_UP_LENGTH && normalized.endsWith("?");
|
|
3423
|
+
}
|
|
3424
|
+
function extractRagParagraphTexts(content) {
|
|
3425
|
+
const paragraphs = [];
|
|
3426
|
+
const currentParagraph = [];
|
|
3427
|
+
const flushParagraph = () => {
|
|
3428
|
+
const paragraph = normalizeRagParagraphText(currentParagraph.join(" "));
|
|
3429
|
+
currentParagraph.length = 0;
|
|
3430
|
+
if (paragraph) paragraphs.push(paragraph);
|
|
3431
|
+
};
|
|
3432
|
+
content.replace(/\\n/g, "\n").split(/\r?\n/).forEach((line) => {
|
|
3433
|
+
const trimmedLine = line.trim();
|
|
3434
|
+
if (!trimmedLine) {
|
|
3435
|
+
flushParagraph();
|
|
3436
|
+
return;
|
|
3437
|
+
}
|
|
3438
|
+
if (HR_PATTERN.test(trimmedLine)) {
|
|
3439
|
+
flushParagraph();
|
|
3440
|
+
return;
|
|
3441
|
+
}
|
|
3442
|
+
currentParagraph.push(trimmedLine);
|
|
3443
|
+
});
|
|
3444
|
+
flushParagraph();
|
|
3445
|
+
return paragraphs;
|
|
3446
|
+
}
|
|
3447
|
+
function getRagAnswerParagraphRoles(paragraphs) {
|
|
3448
|
+
const normalized = paragraphs.map(normalizeRagParagraphText);
|
|
3449
|
+
const roles = normalized.map(() => null);
|
|
3450
|
+
const sourceIndexes = normalized.map((paragraph, index) => isRagSourceParagraph(paragraph) ? index : -1).filter((index) => index >= 0);
|
|
3451
|
+
for (const sourceIndex of sourceIndexes) {
|
|
3452
|
+
roles[sourceIndex] = "source";
|
|
3453
|
+
for (const candidateIndex of [sourceIndex - 1, sourceIndex + 1]) {
|
|
3454
|
+
if (candidateIndex >= 0 && candidateIndex < normalized.length && roles[candidateIndex] == null && isRagFollowUpCandidate(normalized[candidateIndex] ?? "")) {
|
|
3455
|
+
roles[candidateIndex] = "follow-up";
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
}
|
|
3459
|
+
return roles;
|
|
3460
|
+
}
|
|
3461
|
+
function getRagAnswerParagraphRole(paragraph, paragraphs) {
|
|
3462
|
+
const normalizedParagraph = normalizeRagParagraphText(paragraph);
|
|
3463
|
+
if (isRagSourceParagraph(normalizedParagraph)) return "source";
|
|
3464
|
+
const roles = getRagAnswerParagraphRoles(paragraphs);
|
|
3465
|
+
return paragraphs.map(normalizeRagParagraphText).some((candidate, index) => {
|
|
3466
|
+
return candidate === normalizedParagraph && roles[index] === "follow-up";
|
|
3467
|
+
}) ? "follow-up" : null;
|
|
3468
|
+
}
|
|
3469
|
+
function ragAnswerRoleClassName(role) {
|
|
3470
|
+
if (role === "source") return RAG_SOURCE_CLASS;
|
|
3471
|
+
if (role === "follow-up") return RAG_FOLLOW_UP_CLASS;
|
|
3472
|
+
return void 0;
|
|
3473
|
+
}
|
|
3474
|
+
function reactNodeText(node) {
|
|
3475
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
3476
|
+
if (Array.isArray(node)) return node.map(reactNodeText).join("");
|
|
3477
|
+
if (React__namespace.isValidElement(node)) {
|
|
3478
|
+
return reactNodeText(node.props.children);
|
|
3479
|
+
}
|
|
3480
|
+
return "";
|
|
3481
|
+
}
|
|
3482
|
+
function buildComponents(onImageClick, isResolvingRef, ragParagraphsRef) {
|
|
3532
3483
|
return {
|
|
3533
|
-
p: ({ children }) =>
|
|
3484
|
+
p: ({ children }) => {
|
|
3485
|
+
const role = getRagAnswerParagraphRole(
|
|
3486
|
+
reactNodeText(children),
|
|
3487
|
+
ragParagraphsRef?.current ?? []
|
|
3488
|
+
);
|
|
3489
|
+
return /* @__PURE__ */ jsxRuntime.jsx("p", { className: ragAnswerRoleClassName(role), children });
|
|
3490
|
+
},
|
|
3534
3491
|
code: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("code", { children }),
|
|
3535
3492
|
pre: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-markdown-pre", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { children }) }),
|
|
3536
3493
|
ul: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { children }),
|
|
@@ -3566,10 +3523,15 @@ function MarkdownRendererV2({
|
|
|
3566
3523
|
isResolvingImages,
|
|
3567
3524
|
onImageClick
|
|
3568
3525
|
}) {
|
|
3569
|
-
const isResolvingRef =
|
|
3526
|
+
const isResolvingRef = React.useRef(isResolvingImages);
|
|
3570
3527
|
isResolvingRef.current = isResolvingImages;
|
|
3571
|
-
const
|
|
3572
|
-
|
|
3528
|
+
const ragParagraphsRef = React.useRef([]);
|
|
3529
|
+
ragParagraphsRef.current = React.useMemo(
|
|
3530
|
+
() => extractRagParagraphTexts(content),
|
|
3531
|
+
[content]
|
|
3532
|
+
);
|
|
3533
|
+
const components = React.useMemo(
|
|
3534
|
+
() => buildComponents(onImageClick, isResolvingRef, ragParagraphsRef),
|
|
3573
3535
|
[onImageClick]
|
|
3574
3536
|
);
|
|
3575
3537
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3626,14 +3588,14 @@ function FeedbackReasonModal({
|
|
|
3626
3588
|
onClose,
|
|
3627
3589
|
onSubmit
|
|
3628
3590
|
}) {
|
|
3629
|
-
const [reason, setReason] =
|
|
3591
|
+
const [reason, setReason] = React.useState(
|
|
3630
3592
|
NEGATIVE_FEEDBACK_REASONS[0].value
|
|
3631
3593
|
);
|
|
3632
|
-
const [details, setDetails] =
|
|
3633
|
-
const [submitting, setSubmitting] =
|
|
3634
|
-
const [error, setError] =
|
|
3635
|
-
const [reasonOpen, setReasonOpen] =
|
|
3636
|
-
|
|
3594
|
+
const [details, setDetails] = React.useState("");
|
|
3595
|
+
const [submitting, setSubmitting] = React.useState(false);
|
|
3596
|
+
const [error, setError] = React.useState(null);
|
|
3597
|
+
const [reasonOpen, setReasonOpen] = React.useState(false);
|
|
3598
|
+
React.useEffect(() => {
|
|
3637
3599
|
if (open) {
|
|
3638
3600
|
setReason(NEGATIVE_FEEDBACK_REASONS[0].value);
|
|
3639
3601
|
setDetails("");
|
|
@@ -3642,7 +3604,7 @@ function FeedbackReasonModal({
|
|
|
3642
3604
|
setReasonOpen(false);
|
|
3643
3605
|
}
|
|
3644
3606
|
}, [open]);
|
|
3645
|
-
const handleKeyDown =
|
|
3607
|
+
const handleKeyDown = React.useCallback(
|
|
3646
3608
|
(event) => {
|
|
3647
3609
|
if (event.key !== "Escape") return;
|
|
3648
3610
|
if (reasonOpen) {
|
|
@@ -3653,7 +3615,7 @@ function FeedbackReasonModal({
|
|
|
3653
3615
|
},
|
|
3654
3616
|
[onClose, reasonOpen]
|
|
3655
3617
|
);
|
|
3656
|
-
|
|
3618
|
+
React.useEffect(() => {
|
|
3657
3619
|
if (!open || typeof document === "undefined") return;
|
|
3658
3620
|
document.addEventListener("keydown", handleKeyDown);
|
|
3659
3621
|
const previousOverflow = document.body.style.overflow;
|
|
@@ -3857,17 +3819,17 @@ function charDelay(char, speed, multiplier) {
|
|
|
3857
3819
|
function useTypingEffect(targetText, enabled, speed = RESPONSE_SPEED, initialDisplayedText, speedMultiplier = 1) {
|
|
3858
3820
|
const instant = speedMultiplier === 0;
|
|
3859
3821
|
const multiplier = instant ? 1 : Math.max(speedMultiplier, 0.1);
|
|
3860
|
-
const [displayedText, setDisplayedText] =
|
|
3861
|
-
const displayedRef =
|
|
3862
|
-
const targetRef =
|
|
3863
|
-
const enabledRef =
|
|
3864
|
-
const initialDisplayedRef =
|
|
3865
|
-
const timerRef =
|
|
3866
|
-
const runningRef =
|
|
3822
|
+
const [displayedText, setDisplayedText] = React.useState("");
|
|
3823
|
+
const displayedRef = React.useRef("");
|
|
3824
|
+
const targetRef = React.useRef(targetText);
|
|
3825
|
+
const enabledRef = React.useRef(enabled);
|
|
3826
|
+
const initialDisplayedRef = React.useRef(initialDisplayedText);
|
|
3827
|
+
const timerRef = React.useRef(null);
|
|
3828
|
+
const runningRef = React.useRef(false);
|
|
3867
3829
|
targetRef.current = targetText;
|
|
3868
3830
|
enabledRef.current = enabled;
|
|
3869
3831
|
initialDisplayedRef.current = initialDisplayedText;
|
|
3870
|
-
|
|
3832
|
+
React.useEffect(() => {
|
|
3871
3833
|
if (!enabled || instant) {
|
|
3872
3834
|
if (timerRef.current) {
|
|
3873
3835
|
clearTimeout(timerRef.current);
|
|
@@ -3957,26 +3919,26 @@ function AssistantMessageV2({
|
|
|
3957
3919
|
actions,
|
|
3958
3920
|
typingSpeed = 4
|
|
3959
3921
|
}) {
|
|
3960
|
-
const [copied, setCopied] =
|
|
3961
|
-
const [activeFeedback, setActiveFeedback] =
|
|
3922
|
+
const [copied, setCopied] = React.useState(false);
|
|
3923
|
+
const [activeFeedback, setActiveFeedback] = React.useState(
|
|
3962
3924
|
() => getFeedbackState(message)
|
|
3963
3925
|
);
|
|
3964
|
-
const [reasonModalOpen, setReasonModalOpen] =
|
|
3926
|
+
const [reasonModalOpen, setReasonModalOpen] = React.useState(false);
|
|
3965
3927
|
const canSubmitFeedback = !!onSubmitFeedback && !!message.executionId;
|
|
3966
|
-
const [toast, setToast] =
|
|
3967
|
-
const copyResetTimerRef =
|
|
3968
|
-
const toastTimerRef =
|
|
3928
|
+
const [toast, setToast] = React.useState(null);
|
|
3929
|
+
const copyResetTimerRef = React.useRef(null);
|
|
3930
|
+
const toastTimerRef = React.useRef(null);
|
|
3969
3931
|
const showCopyAction = actions?.copy ?? true;
|
|
3970
3932
|
const showTraceAction = (actions?.trace ?? true) && !!onExecutionTraceClick;
|
|
3971
3933
|
const showThumbsUp = actions?.thumbsUp ?? true;
|
|
3972
3934
|
const showThumbsDown = actions?.thumbsDown ?? true;
|
|
3973
3935
|
const hydratedFeedback = message.feedback;
|
|
3974
|
-
const hasEverStreamed =
|
|
3936
|
+
const hasEverStreamed = React.useRef(!!message.isStreaming);
|
|
3975
3937
|
if (message.isStreaming) hasEverStreamed.current = true;
|
|
3976
|
-
|
|
3938
|
+
React.useEffect(() => {
|
|
3977
3939
|
setActiveFeedback(getFeedbackState(message));
|
|
3978
3940
|
}, [hydratedFeedback, message.id]);
|
|
3979
|
-
|
|
3941
|
+
React.useEffect(() => {
|
|
3980
3942
|
return () => {
|
|
3981
3943
|
if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
|
|
3982
3944
|
if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
|
|
@@ -4270,10 +4232,10 @@ function OtpInputV2({
|
|
|
4270
4232
|
disabled = false,
|
|
4271
4233
|
error = false
|
|
4272
4234
|
}) {
|
|
4273
|
-
const inputRefs =
|
|
4235
|
+
const inputRefs = React.useRef([]);
|
|
4274
4236
|
const safeMaxLength = Number.isInteger(maxLength) && maxLength > 0 ? Math.min(maxLength, MAX_SUPPORTED_LENGTH) : DEFAULT_MAX_LENGTH;
|
|
4275
4237
|
const digits = value.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
|
|
4276
|
-
|
|
4238
|
+
React.useEffect(() => {
|
|
4277
4239
|
if (disabled) return;
|
|
4278
4240
|
const timer = window.setTimeout(() => {
|
|
4279
4241
|
inputRefs.current[0]?.focus();
|
|
@@ -4372,31 +4334,31 @@ function VerificationInline({
|
|
|
4372
4334
|
onResend
|
|
4373
4335
|
}) {
|
|
4374
4336
|
const isNumeric = prompt.verificationType !== "ALPHANUMERIC_CODE";
|
|
4375
|
-
const codeLen =
|
|
4376
|
-
const [code, setCode] =
|
|
4377
|
-
const [errored, setErrored] =
|
|
4378
|
-
const [resendSec, setResendSec] =
|
|
4379
|
-
const [hiddenAfterResend, setHiddenAfterResend] =
|
|
4380
|
-
const lastSubmittedRef =
|
|
4381
|
-
const resendTimerRef =
|
|
4337
|
+
const codeLen = React.useMemo(() => codeLengthFromSchema(prompt), [prompt]);
|
|
4338
|
+
const [code, setCode] = React.useState("");
|
|
4339
|
+
const [errored, setErrored] = React.useState(false);
|
|
4340
|
+
const [resendSec, setResendSec] = React.useState(0);
|
|
4341
|
+
const [hiddenAfterResend, setHiddenAfterResend] = React.useState(false);
|
|
4342
|
+
const lastSubmittedRef = React.useRef(null);
|
|
4343
|
+
const resendTimerRef = React.useRef(void 0);
|
|
4382
4344
|
const status = prompt.status;
|
|
4383
4345
|
const busy = status === "submitting";
|
|
4384
4346
|
const stale = status === "stale";
|
|
4385
4347
|
const locked = busy || stale || expired;
|
|
4386
|
-
|
|
4348
|
+
React.useEffect(() => {
|
|
4387
4349
|
if (prompt.subAction === "SubmissionInvalid") {
|
|
4388
4350
|
setErrored(true);
|
|
4389
4351
|
setCode("");
|
|
4390
4352
|
lastSubmittedRef.current = null;
|
|
4391
4353
|
}
|
|
4392
4354
|
}, [prompt.subAction, prompt.userActionId]);
|
|
4393
|
-
|
|
4355
|
+
React.useEffect(() => {
|
|
4394
4356
|
setHiddenAfterResend(false);
|
|
4395
4357
|
}, [prompt.expirySeconds, prompt.message, prompt.subAction, prompt.userActionId]);
|
|
4396
|
-
|
|
4358
|
+
React.useEffect(() => {
|
|
4397
4359
|
if (code.length < codeLen) lastSubmittedRef.current = null;
|
|
4398
4360
|
}, [code, codeLen]);
|
|
4399
|
-
const doSubmit =
|
|
4361
|
+
const doSubmit = React.useCallback(
|
|
4400
4362
|
(value) => {
|
|
4401
4363
|
if (locked || !value) return;
|
|
4402
4364
|
if (lastSubmittedRef.current === value) return;
|
|
@@ -4408,20 +4370,20 @@ function VerificationInline({
|
|
|
4408
4370
|
},
|
|
4409
4371
|
[locked, onSubmit, prompt.userActionId]
|
|
4410
4372
|
);
|
|
4411
|
-
|
|
4373
|
+
React.useEffect(() => {
|
|
4412
4374
|
if (!isNumeric || locked) return;
|
|
4413
4375
|
if (code.length === codeLen && /^\d+$/.test(code)) {
|
|
4414
4376
|
doSubmit(code);
|
|
4415
4377
|
}
|
|
4416
4378
|
}, [code, codeLen, doSubmit, isNumeric, locked]);
|
|
4417
|
-
|
|
4379
|
+
React.useEffect(() => {
|
|
4418
4380
|
return () => {
|
|
4419
4381
|
if (typeof resendTimerRef.current === "number") {
|
|
4420
4382
|
window.clearInterval(resendTimerRef.current);
|
|
4421
4383
|
}
|
|
4422
4384
|
};
|
|
4423
4385
|
}, []);
|
|
4424
|
-
const startResendCooldown =
|
|
4386
|
+
const startResendCooldown = React.useCallback(() => {
|
|
4425
4387
|
setResendSec(RESEND_COOLDOWN_S);
|
|
4426
4388
|
if (typeof resendTimerRef.current === "number") {
|
|
4427
4389
|
window.clearInterval(resendTimerRef.current);
|
|
@@ -4439,7 +4401,7 @@ function VerificationInline({
|
|
|
4439
4401
|
});
|
|
4440
4402
|
}, 1e3);
|
|
4441
4403
|
}, []);
|
|
4442
|
-
const handleResend =
|
|
4404
|
+
const handleResend = React.useCallback(async () => {
|
|
4443
4405
|
if (locked || resendSec > 0) return;
|
|
4444
4406
|
setErrored(false);
|
|
4445
4407
|
setCode("");
|
|
@@ -4452,7 +4414,7 @@ function VerificationInline({
|
|
|
4452
4414
|
setHiddenAfterResend(false);
|
|
4453
4415
|
}
|
|
4454
4416
|
}, [locked, onResend, prompt.userActionId, resendSec, startResendCooldown]);
|
|
4455
|
-
const handleCancel =
|
|
4417
|
+
const handleCancel = React.useCallback(() => {
|
|
4456
4418
|
if (busy) return;
|
|
4457
4419
|
void onCancel(prompt.userActionId);
|
|
4458
4420
|
}, [busy, onCancel, prompt.userActionId]);
|
|
@@ -4542,13 +4504,13 @@ function SchemaFormInline({
|
|
|
4542
4504
|
onCancel
|
|
4543
4505
|
}) {
|
|
4544
4506
|
const schema = prompt.requestedSchema;
|
|
4545
|
-
const fields =
|
|
4546
|
-
const [values, setValues] =
|
|
4507
|
+
const fields = React.useMemo(() => renderableFields(schema), [schema]);
|
|
4508
|
+
const [values, setValues] = React.useState(() => {
|
|
4547
4509
|
const init2 = {};
|
|
4548
4510
|
for (const [key, field] of fields) init2[key] = defaultValueFor(field);
|
|
4549
4511
|
return init2;
|
|
4550
4512
|
});
|
|
4551
|
-
const [errors, setErrors] =
|
|
4513
|
+
const [errors, setErrors] = React.useState({});
|
|
4552
4514
|
const status = prompt.status;
|
|
4553
4515
|
const busy = status === "submitting";
|
|
4554
4516
|
const stale = status === "stale";
|
|
@@ -4689,24 +4651,34 @@ function NotificationInline({ notification, onDismiss }) {
|
|
|
4689
4651
|
}
|
|
4690
4652
|
function useExpiryCountdown(prompt) {
|
|
4691
4653
|
const initial = typeof prompt.expirySeconds === "number" && prompt.expirySeconds > 0 ? Math.floor(prompt.expirySeconds) : void 0;
|
|
4692
|
-
const [secondsLeft, setSecondsLeft] =
|
|
4693
|
-
|
|
4654
|
+
const [secondsLeft, setSecondsLeft] = React.useState(initial);
|
|
4655
|
+
React.useEffect(() => {
|
|
4694
4656
|
if (initial === void 0) {
|
|
4695
4657
|
setSecondsLeft(void 0);
|
|
4696
4658
|
return;
|
|
4697
4659
|
}
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
}
|
|
4708
|
-
}
|
|
4709
|
-
|
|
4660
|
+
const deadlineMs = Date.now() + initial * 1e3;
|
|
4661
|
+
let intervalId;
|
|
4662
|
+
const remaining = () => Math.max(0, Math.ceil((deadlineMs - Date.now()) / 1e3));
|
|
4663
|
+
const sync = () => {
|
|
4664
|
+
const next = remaining();
|
|
4665
|
+
setSecondsLeft(next);
|
|
4666
|
+
if (next === 0 && intervalId !== void 0) {
|
|
4667
|
+
window.clearInterval(intervalId);
|
|
4668
|
+
intervalId = void 0;
|
|
4669
|
+
}
|
|
4670
|
+
};
|
|
4671
|
+
sync();
|
|
4672
|
+
intervalId = window.setInterval(sync, 1e3);
|
|
4673
|
+
document.addEventListener("visibilitychange", sync);
|
|
4674
|
+
window.addEventListener("focus", sync);
|
|
4675
|
+
window.addEventListener("pageshow", sync);
|
|
4676
|
+
return () => {
|
|
4677
|
+
if (intervalId !== void 0) window.clearInterval(intervalId);
|
|
4678
|
+
document.removeEventListener("visibilitychange", sync);
|
|
4679
|
+
window.removeEventListener("focus", sync);
|
|
4680
|
+
window.removeEventListener("pageshow", sync);
|
|
4681
|
+
};
|
|
4710
4682
|
}, [prompt.userActionId, prompt.subAction, initial]);
|
|
4711
4683
|
const expired = initial !== void 0 && secondsLeft === 0;
|
|
4712
4684
|
return [secondsLeft, expired];
|
|
@@ -4719,7 +4691,7 @@ function UserActionInline({
|
|
|
4719
4691
|
onExpired
|
|
4720
4692
|
}) {
|
|
4721
4693
|
const [secondsLeft, expired] = useExpiryCountdown(prompt);
|
|
4722
|
-
|
|
4694
|
+
React.useEffect(() => {
|
|
4723
4695
|
if (expired && prompt.kind !== "notification") onExpired?.();
|
|
4724
4696
|
}, [expired, onExpired, prompt.kind]);
|
|
4725
4697
|
let body;
|
|
@@ -4782,7 +4754,7 @@ function getPromptViewKey(prompt) {
|
|
|
4782
4754
|
prompt.message ?? ""
|
|
4783
4755
|
].join(PROMPT_KEY_SEPARATOR);
|
|
4784
4756
|
}
|
|
4785
|
-
var MessageListV2 =
|
|
4757
|
+
var MessageListV2 = React.forwardRef(
|
|
4786
4758
|
function MessageListV22({
|
|
4787
4759
|
messages,
|
|
4788
4760
|
isStreaming = false,
|
|
@@ -4802,25 +4774,25 @@ var MessageListV2 = react.forwardRef(
|
|
|
4802
4774
|
onSubmitFeedback,
|
|
4803
4775
|
typingSpeed = 4
|
|
4804
4776
|
}, ref) {
|
|
4805
|
-
const noop =
|
|
4777
|
+
const noop = React.useCallback(async () => {
|
|
4806
4778
|
}, []);
|
|
4807
|
-
const scrollRef =
|
|
4808
|
-
const scrollInnerRef =
|
|
4809
|
-
const isNearBottomRef =
|
|
4810
|
-
const [showScrollBtn, setShowScrollBtn] =
|
|
4811
|
-
const [expiredPromptViewState, setExpiredPromptViewState] =
|
|
4812
|
-
const expiredUserActionIdsRef =
|
|
4813
|
-
const prevCountRef =
|
|
4814
|
-
const pauseStickUntilUserMessageRef =
|
|
4815
|
-
const followingBottomRef =
|
|
4816
|
-
const lastPinAtRef =
|
|
4817
|
-
const prevScrollTopRef =
|
|
4818
|
-
const getDistanceFromBottom =
|
|
4779
|
+
const scrollRef = React.useRef(null);
|
|
4780
|
+
const scrollInnerRef = React.useRef(null);
|
|
4781
|
+
const isNearBottomRef = React.useRef(true);
|
|
4782
|
+
const [showScrollBtn, setShowScrollBtn] = React.useState(false);
|
|
4783
|
+
const [expiredPromptViewState, setExpiredPromptViewState] = React.useState({});
|
|
4784
|
+
const expiredUserActionIdsRef = React.useRef(/* @__PURE__ */ new Set());
|
|
4785
|
+
const prevCountRef = React.useRef(messages.length);
|
|
4786
|
+
const pauseStickUntilUserMessageRef = React.useRef(false);
|
|
4787
|
+
const followingBottomRef = React.useRef(true);
|
|
4788
|
+
const lastPinAtRef = React.useRef(0);
|
|
4789
|
+
const prevScrollTopRef = React.useRef(0);
|
|
4790
|
+
const getDistanceFromBottom = React.useCallback(() => {
|
|
4819
4791
|
const el = scrollRef.current;
|
|
4820
4792
|
if (!el) return 0;
|
|
4821
4793
|
return el.scrollHeight - el.scrollTop - el.clientHeight;
|
|
4822
4794
|
}, []);
|
|
4823
|
-
const messageActivityFingerprint =
|
|
4795
|
+
const messageActivityFingerprint = React.useMemo(() => {
|
|
4824
4796
|
const last = messages[messages.length - 1];
|
|
4825
4797
|
const promptFingerprint = (userActionPrompts ?? []).map((prompt) => `${getPromptViewKey(prompt)}:${prompt.status}`).join(PROMPT_KEY_SEPARATOR);
|
|
4826
4798
|
const notificationFingerprint = (notifications ?? []).map((notification) => notification.id).join(PROMPT_KEY_SEPARATOR);
|
|
@@ -4846,7 +4818,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4846
4818
|
notificationFingerprint
|
|
4847
4819
|
].join(PROMPT_KEY_SEPARATOR);
|
|
4848
4820
|
}, [isStreaming, messages, notifications, userActionPrompts]);
|
|
4849
|
-
const handleUserActionExpired =
|
|
4821
|
+
const handleUserActionExpired = React.useCallback(
|
|
4850
4822
|
(promptKey, userActionId) => {
|
|
4851
4823
|
setExpiredPromptViewState((prev) => {
|
|
4852
4824
|
if (prev[promptKey]) return prev;
|
|
@@ -4863,7 +4835,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4863
4835
|
},
|
|
4864
4836
|
[messageActivityFingerprint, onExpireUserAction]
|
|
4865
4837
|
);
|
|
4866
|
-
|
|
4838
|
+
React.useEffect(() => {
|
|
4867
4839
|
setExpiredPromptViewState((prev) => {
|
|
4868
4840
|
let changed = false;
|
|
4869
4841
|
const next = {};
|
|
@@ -4878,7 +4850,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4878
4850
|
return changed ? next : prev;
|
|
4879
4851
|
});
|
|
4880
4852
|
}, [messageActivityFingerprint]);
|
|
4881
|
-
|
|
4853
|
+
React.useEffect(() => {
|
|
4882
4854
|
const livePromptKeys = new Set((userActionPrompts ?? []).map(getPromptViewKey));
|
|
4883
4855
|
const liveUserActionIds = new Set((userActionPrompts ?? []).map((p) => p.userActionId));
|
|
4884
4856
|
for (const userActionId of expiredUserActionIdsRef.current) {
|
|
@@ -4899,21 +4871,21 @@ var MessageListV2 = react.forwardRef(
|
|
|
4899
4871
|
return changed ? next : prev;
|
|
4900
4872
|
});
|
|
4901
4873
|
}, [userActionPrompts]);
|
|
4902
|
-
const visibleUserActionPrompts =
|
|
4874
|
+
const visibleUserActionPrompts = React.useMemo(
|
|
4903
4875
|
() => userActionPrompts?.filter((prompt) => {
|
|
4904
4876
|
const promptKey = getPromptViewKey(prompt);
|
|
4905
4877
|
return !expiredPromptViewState[promptKey]?.hidden;
|
|
4906
4878
|
}),
|
|
4907
4879
|
[expiredPromptViewState, userActionPrompts]
|
|
4908
4880
|
);
|
|
4909
|
-
const pinToBottom =
|
|
4881
|
+
const pinToBottom = React.useCallback((behavior = "instant") => {
|
|
4910
4882
|
const el = scrollRef.current;
|
|
4911
4883
|
if (!el) return;
|
|
4912
4884
|
lastPinAtRef.current = performance.now();
|
|
4913
4885
|
el.scrollTo({ top: el.scrollHeight, behavior });
|
|
4914
4886
|
prevScrollTopRef.current = el.scrollHeight;
|
|
4915
4887
|
}, []);
|
|
4916
|
-
const scrollToBottom =
|
|
4888
|
+
const scrollToBottom = React.useCallback(
|
|
4917
4889
|
(behavior = "smooth") => {
|
|
4918
4890
|
const el = scrollRef.current;
|
|
4919
4891
|
if (!el) return;
|
|
@@ -4923,7 +4895,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4923
4895
|
},
|
|
4924
4896
|
[pinToBottom]
|
|
4925
4897
|
);
|
|
4926
|
-
|
|
4898
|
+
React.useImperativeHandle(
|
|
4927
4899
|
ref,
|
|
4928
4900
|
() => ({
|
|
4929
4901
|
scrollToBottom: (behavior = "smooth") => {
|
|
@@ -4936,7 +4908,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4936
4908
|
}),
|
|
4937
4909
|
[scrollToBottom]
|
|
4938
4910
|
);
|
|
4939
|
-
const handleScroll =
|
|
4911
|
+
const handleScroll = React.useCallback(() => {
|
|
4940
4912
|
const el = scrollRef.current;
|
|
4941
4913
|
if (!el) return;
|
|
4942
4914
|
const currentScrollTop = el.scrollTop;
|
|
@@ -4957,7 +4929,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4957
4929
|
pauseStickUntilUserMessageRef.current = false;
|
|
4958
4930
|
}
|
|
4959
4931
|
}, [getDistanceFromBottom]);
|
|
4960
|
-
|
|
4932
|
+
React.useEffect(() => {
|
|
4961
4933
|
const prevCount = prevCountRef.current;
|
|
4962
4934
|
prevCountRef.current = messages.length;
|
|
4963
4935
|
if (messages.length > prevCount) {
|
|
@@ -4971,7 +4943,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4971
4943
|
}
|
|
4972
4944
|
}
|
|
4973
4945
|
}, [messages.length, scrollToBottom]);
|
|
4974
|
-
|
|
4946
|
+
React.useEffect(() => {
|
|
4975
4947
|
const inner = scrollInnerRef.current;
|
|
4976
4948
|
if (!inner) return;
|
|
4977
4949
|
const pinIfFollowing = () => {
|
|
@@ -4996,7 +4968,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
4996
4968
|
mo.disconnect();
|
|
4997
4969
|
};
|
|
4998
4970
|
}, [pinToBottom]);
|
|
4999
|
-
|
|
4971
|
+
React.useEffect(() => {
|
|
5000
4972
|
if (messages.length > 0) {
|
|
5001
4973
|
setTimeout(() => scrollToBottom("instant"), 50);
|
|
5002
4974
|
}
|
|
@@ -5085,7 +5057,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
5085
5057
|
] });
|
|
5086
5058
|
}
|
|
5087
5059
|
);
|
|
5088
|
-
var ChatInputV2 =
|
|
5060
|
+
var ChatInputV2 = React.forwardRef(
|
|
5089
5061
|
function ChatInputV22({
|
|
5090
5062
|
onSend,
|
|
5091
5063
|
disabled = false,
|
|
@@ -5109,20 +5081,20 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5109
5081
|
onAnalysisModeChange,
|
|
5110
5082
|
slashCommands = []
|
|
5111
5083
|
}, ref) {
|
|
5112
|
-
const [value, setValue] =
|
|
5113
|
-
const [isFocused, setIsFocused] =
|
|
5114
|
-
const [showActions, setShowActions] =
|
|
5115
|
-
const [showVoiceTooltip, setShowVoiceTooltip] =
|
|
5116
|
-
const [selectedCommandIndex, setSelectedCommandIndex] =
|
|
5117
|
-
const [inlineHint, setInlineHint] =
|
|
5118
|
-
const [commandMenuDismissed, setCommandMenuDismissed] =
|
|
5119
|
-
const textareaRef =
|
|
5120
|
-
const actionsRef =
|
|
5121
|
-
const preRecordTextRef =
|
|
5122
|
-
const voiceTooltipTimerRef =
|
|
5084
|
+
const [value, setValue] = React.useState("");
|
|
5085
|
+
const [isFocused, setIsFocused] = React.useState(false);
|
|
5086
|
+
const [showActions, setShowActions] = React.useState(false);
|
|
5087
|
+
const [showVoiceTooltip, setShowVoiceTooltip] = React.useState(false);
|
|
5088
|
+
const [selectedCommandIndex, setSelectedCommandIndex] = React.useState(0);
|
|
5089
|
+
const [inlineHint, setInlineHint] = React.useState(null);
|
|
5090
|
+
const [commandMenuDismissed, setCommandMenuDismissed] = React.useState(false);
|
|
5091
|
+
const textareaRef = React.useRef(null);
|
|
5092
|
+
const actionsRef = React.useRef(null);
|
|
5093
|
+
const preRecordTextRef = React.useRef("");
|
|
5094
|
+
const voiceTooltipTimerRef = React.useRef(
|
|
5123
5095
|
null
|
|
5124
5096
|
);
|
|
5125
|
-
const voiceDraftSyncActiveRef =
|
|
5097
|
+
const voiceDraftSyncActiveRef = React.useRef(false);
|
|
5126
5098
|
const isInputLocked = disabled || isRecording;
|
|
5127
5099
|
const hasAttachmentOptions = showUploadImageButton || showAttachFileButton;
|
|
5128
5100
|
const showAttachmentMenuButton = showAttachmentButton && hasAttachmentOptions;
|
|
@@ -5133,14 +5105,14 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5133
5105
|
(command) => command.name.toLowerCase().startsWith(commandQuery)
|
|
5134
5106
|
);
|
|
5135
5107
|
const showCommandSuggestions = !commandMenuDismissed && !isRecording && !disabled && commandSuggestions.length > 0;
|
|
5136
|
-
|
|
5108
|
+
React.useEffect(() => {
|
|
5137
5109
|
if (textareaRef.current) {
|
|
5138
5110
|
textareaRef.current.style.height = "auto";
|
|
5139
5111
|
const scrollHeight = textareaRef.current.scrollHeight;
|
|
5140
5112
|
textareaRef.current.style.height = `${Math.min(scrollHeight, 200)}px`;
|
|
5141
5113
|
}
|
|
5142
5114
|
}, [value]);
|
|
5143
|
-
|
|
5115
|
+
React.useEffect(() => {
|
|
5144
5116
|
if (disabled) {
|
|
5145
5117
|
setIsFocused(false);
|
|
5146
5118
|
setShowActions(false);
|
|
@@ -5150,7 +5122,7 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5150
5122
|
const frameId = requestAnimationFrame(() => textareaRef.current?.focus());
|
|
5151
5123
|
return () => cancelAnimationFrame(frameId);
|
|
5152
5124
|
}, [disabled]);
|
|
5153
|
-
|
|
5125
|
+
React.useImperativeHandle(
|
|
5154
5126
|
ref,
|
|
5155
5127
|
() => ({
|
|
5156
5128
|
setDraft: (message) => {
|
|
@@ -5167,7 +5139,7 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5167
5139
|
}),
|
|
5168
5140
|
[disabled]
|
|
5169
5141
|
);
|
|
5170
|
-
|
|
5142
|
+
React.useEffect(() => {
|
|
5171
5143
|
if (!showActions) return;
|
|
5172
5144
|
const handleClickOutside = (e) => {
|
|
5173
5145
|
if (actionsRef.current && !actionsRef.current.contains(e.target)) {
|
|
@@ -5177,29 +5149,29 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5177
5149
|
document.addEventListener("mousedown", handleClickOutside);
|
|
5178
5150
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
5179
5151
|
}, [showActions]);
|
|
5180
|
-
|
|
5152
|
+
React.useEffect(() => {
|
|
5181
5153
|
if (!showAttachmentMenuButton) {
|
|
5182
5154
|
setShowActions(false);
|
|
5183
5155
|
}
|
|
5184
5156
|
}, [showAttachmentMenuButton]);
|
|
5185
|
-
|
|
5157
|
+
React.useEffect(() => {
|
|
5186
5158
|
setSelectedCommandIndex(0);
|
|
5187
5159
|
setCommandMenuDismissed(false);
|
|
5188
5160
|
}, [commandQuery]);
|
|
5189
|
-
|
|
5161
|
+
React.useEffect(() => {
|
|
5190
5162
|
return () => {
|
|
5191
5163
|
if (voiceTooltipTimerRef.current) {
|
|
5192
5164
|
clearTimeout(voiceTooltipTimerRef.current);
|
|
5193
5165
|
}
|
|
5194
5166
|
};
|
|
5195
5167
|
}, []);
|
|
5196
|
-
|
|
5168
|
+
React.useEffect(() => {
|
|
5197
5169
|
if (!voiceDraftSyncActiveRef.current) return;
|
|
5198
5170
|
const base = preRecordTextRef.current;
|
|
5199
5171
|
const separator = base && !base.endsWith(" ") && transcribedText ? " " : "";
|
|
5200
5172
|
setValue(`${base}${separator}${transcribedText}`);
|
|
5201
5173
|
}, [isRecording, transcribedText]);
|
|
5202
|
-
const handleSend =
|
|
5174
|
+
const handleSend = React.useCallback(() => {
|
|
5203
5175
|
if (!value.trim() || disabled) return;
|
|
5204
5176
|
const commandHint = getSlashCommandValidationHint(value);
|
|
5205
5177
|
if (commandHint) {
|
|
@@ -5219,7 +5191,7 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5219
5191
|
}
|
|
5220
5192
|
});
|
|
5221
5193
|
}, [value, disabled, onClearEditing, onSend]);
|
|
5222
|
-
const selectCommand =
|
|
5194
|
+
const selectCommand = React.useCallback(
|
|
5223
5195
|
(command) => {
|
|
5224
5196
|
const insertText = command.insertText ?? `${command.name} `;
|
|
5225
5197
|
setValue(insertText);
|
|
@@ -5275,14 +5247,14 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5275
5247
|
onAttachFileClick?.();
|
|
5276
5248
|
setShowActions(false);
|
|
5277
5249
|
};
|
|
5278
|
-
const hideVoiceTooltip =
|
|
5250
|
+
const hideVoiceTooltip = React.useCallback(() => {
|
|
5279
5251
|
if (voiceTooltipTimerRef.current) {
|
|
5280
5252
|
clearTimeout(voiceTooltipTimerRef.current);
|
|
5281
5253
|
voiceTooltipTimerRef.current = null;
|
|
5282
5254
|
}
|
|
5283
5255
|
setShowVoiceTooltip(false);
|
|
5284
5256
|
}, []);
|
|
5285
|
-
const startVoiceTooltipTimer =
|
|
5257
|
+
const startVoiceTooltipTimer = React.useCallback(() => {
|
|
5286
5258
|
if (isVoiceButtonDisabled || isRecording) return;
|
|
5287
5259
|
if (voiceTooltipTimerRef.current) {
|
|
5288
5260
|
clearTimeout(voiceTooltipTimerRef.current);
|
|
@@ -5604,9 +5576,9 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5604
5576
|
var thinking_atom_default = "data:application/zip;base64,UEsDBBQAAAAIAMWrkFzFrMWzUgAAAF4AAAANAAAAbWFuaWZlc3QuanNvbqtWKkstKs7Mz1OyUjJS0lFKT81LLUosyS8C8h1S8kty8ktKMlP14SzdrGIHQz0zPZDaxLzM3MQSoN5iJavoaqXMFKAe38TMPIXgZKApSrWxtQBQSwMEFAAAAAgAxauQXLRghFpXBAAA1RwAABEAAABhL01haW4gU2NlbmUuanNvbu1YWW/jNhD+KwafJVWkqMtPbdEDfdiiQIq+GMZCcei1GvmApLRdGP7v/YYiddqbGNumR4wcomZGHM7B76N0ZLstm7N3Wb6b3a3UTjGHPTw8sLnvsA2bCx/X3811q+qMzY/sAx74stjXda7WeaGqL1alyup9OeNeEnmcnRxWZB9VWbH54sjqj2weOI2bH5+KYibhoirZnONSa0f7AzykGOQYkGP4X2dFpbq13ONx0mTVu6x6bNXZXosf4erI9OLwjwRw7Tv4WWLSP+ALa7I2Rs0RkvkzRhEZQdWz8iHCms48Z54RMEAs2gABkcGRYVFHBqXv8Sh2GBKgRzDNW00SIClag1GzugVNShk5OUd9zxMj4cI/2UhoSdUwVBJpn53EGPMTOd0hh8hAUwuodC1UoVZ1ud+9UjWog+jvb6hIv9D9egxT8aK8kfte5tD5kiTYCfpaqvUPyABb7beH9/57zlUi4zBwE+FnrsyUdDOfC/c+iNVqzVOVKoH06vwLLDsr1Y6q+VZLgX7+dxQDW29SDGmKsVNPr1iLSyB1Bkui0CDGAEdkEmmpeXghQwe/Td0slnRzyDQ5NwdH8L05htXHLGFqIWk0fQ+YPhc9P3+3VpvsoDrSYR9KFNHWpKvWdgfdV998/e3sF2w70Nb35f7pAFNdfn0z49QpNLHDVnqh0FL9IUXU1kG1eZmDO1rYzB06+imrN30/hNG9JmkiPLIVm9flE2ZFuRZoFzf0hIyXzkJfqXcgtLJGCSHyi1SR/URF9pNJYP8b2adeaEwwoqc6AQ2XS+obXTi7bdi6eGmWs8MmXyEN3+UFPaOzQGOdBcQ52BeeDGXqgB3jRNIlirBe7Vs2TYNkXeiGsFtcTS0w3XLPAp8x0MQ86uluEVPse66t9R4ZdbVd88Vw4tNpqTcZIZekEUrFQi/2fAS3hqPIwBMXSIqBp6yqVN1shjHH5NejpvUyOtdZzNyX93lNVfwPn+vGrHjDpiuxSXAvFIHDhSdFRNghvcSPnMQLhKRbo3dbg0bvNgYWsZ4xcz7txuIYrGOfOzz0/JiTUZB4acwdVwiNa43abfVGrbVnMA79fCXG3WGvPdLLlM5nc6czWiBpKFXxq07ptqBOudg7hDI49vRUOAJYuJggZiQDrqFSxA6CMgj2/8PCNqDty6oCjqlViaL8XOb0iC4JjWfU51Xb6CiLunz8CiPop0cnnIb6Ryd7YGpf4bqTUmhPSpSSYXxuSsBtk3ztGkQwPAJS7QevkWdOa2SLNLSn378smfqMTZF0yRzV8Ez4SToNf4i5drmWByfHdk1B5PxGQW+Xgix5jMlhTB5jchlS0CeNOiK74GREQROOGVLQhKFuFHSjoH+CgkSELwM3CrqCgjDJGQoKbhT0pikIH0oE+CAMgOmpF3HAof580grxHaWRdt9opjr9wWUyj6UWHnvSD4yZ1N9pBiIXshuF3Cjktd9izmHo61CIxeSAPpWd/gRQSwECFAAUAAAACADFq5BcxazFs1IAAABeAAAADQAAAAAAAAAAAAAAAAAAAAAAbWFuaWZlc3QuanNvblBLAQIUABQAAAAIAMWrkFy0YIRaVwQAANUcAAARAAAAAAAAAAAAAAAAAH0AAABhL01haW4gU2NlbmUuanNvblBLBQYAAAAAAgACAHoAAAADBQAAAAA=";
|
|
5605
5577
|
var DEFAULT_SIZE = 36;
|
|
5606
5578
|
function useElapsedSeconds(isStreaming) {
|
|
5607
|
-
const [elapsed, setElapsed] =
|
|
5608
|
-
const startRef =
|
|
5609
|
-
|
|
5579
|
+
const [elapsed, setElapsed] = React.useState(0);
|
|
5580
|
+
const startRef = React.useRef(null);
|
|
5581
|
+
React.useEffect(() => {
|
|
5610
5582
|
if (!isStreaming) {
|
|
5611
5583
|
startRef.current = null;
|
|
5612
5584
|
setElapsed(0);
|
|
@@ -5665,22 +5637,22 @@ function StreamingIndicatorV2({
|
|
|
5665
5637
|
) });
|
|
5666
5638
|
}
|
|
5667
5639
|
function ImageLightboxV2({ src, alt, onClose }) {
|
|
5668
|
-
const [isMounted, setIsMounted] =
|
|
5669
|
-
const [isImageLoaded, setIsImageLoaded] =
|
|
5670
|
-
|
|
5640
|
+
const [isMounted, setIsMounted] = React.useState(false);
|
|
5641
|
+
const [isImageLoaded, setIsImageLoaded] = React.useState(false);
|
|
5642
|
+
React.useEffect(() => {
|
|
5671
5643
|
setIsMounted(true);
|
|
5672
5644
|
return () => setIsMounted(false);
|
|
5673
5645
|
}, []);
|
|
5674
|
-
|
|
5646
|
+
React.useEffect(() => {
|
|
5675
5647
|
setIsImageLoaded(false);
|
|
5676
5648
|
}, [src]);
|
|
5677
|
-
const handleKeyDown =
|
|
5649
|
+
const handleKeyDown = React.useCallback(
|
|
5678
5650
|
(e) => {
|
|
5679
5651
|
if (e.key === "Escape") onClose();
|
|
5680
5652
|
},
|
|
5681
5653
|
[onClose]
|
|
5682
5654
|
);
|
|
5683
|
-
|
|
5655
|
+
React.useEffect(() => {
|
|
5684
5656
|
if (!src || typeof document === "undefined") return;
|
|
5685
5657
|
document.addEventListener("keydown", handleKeyDown);
|
|
5686
5658
|
const previousOverflow = document.body.style.overflow;
|
|
@@ -5829,10 +5801,10 @@ function TraceTimelineModal({
|
|
|
5829
5801
|
apiBaseUrl,
|
|
5830
5802
|
apiHeaders
|
|
5831
5803
|
}) {
|
|
5832
|
-
const [trace, setTrace] =
|
|
5833
|
-
const [loading, setLoading] =
|
|
5834
|
-
const [error, setError] =
|
|
5835
|
-
|
|
5804
|
+
const [trace, setTrace] = React.useState(null);
|
|
5805
|
+
const [loading, setLoading] = React.useState(false);
|
|
5806
|
+
const [error, setError] = React.useState(null);
|
|
5807
|
+
React.useEffect(() => {
|
|
5836
5808
|
if (!open || !executionId) return;
|
|
5837
5809
|
const ctrl = new AbortController();
|
|
5838
5810
|
setLoading(true);
|
|
@@ -5854,7 +5826,7 @@ function TraceTimelineModal({
|
|
|
5854
5826
|
}).finally(() => setLoading(false));
|
|
5855
5827
|
return () => ctrl.abort();
|
|
5856
5828
|
}, [open, executionId, apiBaseUrl, apiHeaders]);
|
|
5857
|
-
const totalMs =
|
|
5829
|
+
const totalMs = React.useMemo(() => {
|
|
5858
5830
|
if (!trace) return 0;
|
|
5859
5831
|
const meta = trace.runMetadata?.totalTimeMs;
|
|
5860
5832
|
if (typeof meta === "number" && meta > 0) return meta;
|
|
@@ -5863,7 +5835,7 @@ function TraceTimelineModal({
|
|
|
5863
5835
|
if (starts.length === 0 || ends.length === 0) return 0;
|
|
5864
5836
|
return Math.max(...ends) - Math.min(...starts);
|
|
5865
5837
|
}, [trace]);
|
|
5866
|
-
const accountedMs =
|
|
5838
|
+
const accountedMs = React.useMemo(
|
|
5867
5839
|
() => (trace?.pipelineSteps ?? []).reduce(
|
|
5868
5840
|
(sum, s) => sum + (s.durationMs ?? 0),
|
|
5869
5841
|
0
|
|
@@ -6124,12 +6096,12 @@ var NOOP_ASYNC = async () => {
|
|
|
6124
6096
|
var NOOP = () => {
|
|
6125
6097
|
};
|
|
6126
6098
|
function useSentryChatCallbacks(callbacks, config) {
|
|
6127
|
-
const sentryCtxRef =
|
|
6128
|
-
const callbacksRef =
|
|
6099
|
+
const sentryCtxRef = React.useRef({});
|
|
6100
|
+
const callbacksRef = React.useRef(callbacks);
|
|
6129
6101
|
callbacksRef.current = callbacks;
|
|
6130
6102
|
const initialSessionId = config.initialSessionId;
|
|
6131
6103
|
const apiHeaders = config.api.headers;
|
|
6132
|
-
|
|
6104
|
+
React.useEffect(() => {
|
|
6133
6105
|
sentryCtxRef.current.agentId = config.agentId;
|
|
6134
6106
|
sentryCtxRef.current.sessionOwnerId = config.sessionParams?.id;
|
|
6135
6107
|
if (initialSessionId) {
|
|
@@ -6145,13 +6117,13 @@ function useSentryChatCallbacks(callbacks, config) {
|
|
|
6145
6117
|
initialSessionId,
|
|
6146
6118
|
apiHeaders
|
|
6147
6119
|
]);
|
|
6148
|
-
|
|
6120
|
+
React.useEffect(() => {
|
|
6149
6121
|
const endpoint = config.api.streamEndpoint || "/api/playground/ask/stream";
|
|
6150
6122
|
return subscribeToCfRay(endpoint, (cfRay) => {
|
|
6151
6123
|
sentryCtxRef.current.cfRay = cfRay;
|
|
6152
6124
|
});
|
|
6153
6125
|
}, [config.api.streamEndpoint]);
|
|
6154
|
-
return
|
|
6126
|
+
return React.useMemo(
|
|
6155
6127
|
() => ({
|
|
6156
6128
|
onMessageSent: (msg) => callbacksRef.current?.onMessageSent?.(msg),
|
|
6157
6129
|
onStreamStart: () => callbacksRef.current?.onStreamStart?.(),
|
|
@@ -6200,7 +6172,7 @@ function useSentryChatCallbacks(callbacks, config) {
|
|
|
6200
6172
|
[]
|
|
6201
6173
|
);
|
|
6202
6174
|
}
|
|
6203
|
-
var PaymanChatInner =
|
|
6175
|
+
var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
|
|
6204
6176
|
config,
|
|
6205
6177
|
callbacks = {},
|
|
6206
6178
|
className,
|
|
@@ -6211,18 +6183,18 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6211
6183
|
hasMoreMessages = false,
|
|
6212
6184
|
chat
|
|
6213
6185
|
}, ref) {
|
|
6214
|
-
const [inputValue, setInputValue] =
|
|
6215
|
-
const prevInputValueRef =
|
|
6216
|
-
const [hasEverSentMessage, setHasEverSentMessage] =
|
|
6217
|
-
const [lightboxSrc, setLightboxSrc] =
|
|
6218
|
-
const [lightboxAlt, setLightboxAlt] =
|
|
6219
|
-
const [editingMessageId, setEditingMessageId] =
|
|
6220
|
-
const [isResetSessionConfirmOpen, setIsResetSessionConfirmOpen] =
|
|
6221
|
-
const [analysisMode, setAnalysisMode] =
|
|
6222
|
-
const chatInputV2Ref =
|
|
6223
|
-
const messageListV2Ref =
|
|
6224
|
-
const resetToEmptyStateRef =
|
|
6225
|
-
|
|
6186
|
+
const [inputValue, setInputValue] = React.useState("");
|
|
6187
|
+
const prevInputValueRef = React.useRef(inputValue);
|
|
6188
|
+
const [hasEverSentMessage, setHasEverSentMessage] = React.useState(false);
|
|
6189
|
+
const [lightboxSrc, setLightboxSrc] = React.useState(null);
|
|
6190
|
+
const [lightboxAlt, setLightboxAlt] = React.useState("");
|
|
6191
|
+
const [editingMessageId, setEditingMessageId] = React.useState(null);
|
|
6192
|
+
const [isResetSessionConfirmOpen, setIsResetSessionConfirmOpen] = React.useState(false);
|
|
6193
|
+
const [analysisMode, setAnalysisMode] = React.useState("fast");
|
|
6194
|
+
const chatInputV2Ref = React.useRef(null);
|
|
6195
|
+
const messageListV2Ref = React.useRef(null);
|
|
6196
|
+
const resetToEmptyStateRef = React.useRef(false);
|
|
6197
|
+
React.useEffect(() => {
|
|
6226
6198
|
if (config.sentryDsn) {
|
|
6227
6199
|
initSentryIfNeeded(config.sentryDsn);
|
|
6228
6200
|
}
|
|
@@ -6238,7 +6210,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6238
6210
|
getSessionId,
|
|
6239
6211
|
getMessages
|
|
6240
6212
|
} = chat;
|
|
6241
|
-
|
|
6213
|
+
React.useEffect(() => {
|
|
6242
6214
|
if (resetToEmptyStateRef.current) {
|
|
6243
6215
|
if (messages.length === 0) {
|
|
6244
6216
|
setHasEverSentMessage(false);
|
|
@@ -6250,7 +6222,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6250
6222
|
setHasEverSentMessage(true);
|
|
6251
6223
|
}
|
|
6252
6224
|
}, [messages.length, hasEverSentMessage]);
|
|
6253
|
-
|
|
6225
|
+
React.useEffect(() => {
|
|
6254
6226
|
if (!editingMessageId) return;
|
|
6255
6227
|
const editingMessageStillExists = messages.some(
|
|
6256
6228
|
(message) => message.id === editingMessageId && message.role === "user"
|
|
@@ -6263,7 +6235,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6263
6235
|
const submitUserAction2 = chat.submitUserAction ?? NOOP_ASYNC;
|
|
6264
6236
|
const cancelUserAction2 = chat.cancelUserAction ?? NOOP_ASYNC;
|
|
6265
6237
|
const resendUserAction2 = chat.resendUserAction ?? NOOP_ASYNC;
|
|
6266
|
-
const
|
|
6238
|
+
const expireUserAction2 = chat.expireUserAction ?? NOOP_ASYNC;
|
|
6267
6239
|
const dismissNotification = chat.dismissNotification ?? NOOP;
|
|
6268
6240
|
const isUserActionSupported = typeof chat.submitUserAction === "function" && typeof chat.cancelUserAction === "function" && typeof chat.resendUserAction === "function";
|
|
6269
6241
|
const {
|
|
@@ -6289,7 +6261,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6289
6261
|
}
|
|
6290
6262
|
}
|
|
6291
6263
|
);
|
|
6292
|
-
const contextValue =
|
|
6264
|
+
const contextValue = React.useMemo(
|
|
6293
6265
|
() => ({
|
|
6294
6266
|
resetSession,
|
|
6295
6267
|
clearMessages,
|
|
@@ -6316,8 +6288,8 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6316
6288
|
onAttachFileClick,
|
|
6317
6289
|
onMessageFeedback
|
|
6318
6290
|
} = callbacks;
|
|
6319
|
-
const [debugTraceExecutionId, setDebugTraceExecutionId] =
|
|
6320
|
-
const handleSubmitFeedback =
|
|
6291
|
+
const [debugTraceExecutionId, setDebugTraceExecutionId] = React.useState(null);
|
|
6292
|
+
const handleSubmitFeedback = React.useCallback(
|
|
6321
6293
|
async ({ messageId, executionId, feedback, details }) => {
|
|
6322
6294
|
if (!executionId) {
|
|
6323
6295
|
throw new Error("Cannot submit feedback before the response completes");
|
|
@@ -6348,14 +6320,14 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6348
6320
|
onMessageFeedback
|
|
6349
6321
|
]
|
|
6350
6322
|
);
|
|
6351
|
-
const onExecutionTraceClick =
|
|
6323
|
+
const onExecutionTraceClick = React.useMemo(() => {
|
|
6352
6324
|
if (!config.debug) return rawOnExecutionTraceClick;
|
|
6353
6325
|
return (data) => {
|
|
6354
6326
|
rawOnExecutionTraceClick?.(data);
|
|
6355
6327
|
if (data.executionId) setDebugTraceExecutionId(data.executionId);
|
|
6356
6328
|
};
|
|
6357
6329
|
}, [config.debug, rawOnExecutionTraceClick]);
|
|
6358
|
-
const performResetSession =
|
|
6330
|
+
const performResetSession = React.useCallback(() => {
|
|
6359
6331
|
resetToEmptyStateRef.current = true;
|
|
6360
6332
|
setEditingMessageId(null);
|
|
6361
6333
|
setIsResetSessionConfirmOpen(false);
|
|
@@ -6376,13 +6348,13 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6376
6348
|
resetSession,
|
|
6377
6349
|
stopRecording
|
|
6378
6350
|
]);
|
|
6379
|
-
const requestResetSession =
|
|
6351
|
+
const requestResetSession = React.useCallback(() => {
|
|
6380
6352
|
setIsResetSessionConfirmOpen(true);
|
|
6381
6353
|
}, []);
|
|
6382
|
-
const closeResetSessionConfirm =
|
|
6354
|
+
const closeResetSessionConfirm = React.useCallback(() => {
|
|
6383
6355
|
setIsResetSessionConfirmOpen(false);
|
|
6384
6356
|
}, []);
|
|
6385
|
-
|
|
6357
|
+
React.useImperativeHandle(ref, () => ({
|
|
6386
6358
|
resetSession: performResetSession,
|
|
6387
6359
|
clearMessages,
|
|
6388
6360
|
cancelStream,
|
|
@@ -6421,7 +6393,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6421
6393
|
slashCommands: slashCommandsConfig,
|
|
6422
6394
|
commandPermissions
|
|
6423
6395
|
} = config;
|
|
6424
|
-
const messageActions =
|
|
6396
|
+
const messageActions = React.useMemo(
|
|
6425
6397
|
() => ({
|
|
6426
6398
|
userMessageActions: {
|
|
6427
6399
|
copy: messageActionsConfig?.userMessageActions?.copy ?? true,
|
|
@@ -6437,18 +6409,18 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6437
6409
|
}),
|
|
6438
6410
|
[messageActionsConfig]
|
|
6439
6411
|
);
|
|
6440
|
-
const slashCommands =
|
|
6412
|
+
const slashCommands = React.useMemo(
|
|
6441
6413
|
() => enableSlashCommands ? filterSlashCommands(
|
|
6442
6414
|
slashCommandsConfig ?? DEFAULT_SLASH_COMMANDS,
|
|
6443
6415
|
commandPermissions
|
|
6444
6416
|
) : [],
|
|
6445
6417
|
[commandPermissions, enableSlashCommands, slashCommandsConfig]
|
|
6446
6418
|
);
|
|
6447
|
-
const isSessionParamsConfigured =
|
|
6419
|
+
const isSessionParamsConfigured = React.useMemo(() => {
|
|
6448
6420
|
if (!sessionParams) return false;
|
|
6449
6421
|
return !!(sessionParams.id?.trim() && sessionParams.name?.trim());
|
|
6450
6422
|
}, [sessionParams?.id, sessionParams?.name]);
|
|
6451
|
-
|
|
6423
|
+
React.useEffect(() => {
|
|
6452
6424
|
const wasEmpty = prevInputValueRef.current.trim() === "";
|
|
6453
6425
|
const isEmpty2 = inputValue.trim() === "";
|
|
6454
6426
|
prevInputValueRef.current = inputValue;
|
|
@@ -6515,7 +6487,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6515
6487
|
void sendMessage(text.trim(), { analysisMode: effectiveAnalysisMode });
|
|
6516
6488
|
}
|
|
6517
6489
|
};
|
|
6518
|
-
const handleVoicePress =
|
|
6490
|
+
const handleVoicePress = React.useCallback(async () => {
|
|
6519
6491
|
if (!voiceAvailable) return;
|
|
6520
6492
|
if (isRecording) {
|
|
6521
6493
|
stopRecording();
|
|
@@ -6524,7 +6496,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6524
6496
|
clearTranscript();
|
|
6525
6497
|
await startRecording();
|
|
6526
6498
|
}, [clearTranscript, isRecording, startRecording, stopRecording, voiceAvailable]);
|
|
6527
|
-
const handleEditMessageDraft =
|
|
6499
|
+
const handleEditMessageDraft = React.useCallback((messageId) => {
|
|
6528
6500
|
const targetMessage = messages.find((message) => message.id === messageId);
|
|
6529
6501
|
if (!targetMessage?.content.trim()) return;
|
|
6530
6502
|
setEditingMessageId(messageId);
|
|
@@ -6533,7 +6505,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6533
6505
|
messageListV2Ref.current?.scrollToBottom("smooth");
|
|
6534
6506
|
});
|
|
6535
6507
|
}, [messages]);
|
|
6536
|
-
const handleRetryUserMessage =
|
|
6508
|
+
const handleRetryUserMessage = React.useCallback((messageId) => {
|
|
6537
6509
|
if (isWaitingForResponse) return;
|
|
6538
6510
|
const targetMessage = messages.find(
|
|
6539
6511
|
(message) => message.id === messageId && message.role === "user"
|
|
@@ -6550,7 +6522,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6550
6522
|
});
|
|
6551
6523
|
});
|
|
6552
6524
|
}, [isWaitingForResponse, messages, sendMessage, effectiveAnalysisMode]);
|
|
6553
|
-
const handleClearEditing =
|
|
6525
|
+
const handleClearEditing = React.useCallback(() => {
|
|
6554
6526
|
setEditingMessageId(null);
|
|
6555
6527
|
}, []);
|
|
6556
6528
|
return /* @__PURE__ */ jsxRuntime.jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -6664,7 +6636,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6664
6636
|
onSubmitUserAction: isUserActionSupported ? submitUserAction2 : void 0,
|
|
6665
6637
|
onCancelUserAction: isUserActionSupported ? cancelUserAction2 : void 0,
|
|
6666
6638
|
onResendUserAction: isUserActionSupported ? resendUserAction2 : void 0,
|
|
6667
|
-
onExpireUserAction: isUserActionSupported ?
|
|
6639
|
+
onExpireUserAction: isUserActionSupported ? expireUserAction2 : void 0,
|
|
6668
6640
|
onDismissNotification: dismissNotification,
|
|
6669
6641
|
onSubmitFeedback: handleSubmitFeedback
|
|
6670
6642
|
}
|
|
@@ -6740,7 +6712,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
6740
6712
|
}
|
|
6741
6713
|
) });
|
|
6742
6714
|
});
|
|
6743
|
-
var PaymanChat =
|
|
6715
|
+
var PaymanChat = React.forwardRef(
|
|
6744
6716
|
function PaymanChat2(props, ref) {
|
|
6745
6717
|
const mergedCallbacks = useSentryChatCallbacks(props.callbacks, props.config);
|
|
6746
6718
|
const chat = useChatV2(props.config, mergedCallbacks);
|