@paymanai/payman-ask-sdk 4.0.20 → 4.0.22
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.d.mts +26 -93
- package/dist/index.d.ts +26 -93
- package/dist/index.js +389 -1734
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +392 -1726
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +3703 -0
- package/dist/index.native.js.map +1 -0
- package/dist/styles.css +28 -486
- package/dist/styles.css.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -40,10 +40,7 @@ var remarkBreaks__default = /*#__PURE__*/_interopDefault(remarkBreaks);
|
|
|
40
40
|
|
|
41
41
|
var __defProp = Object.defineProperty;
|
|
42
42
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
43
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj,
|
|
44
|
-
var __defProp2 = Object.defineProperty;
|
|
45
|
-
var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
46
|
-
var __publicField2 = (obj, key, value) => __defNormalProp2(obj, key + "", value);
|
|
43
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, key + "", value);
|
|
47
44
|
function generateId() {
|
|
48
45
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
49
46
|
const r = Math.random() * 16 | 0;
|
|
@@ -739,8 +736,7 @@ function buildRequestBody(config, userMessage, sessionId, options) {
|
|
|
739
736
|
sessionAttributes,
|
|
740
737
|
analysisMode: options?.analysisMode,
|
|
741
738
|
locale: resolveLocale(config.locale),
|
|
742
|
-
timezone: resolveTimezone(config.timezone)
|
|
743
|
-
...options?.attachments?.length ? { attachments: options.attachments } : {}
|
|
739
|
+
timezone: resolveTimezone(config.timezone)
|
|
744
740
|
};
|
|
745
741
|
}
|
|
746
742
|
function resolveLocale(configured) {
|
|
@@ -785,7 +781,6 @@ function buildResolveImagesUrl(config) {
|
|
|
785
781
|
const basePath = normalizedEndpointPath.endsWith("/stream") ? normalizedEndpointPath.slice(0, -"/stream".length) : normalizedEndpointPath;
|
|
786
782
|
return `${config.api.baseUrl}${basePath}/resolve-image-urls`;
|
|
787
783
|
}
|
|
788
|
-
var NGROK_SKIP_BROWSER_WARNING = "ngrok-skip-browser-warning";
|
|
789
784
|
function buildRequestHeaders(config) {
|
|
790
785
|
const headers = {
|
|
791
786
|
...config.api.headers
|
|
@@ -793,9 +788,6 @@ function buildRequestHeaders(config) {
|
|
|
793
788
|
if (config.api.authToken) {
|
|
794
789
|
headers.Authorization = `Bearer ${config.api.authToken}`;
|
|
795
790
|
}
|
|
796
|
-
if (!headers[NGROK_SKIP_BROWSER_WARNING]) {
|
|
797
|
-
headers[NGROK_SKIP_BROWSER_WARNING] = "true";
|
|
798
|
-
}
|
|
799
791
|
return headers;
|
|
800
792
|
}
|
|
801
793
|
var RAG_IMAGE_REGEX = /\/api\/rag\/chunks\/[^"'\s]+\/image/;
|
|
@@ -1076,85 +1068,10 @@ function createCancelledMessageUpdate(steps, currentMessage) {
|
|
|
1076
1068
|
currentMessage: currentMessage || "Thinking..."
|
|
1077
1069
|
};
|
|
1078
1070
|
}
|
|
1079
|
-
var DEFAULT_SIGNED_URL_ENDPOINT = "/api/files/signed-url";
|
|
1080
|
-
function fileExtension(filename) {
|
|
1081
|
-
const ext = filename.split(".").pop()?.toLowerCase().replace(/^\./, "");
|
|
1082
|
-
return ext && ext.length > 0 ? ext : "bin";
|
|
1083
|
-
}
|
|
1084
|
-
function resolveMimeType(file) {
|
|
1085
|
-
if (file.type && file.type.trim().length > 0) return file.type;
|
|
1086
|
-
const ext = fileExtension(file.name);
|
|
1087
|
-
const byExt = {
|
|
1088
|
-
pdf: "application/pdf",
|
|
1089
|
-
png: "image/png",
|
|
1090
|
-
jpg: "image/jpeg",
|
|
1091
|
-
jpeg: "image/jpeg",
|
|
1092
|
-
gif: "image/gif",
|
|
1093
|
-
webp: "image/webp"
|
|
1094
|
-
};
|
|
1095
|
-
return byExt[ext] ?? "application/octet-stream";
|
|
1096
|
-
}
|
|
1097
|
-
function buildSignedUrlEndpoint(config, ext) {
|
|
1098
|
-
const endpoint = config.api.signedUrlEndpoint || DEFAULT_SIGNED_URL_ENDPOINT;
|
|
1099
|
-
const queryParams = new URLSearchParams({ extn: ext.replace(/^\./, "") });
|
|
1100
|
-
return `${config.api.baseUrl}${endpoint}?${queryParams.toString()}`;
|
|
1101
|
-
}
|
|
1102
|
-
async function requestSignedUrl(config, ext, signal) {
|
|
1103
|
-
const url = buildSignedUrlEndpoint(config, ext);
|
|
1104
|
-
const headers = buildRequestHeaders(config);
|
|
1105
|
-
const response = await fetch(url, {
|
|
1106
|
-
method: "GET",
|
|
1107
|
-
headers,
|
|
1108
|
-
signal
|
|
1109
|
-
});
|
|
1110
|
-
if (!response.ok) {
|
|
1111
|
-
const errorText = await response.text().catch(() => "");
|
|
1112
|
-
throw new Error(
|
|
1113
|
-
errorText ? `Failed to get upload URL (${response.status}): ${errorText}` : `Failed to get upload URL (${response.status})`
|
|
1114
|
-
);
|
|
1115
|
-
}
|
|
1116
|
-
const data = await response.json();
|
|
1117
|
-
if (!data.key || !data.url) {
|
|
1118
|
-
throw new Error("Signed URL response missing key or url");
|
|
1119
|
-
}
|
|
1120
|
-
return { key: data.key, url: data.url };
|
|
1121
|
-
}
|
|
1122
|
-
async function uploadToSignedUrl(signedUrl, file, mimeType, signal) {
|
|
1123
|
-
const response = await fetch(signedUrl, {
|
|
1124
|
-
method: "PUT",
|
|
1125
|
-
headers: {
|
|
1126
|
-
"Content-Type": mimeType,
|
|
1127
|
-
"x-ms-blob-type": "BlockBlob"
|
|
1128
|
-
},
|
|
1129
|
-
body: file,
|
|
1130
|
-
signal
|
|
1131
|
-
});
|
|
1132
|
-
if (!response.ok) {
|
|
1133
|
-
const errorText = await response.text().catch(() => "");
|
|
1134
|
-
throw new Error(
|
|
1135
|
-
errorText ? `Failed to upload file (${response.status}): ${errorText}` : `Failed to upload file (${response.status})`
|
|
1136
|
-
);
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
async function uploadAttachment(config, file, signal) {
|
|
1140
|
-
const ext = fileExtension(file.name);
|
|
1141
|
-
const mimeType = resolveMimeType(file);
|
|
1142
|
-
const { key, url } = await requestSignedUrl(config, ext, signal);
|
|
1143
|
-
await uploadToSignedUrl(url, file, mimeType, signal);
|
|
1144
|
-
return {
|
|
1145
|
-
tempKey: key,
|
|
1146
|
-
filename: file.name,
|
|
1147
|
-
mimeType
|
|
1148
|
-
};
|
|
1149
|
-
}
|
|
1150
|
-
async function uploadAttachments(config, files, signal) {
|
|
1151
|
-
const uploads = files.map((file) => uploadAttachment(config, file, signal));
|
|
1152
|
-
return Promise.all(uploads);
|
|
1153
|
-
}
|
|
1154
1071
|
var UserActionStaleError = class extends Error {
|
|
1155
1072
|
constructor(userActionId, message = "User action is no longer actionable") {
|
|
1156
1073
|
super(message);
|
|
1157
|
-
|
|
1074
|
+
__publicField(this, "userActionId");
|
|
1158
1075
|
this.name = "UserActionStaleError";
|
|
1159
1076
|
this.userActionId = userActionId;
|
|
1160
1077
|
}
|
|
@@ -1187,6 +1104,9 @@ async function cancelUserAction(config, userActionId) {
|
|
|
1187
1104
|
async function resendUserAction(config, userActionId) {
|
|
1188
1105
|
return sendUserActionRequest(config, userActionId, "resend");
|
|
1189
1106
|
}
|
|
1107
|
+
async function expireUserAction(config, userActionId) {
|
|
1108
|
+
return sendUserActionRequest(config, userActionId, "expired");
|
|
1109
|
+
}
|
|
1190
1110
|
var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
|
|
1191
1111
|
function upsertPrompt(prompts, req) {
|
|
1192
1112
|
const active = { ...req, status: "pending" };
|
|
@@ -1215,32 +1135,12 @@ function getStoredOrInitialMessages(config) {
|
|
|
1215
1135
|
function getSessionIdFromMessages(messages) {
|
|
1216
1136
|
return messages.find((message) => message.sessionId)?.sessionId;
|
|
1217
1137
|
}
|
|
1218
|
-
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "gif", "webp", "avif"]);
|
|
1219
|
-
function attachmentKindFromFile(file) {
|
|
1220
|
-
const ext = file.name.split(".").pop()?.toLowerCase() ?? "";
|
|
1221
|
-
if (IMAGE_EXTENSIONS.has(ext) || file.type.startsWith("image/")) return "image";
|
|
1222
|
-
return "file";
|
|
1223
|
-
}
|
|
1224
|
-
function buildMessageAttachments(files) {
|
|
1225
|
-
return files.map((file, index) => {
|
|
1226
|
-
const kind = attachmentKindFromFile(file);
|
|
1227
|
-
return {
|
|
1228
|
-
id: `att-${Date.now()}-${index}`,
|
|
1229
|
-
filename: file.name,
|
|
1230
|
-
mimeType: file.type || "application/octet-stream",
|
|
1231
|
-
// Blob URL for all local files so PDFs/docs stay previewable after send.
|
|
1232
|
-
previewUrl: URL.createObjectURL(file),
|
|
1233
|
-
kind
|
|
1234
|
-
};
|
|
1235
|
-
});
|
|
1236
|
-
}
|
|
1237
1138
|
function useChatV2(config, callbacks = {}) {
|
|
1238
1139
|
const [messages, setMessages] = react.useState(() => getStoredOrInitialMessages(config));
|
|
1239
1140
|
const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(() => {
|
|
1240
1141
|
if (!config.userId) return false;
|
|
1241
1142
|
return activeStreamStore.get(config.userId)?.isWaiting ?? false;
|
|
1242
1143
|
});
|
|
1243
|
-
const [isUploadingAttachments, setIsUploadingAttachments] = react.useState(false);
|
|
1244
1144
|
const sessionIdRef = react.useRef(
|
|
1245
1145
|
getSessionIdFromMessages(getStoredOrInitialMessages(config)) ?? config.initialSessionId ?? void 0
|
|
1246
1146
|
);
|
|
@@ -1315,45 +1215,21 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1315
1215
|
);
|
|
1316
1216
|
const sendMessage = react.useCallback(
|
|
1317
1217
|
async (userMessage, options) => {
|
|
1318
|
-
|
|
1319
|
-
const files = options?.files ?? [];
|
|
1320
|
-
const hasPreuploadedAttachments = (options?.attachments?.length ?? 0) > 0;
|
|
1321
|
-
if (!trimmedMessage && files.length === 0 && !hasPreuploadedAttachments) return;
|
|
1322
|
-
let streamAttachments = options?.attachments;
|
|
1323
|
-
if (!streamAttachments && files.length > 0) {
|
|
1324
|
-
setIsUploadingAttachments(true);
|
|
1325
|
-
try {
|
|
1326
|
-
streamAttachments = await uploadAttachments(configRef.current, files);
|
|
1327
|
-
} catch (error) {
|
|
1328
|
-
if (error.name !== "AbortError") {
|
|
1329
|
-
callbacksRef.current.onError?.(error);
|
|
1330
|
-
}
|
|
1331
|
-
throw error;
|
|
1332
|
-
} finally {
|
|
1333
|
-
setIsUploadingAttachments(false);
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1218
|
+
if (!userMessage.trim()) return;
|
|
1336
1219
|
if (!sessionIdRef.current && configRef.current.autoGenerateSessionId !== false) {
|
|
1337
1220
|
sessionIdRef.current = generateId();
|
|
1338
1221
|
callbacksRef.current.onSessionIdChange?.(sessionIdRef.current);
|
|
1339
1222
|
}
|
|
1340
|
-
const messageAttachments = files.length > 0 ? buildMessageAttachments(files) : streamAttachments?.length ? streamAttachments.map((attachment, index) => ({
|
|
1341
|
-
id: `att-${Date.now()}-${index}`,
|
|
1342
|
-
filename: attachment.filename,
|
|
1343
|
-
mimeType: attachment.mimeType,
|
|
1344
|
-
kind: attachment.mimeType.startsWith("image/") ? "image" : "file"
|
|
1345
|
-
})) : void 0;
|
|
1346
1223
|
const userMessageId = `user-${Date.now()}`;
|
|
1347
1224
|
const userMsg = {
|
|
1348
1225
|
id: userMessageId,
|
|
1349
1226
|
sessionId: sessionIdRef.current,
|
|
1350
1227
|
role: "user",
|
|
1351
|
-
content:
|
|
1352
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1353
|
-
attachments: messageAttachments
|
|
1228
|
+
content: userMessage,
|
|
1229
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1354
1230
|
};
|
|
1355
1231
|
setMessages((prev) => [...prev, userMsg]);
|
|
1356
|
-
callbacksRef.current.onMessageSent?.(
|
|
1232
|
+
callbacksRef.current.onMessageSent?.(userMessage);
|
|
1357
1233
|
setIsWaitingForResponse(true);
|
|
1358
1234
|
callbacksRef.current.onStreamStart?.();
|
|
1359
1235
|
const streamingId = `assistant-${Date.now()}`;
|
|
@@ -1380,14 +1256,11 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1380
1256
|
activeStreamStore.start(userId, abortController, initialMessages);
|
|
1381
1257
|
}
|
|
1382
1258
|
const newSessionId = await startStream(
|
|
1383
|
-
|
|
1259
|
+
userMessage,
|
|
1384
1260
|
streamingId,
|
|
1385
1261
|
sessionIdRef.current,
|
|
1386
1262
|
abortController,
|
|
1387
|
-
|
|
1388
|
-
analysisMode: options?.analysisMode,
|
|
1389
|
-
attachments: streamAttachments
|
|
1390
|
-
}
|
|
1263
|
+
options
|
|
1391
1264
|
);
|
|
1392
1265
|
const finalStreamUserId = streamUserIdRef.current ?? userId;
|
|
1393
1266
|
if (finalStreamUserId) {
|
|
@@ -1525,6 +1398,19 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1525
1398
|
},
|
|
1526
1399
|
[setPromptStatus]
|
|
1527
1400
|
);
|
|
1401
|
+
const expireUserAction2 = react.useCallback(
|
|
1402
|
+
async (userActionId) => {
|
|
1403
|
+
setPromptStatus(userActionId, "expired");
|
|
1404
|
+
try {
|
|
1405
|
+
await expireUserAction(configRef.current, userActionId);
|
|
1406
|
+
} catch (error) {
|
|
1407
|
+
if (error instanceof UserActionStaleError) return;
|
|
1408
|
+
callbacksRef.current.onError?.(error);
|
|
1409
|
+
throw error;
|
|
1410
|
+
}
|
|
1411
|
+
},
|
|
1412
|
+
[setPromptStatus]
|
|
1413
|
+
);
|
|
1528
1414
|
const dismissNotification = react.useCallback((id) => {
|
|
1529
1415
|
setUserActionState((prev) => ({
|
|
1530
1416
|
...prev,
|
|
@@ -1565,18 +1451,6 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1565
1451
|
setMessages(config.initialMessages);
|
|
1566
1452
|
sessionIdRef.current = getSessionIdFromMessages(config.initialMessages) ?? config.initialSessionId;
|
|
1567
1453
|
}, [config.initialMessages, config.initialSessionId, config.userId]);
|
|
1568
|
-
const hydratedSessionIdRef = react.useRef(void 0);
|
|
1569
|
-
react.useEffect(() => {
|
|
1570
|
-
if (config.userId) return;
|
|
1571
|
-
if (!config.initialMessages?.length) return;
|
|
1572
|
-
const sessionId = config.initialSessionId;
|
|
1573
|
-
if (hydratedSessionIdRef.current === sessionId && messagesRef.current.length > 0) {
|
|
1574
|
-
return;
|
|
1575
|
-
}
|
|
1576
|
-
hydratedSessionIdRef.current = sessionId;
|
|
1577
|
-
setMessages(config.initialMessages);
|
|
1578
|
-
sessionIdRef.current = getSessionIdFromMessages(config.initialMessages) ?? sessionId;
|
|
1579
|
-
}, [config.initialMessages, config.initialSessionId, config.userId]);
|
|
1580
1454
|
react.useEffect(() => {
|
|
1581
1455
|
const prevUserId = prevUserIdRef.current;
|
|
1582
1456
|
prevUserIdRef.current = config.userId;
|
|
@@ -1611,12 +1485,12 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1611
1485
|
getSessionId,
|
|
1612
1486
|
getMessages,
|
|
1613
1487
|
isWaitingForResponse,
|
|
1614
|
-
isUploadingAttachments,
|
|
1615
1488
|
sessionId: sessionIdRef.current,
|
|
1616
1489
|
userActionState,
|
|
1617
1490
|
submitUserAction: submitUserAction2,
|
|
1618
1491
|
cancelUserAction: cancelUserAction2,
|
|
1619
1492
|
resendUserAction: resendUserAction2,
|
|
1493
|
+
expireUserAction: expireUserAction2,
|
|
1620
1494
|
dismissNotification
|
|
1621
1495
|
};
|
|
1622
1496
|
}
|
|
@@ -1835,102 +1709,6 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1835
1709
|
reset
|
|
1836
1710
|
};
|
|
1837
1711
|
}
|
|
1838
|
-
function useAttachmentUpload(config) {
|
|
1839
|
-
const configRef = react.useRef(config);
|
|
1840
|
-
configRef.current = config;
|
|
1841
|
-
const [entries, setEntries] = react.useState(/* @__PURE__ */ new Map());
|
|
1842
|
-
const [orderedIds, setOrderedIds] = react.useState([]);
|
|
1843
|
-
const abortControllersRef = react.useRef(/* @__PURE__ */ new Map());
|
|
1844
|
-
const activeIdsRef = react.useRef(/* @__PURE__ */ new Set());
|
|
1845
|
-
const startUpload = react.useCallback((id, file) => {
|
|
1846
|
-
if (activeIdsRef.current.has(id)) return;
|
|
1847
|
-
activeIdsRef.current.add(id);
|
|
1848
|
-
const controller = new AbortController();
|
|
1849
|
-
abortControllersRef.current.set(id, controller);
|
|
1850
|
-
setEntries((prev) => {
|
|
1851
|
-
const next = new Map(prev);
|
|
1852
|
-
next.set(id, { id, status: "uploading" });
|
|
1853
|
-
return next;
|
|
1854
|
-
});
|
|
1855
|
-
void uploadAttachment(configRef.current, file, controller.signal).then((payload) => {
|
|
1856
|
-
if (controller.signal.aborted) return;
|
|
1857
|
-
setEntries((prev) => {
|
|
1858
|
-
const next = new Map(prev);
|
|
1859
|
-
next.set(id, { id, status: "done", payload });
|
|
1860
|
-
return next;
|
|
1861
|
-
});
|
|
1862
|
-
}).catch((error) => {
|
|
1863
|
-
if (error.name === "AbortError") return;
|
|
1864
|
-
setEntries((prev) => {
|
|
1865
|
-
const next = new Map(prev);
|
|
1866
|
-
next.set(id, {
|
|
1867
|
-
id,
|
|
1868
|
-
status: "error",
|
|
1869
|
-
error: error.message || "Upload failed"
|
|
1870
|
-
});
|
|
1871
|
-
return next;
|
|
1872
|
-
});
|
|
1873
|
-
}).finally(() => {
|
|
1874
|
-
abortControllersRef.current.delete(id);
|
|
1875
|
-
});
|
|
1876
|
-
}, []);
|
|
1877
|
-
const syncAttachments = react.useCallback(
|
|
1878
|
-
(attachments) => {
|
|
1879
|
-
const nextIds = attachments.map((attachment) => attachment.id);
|
|
1880
|
-
setOrderedIds(nextIds);
|
|
1881
|
-
const nextIdSet = new Set(nextIds);
|
|
1882
|
-
for (const id of activeIdsRef.current) {
|
|
1883
|
-
if (nextIdSet.has(id)) continue;
|
|
1884
|
-
abortControllersRef.current.get(id)?.abort();
|
|
1885
|
-
abortControllersRef.current.delete(id);
|
|
1886
|
-
activeIdsRef.current.delete(id);
|
|
1887
|
-
}
|
|
1888
|
-
setEntries((prev) => {
|
|
1889
|
-
const next = new Map(prev);
|
|
1890
|
-
for (const id of next.keys()) {
|
|
1891
|
-
if (!nextIdSet.has(id)) next.delete(id);
|
|
1892
|
-
}
|
|
1893
|
-
return next;
|
|
1894
|
-
});
|
|
1895
|
-
for (const attachment of attachments) {
|
|
1896
|
-
startUpload(attachment.id, attachment.file);
|
|
1897
|
-
}
|
|
1898
|
-
},
|
|
1899
|
-
[startUpload]
|
|
1900
|
-
);
|
|
1901
|
-
const clearAll = react.useCallback(() => {
|
|
1902
|
-
for (const controller of abortControllersRef.current.values()) {
|
|
1903
|
-
controller.abort();
|
|
1904
|
-
}
|
|
1905
|
-
abortControllersRef.current.clear();
|
|
1906
|
-
activeIdsRef.current.clear();
|
|
1907
|
-
setOrderedIds([]);
|
|
1908
|
-
setEntries(/* @__PURE__ */ new Map());
|
|
1909
|
-
}, []);
|
|
1910
|
-
const entryList = react.useMemo(
|
|
1911
|
-
() => orderedIds.map((id) => entries.get(id)).filter((entry) => entry != null),
|
|
1912
|
-
[entries, orderedIds]
|
|
1913
|
-
);
|
|
1914
|
-
const isUploading = entryList.some((entry) => entry.status === "uploading");
|
|
1915
|
-
const hasErrors = entryList.some((entry) => entry.status === "error");
|
|
1916
|
-
const allReady = orderedIds.length === 0 || orderedIds.every((id) => entries.get(id)?.status === "done");
|
|
1917
|
-
const payloads = entryList.filter((entry) => entry.status === "done" && entry.payload).map((entry) => entry.payload);
|
|
1918
|
-
const statusById = react.useMemo(
|
|
1919
|
-
() => Object.fromEntries(
|
|
1920
|
-
entryList.map((entry) => [entry.id, entry.status])
|
|
1921
|
-
),
|
|
1922
|
-
[entryList]
|
|
1923
|
-
);
|
|
1924
|
-
return {
|
|
1925
|
-
syncAttachments,
|
|
1926
|
-
clearAll,
|
|
1927
|
-
isUploading,
|
|
1928
|
-
hasErrors,
|
|
1929
|
-
allReady,
|
|
1930
|
-
payloads,
|
|
1931
|
-
statusById
|
|
1932
|
-
};
|
|
1933
|
-
}
|
|
1934
1712
|
function classifyField(field) {
|
|
1935
1713
|
if (!field) return "text";
|
|
1936
1714
|
if (Array.isArray(field.oneOf) && field.oneOf.length > 0) return "select";
|
|
@@ -2047,66 +1825,6 @@ function buildContent(schema, values) {
|
|
|
2047
1825
|
}
|
|
2048
1826
|
return content;
|
|
2049
1827
|
}
|
|
2050
|
-
var ATTACHMENTS_SUFFIX_RE = /\n\n\[Attachments:[^\]]*\]\s*$/;
|
|
2051
|
-
function stripAttachmentsSuffixFromIntent(intent) {
|
|
2052
|
-
return intent.replace(ATTACHMENTS_SUFFIX_RE, "").trimEnd();
|
|
2053
|
-
}
|
|
2054
|
-
function mapFeedback(feedback) {
|
|
2055
|
-
if (!feedback?.feedback) return null;
|
|
2056
|
-
return feedback.feedback === "POSITIVE" ? "up" : "down";
|
|
2057
|
-
}
|
|
2058
|
-
function mapHistoryAttachments(executionId, attachments) {
|
|
2059
|
-
const mapped = (attachments ?? []).map((attachment, index) => ({
|
|
2060
|
-
id: `${executionId}:att:${index}`,
|
|
2061
|
-
filename: attachment.filename,
|
|
2062
|
-
mimeType: attachment.mimeType,
|
|
2063
|
-
url: attachment.url ?? void 0,
|
|
2064
|
-
kind: attachment.mimeType.startsWith("image/") ? "image" : "file"
|
|
2065
|
-
}));
|
|
2066
|
-
return mapped.length > 0 ? mapped : void 0;
|
|
2067
|
-
}
|
|
2068
|
-
function mapExecutionHistoryToChatMessages(message) {
|
|
2069
|
-
const timestamp = message.startTime || message.endTime || (/* @__PURE__ */ new Date()).toISOString();
|
|
2070
|
-
const executionId = message.executionId ?? message.traceId ?? message.id;
|
|
2071
|
-
const attachments = mapHistoryAttachments(message.id, message.attachments);
|
|
2072
|
-
const rows = [
|
|
2073
|
-
{
|
|
2074
|
-
id: `${message.id}:user`,
|
|
2075
|
-
role: "user",
|
|
2076
|
-
content: stripAttachmentsSuffixFromIntent(message.sessionUserIntent),
|
|
2077
|
-
timestamp,
|
|
2078
|
-
attachments
|
|
2079
|
-
}
|
|
2080
|
-
];
|
|
2081
|
-
if (message.agentResponse) {
|
|
2082
|
-
rows.push({
|
|
2083
|
-
id: `${message.id}:assistant`,
|
|
2084
|
-
role: "assistant",
|
|
2085
|
-
content: message.agentResponse,
|
|
2086
|
-
timestamp: message.endTime || timestamp,
|
|
2087
|
-
isError: message.status === "FAILED",
|
|
2088
|
-
executionId,
|
|
2089
|
-
feedback: mapFeedback(message.feedback)
|
|
2090
|
-
});
|
|
2091
|
-
}
|
|
2092
|
-
return rows;
|
|
2093
|
-
}
|
|
2094
|
-
function mapExecutionHistoryPageToChatMessages(messages) {
|
|
2095
|
-
return messages.flatMap(mapExecutionHistoryToChatMessages);
|
|
2096
|
-
}
|
|
2097
|
-
function attachmentDisplayUrl(attachment) {
|
|
2098
|
-
return attachment.previewUrl ?? attachment.url;
|
|
2099
|
-
}
|
|
2100
|
-
function isImageAttachment(attachment) {
|
|
2101
|
-
const displayUrl = attachmentDisplayUrl(attachment);
|
|
2102
|
-
return attachment.kind === "image" || Boolean(displayUrl) && attachment.mimeType.startsWith("image/");
|
|
2103
|
-
}
|
|
2104
|
-
function isPdfAttachmentMeta(attachment) {
|
|
2105
|
-
return attachment.mimeType === "application/pdf" || /\.pdf$/i.test(attachment.filename);
|
|
2106
|
-
}
|
|
2107
|
-
function isPdfFile(file) {
|
|
2108
|
-
return file.type === "application/pdf" || /\.pdf$/i.test(file.name);
|
|
2109
|
-
}
|
|
2110
1828
|
var PaymanChatContext = react.createContext(void 0);
|
|
2111
1829
|
function usePaymanChat() {
|
|
2112
1830
|
const context = react.useContext(PaymanChatContext);
|
|
@@ -2217,111 +1935,6 @@ function subscribeToCfRay(urlPattern, listener) {
|
|
|
2217
1935
|
};
|
|
2218
1936
|
}
|
|
2219
1937
|
|
|
2220
|
-
// src/utils/attachmentConfig.ts
|
|
2221
|
-
var DEFAULT_IMAGE_EXTENSIONS = ["png", "jpg", "jpeg", "gif", "webp"];
|
|
2222
|
-
var DEFAULT_DOCUMENT_EXTENSIONS = ["pdf", "docx", "xlsx", "xls"];
|
|
2223
|
-
function resolveChatAttachmentConfig(config) {
|
|
2224
|
-
const nested = config.attachments;
|
|
2225
|
-
const enabled = nested?.enabled ?? config.showAttachmentButton ?? true;
|
|
2226
|
-
const uploadImage = nested?.uploadImage ?? config.showUploadImageButton ?? true;
|
|
2227
|
-
const attachFile = nested?.attachFile ?? config.showAttachFileButton ?? true;
|
|
2228
|
-
return {
|
|
2229
|
-
showAttachmentButton: enabled && (uploadImage || attachFile),
|
|
2230
|
-
showUploadImageButton: enabled && uploadImage,
|
|
2231
|
-
showAttachFileButton: enabled && attachFile,
|
|
2232
|
-
maxCount: nested?.maxCount ?? nested?.maxImages ?? nested?.maxDocuments,
|
|
2233
|
-
maxFileBytes: nested?.maxFileBytes,
|
|
2234
|
-
maxTotalBytes: nested?.maxTotalBytes,
|
|
2235
|
-
allowedImageExtensions: nested?.imageExtensions ?? DEFAULT_IMAGE_EXTENSIONS,
|
|
2236
|
-
allowedFileExtensions: nested?.documentExtensions ?? DEFAULT_DOCUMENT_EXTENSIONS
|
|
2237
|
-
};
|
|
2238
|
-
}
|
|
2239
|
-
|
|
2240
|
-
// src/utils/formatAttachmentBytes.ts
|
|
2241
|
-
function formatAttachmentBytes(bytes) {
|
|
2242
|
-
if (!Number.isFinite(bytes) || bytes <= 0) return "0 B";
|
|
2243
|
-
const units = ["B", "KB", "MB", "GB"];
|
|
2244
|
-
let value = bytes;
|
|
2245
|
-
let unitIndex = 0;
|
|
2246
|
-
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
2247
|
-
value /= 1024;
|
|
2248
|
-
unitIndex += 1;
|
|
2249
|
-
}
|
|
2250
|
-
const rounded = unitIndex === 0 ? String(Math.round(value)) : value >= 10 ? value.toFixed(0) : value.toFixed(1).replace(/\.0$/, "");
|
|
2251
|
-
return `${rounded} ${units[unitIndex]}`;
|
|
2252
|
-
}
|
|
2253
|
-
|
|
2254
|
-
// src/utils/pdfLink.ts
|
|
2255
|
-
function filenameFromContentDisposition(value) {
|
|
2256
|
-
if (!value) return void 0;
|
|
2257
|
-
let decoded = value;
|
|
2258
|
-
try {
|
|
2259
|
-
decoded = decodeURIComponent(value);
|
|
2260
|
-
} catch {
|
|
2261
|
-
decoded = value;
|
|
2262
|
-
}
|
|
2263
|
-
const quoted = decoded.match(/filename\*=(?:UTF-8''([^;]+)|"([^"]+)")/i);
|
|
2264
|
-
if (quoted?.[1] || quoted?.[2]) {
|
|
2265
|
-
return (quoted[1] ?? quoted[2])?.trim();
|
|
2266
|
-
}
|
|
2267
|
-
const unquoted = decoded.match(/filename=([^;]+)/i);
|
|
2268
|
-
return unquoted?.[1]?.replace(/"/g, "").trim();
|
|
2269
|
-
}
|
|
2270
|
-
function filenameFromUrlPath(href) {
|
|
2271
|
-
try {
|
|
2272
|
-
const parts = new URL(href).pathname.split("/").filter(Boolean);
|
|
2273
|
-
const last = parts[parts.length - 1];
|
|
2274
|
-
return last ? decodeURIComponent(last) : void 0;
|
|
2275
|
-
} catch {
|
|
2276
|
-
return void 0;
|
|
2277
|
-
}
|
|
2278
|
-
}
|
|
2279
|
-
function isPdfUrl(href) {
|
|
2280
|
-
if (!href) return false;
|
|
2281
|
-
const lower = href.toLowerCase();
|
|
2282
|
-
if (lower.includes(".pdf")) return true;
|
|
2283
|
-
try {
|
|
2284
|
-
const url = new URL(href);
|
|
2285
|
-
if (url.pathname.toLowerCase().endsWith(".pdf")) return true;
|
|
2286
|
-
const filename = url.searchParams.get("filename");
|
|
2287
|
-
if (filename?.toLowerCase().includes(".pdf")) return true;
|
|
2288
|
-
for (const key of ["rscd", "response-content-disposition"]) {
|
|
2289
|
-
const fromDisposition = filenameFromContentDisposition(
|
|
2290
|
-
url.searchParams.get(key)
|
|
2291
|
-
);
|
|
2292
|
-
if (fromDisposition?.toLowerCase().includes(".pdf")) return true;
|
|
2293
|
-
}
|
|
2294
|
-
} catch {
|
|
2295
|
-
return lower.endsWith(".pdf");
|
|
2296
|
-
}
|
|
2297
|
-
return false;
|
|
2298
|
-
}
|
|
2299
|
-
function getPdfTitleFromUrl(href, linkText) {
|
|
2300
|
-
const text = linkText?.trim();
|
|
2301
|
-
if (text) return text;
|
|
2302
|
-
try {
|
|
2303
|
-
const url = new URL(href);
|
|
2304
|
-
const filename = url.searchParams.get("filename");
|
|
2305
|
-
if (filename) {
|
|
2306
|
-
return filename.replace(/\.pdf$/i, "").replace(/[-_]+/g, " ").trim();
|
|
2307
|
-
}
|
|
2308
|
-
for (const key of ["rscd", "response-content-disposition"]) {
|
|
2309
|
-
const fromDisposition = filenameFromContentDisposition(
|
|
2310
|
-
url.searchParams.get(key)
|
|
2311
|
-
);
|
|
2312
|
-
if (fromDisposition) {
|
|
2313
|
-
return fromDisposition.replace(/\.pdf$/i, "").replace(/[-_]+/g, " ").trim();
|
|
2314
|
-
}
|
|
2315
|
-
}
|
|
2316
|
-
} catch {
|
|
2317
|
-
}
|
|
2318
|
-
const fromPath = filenameFromUrlPath(href);
|
|
2319
|
-
if (fromPath) {
|
|
2320
|
-
return fromPath.replace(/\.pdf$/i, "").replace(/[-_]+/g, " ").trim();
|
|
2321
|
-
}
|
|
2322
|
-
return "Document";
|
|
2323
|
-
}
|
|
2324
|
-
|
|
2325
1938
|
// src/utils/slashCommands.ts
|
|
2326
1939
|
var DEFAULT_SLASH_COMMANDS = [
|
|
2327
1940
|
{
|
|
@@ -3473,108 +3086,6 @@ function ActionTooltipV2({ label, children }) {
|
|
|
3473
3086
|
] }) })
|
|
3474
3087
|
] });
|
|
3475
3088
|
}
|
|
3476
|
-
function FilePreviewShell({
|
|
3477
|
-
filename,
|
|
3478
|
-
typeLabel,
|
|
3479
|
-
onClick,
|
|
3480
|
-
thumbnail,
|
|
3481
|
-
className,
|
|
3482
|
-
"aria-label": ariaLabel
|
|
3483
|
-
}) {
|
|
3484
|
-
const shellClass = cn(
|
|
3485
|
-
"payman-v2-file-preview-shell",
|
|
3486
|
-
"payman-v2-file-preview-shell-sent",
|
|
3487
|
-
onClick && "payman-v2-file-preview-shell-clickable",
|
|
3488
|
-
className
|
|
3489
|
-
);
|
|
3490
|
-
const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3491
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-file-preview-thumb", children: thumbnail ?? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3492
|
-
lucideReact.FileText,
|
|
3493
|
-
{
|
|
3494
|
-
size: 16,
|
|
3495
|
-
strokeWidth: 1.75,
|
|
3496
|
-
className: "payman-v2-file-preview-doc-icon"
|
|
3497
|
-
}
|
|
3498
|
-
) }),
|
|
3499
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-file-preview-info", children: [
|
|
3500
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-file-preview-name", children: filename }),
|
|
3501
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-file-preview-type", children: typeLabel })
|
|
3502
|
-
] })
|
|
3503
|
-
] });
|
|
3504
|
-
if (onClick) {
|
|
3505
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3506
|
-
"button",
|
|
3507
|
-
{
|
|
3508
|
-
type: "button",
|
|
3509
|
-
className: shellClass,
|
|
3510
|
-
onClick,
|
|
3511
|
-
"aria-label": ariaLabel ?? `Open ${filename}`,
|
|
3512
|
-
children: body
|
|
3513
|
-
}
|
|
3514
|
-
);
|
|
3515
|
-
}
|
|
3516
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: shellClass, children: body });
|
|
3517
|
-
}
|
|
3518
|
-
function FilePreviewBlockLayout({
|
|
3519
|
-
children,
|
|
3520
|
-
className,
|
|
3521
|
-
...rest
|
|
3522
|
-
}) {
|
|
3523
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("payman-v2-file-preview-item", className), ...rest, children });
|
|
3524
|
-
}
|
|
3525
|
-
function attachmentTypeLabel(attachment) {
|
|
3526
|
-
if (isImageAttachment(attachment)) {
|
|
3527
|
-
return "Image";
|
|
3528
|
-
}
|
|
3529
|
-
const ext = attachment.filename.split(".").pop()?.toUpperCase();
|
|
3530
|
-
return ext || "Document";
|
|
3531
|
-
}
|
|
3532
|
-
function isPdfAttachment(attachment) {
|
|
3533
|
-
const displayUrl = attachmentDisplayUrl(attachment);
|
|
3534
|
-
return isPdfAttachmentMeta(attachment) || Boolean(displayUrl) && isPdfUrl(displayUrl);
|
|
3535
|
-
}
|
|
3536
|
-
function AttachmentPreviewBlock({
|
|
3537
|
-
attachment,
|
|
3538
|
-
onImageClick
|
|
3539
|
-
}) {
|
|
3540
|
-
const chatContext = react.useContext(PaymanChatContext);
|
|
3541
|
-
const displayUrl = attachmentDisplayUrl(attachment);
|
|
3542
|
-
const typeLabel = attachmentTypeLabel(attachment);
|
|
3543
|
-
const isImage = isImageAttachment(attachment) && displayUrl;
|
|
3544
|
-
const openAttachment = () => {
|
|
3545
|
-
if (!displayUrl) return;
|
|
3546
|
-
if (isImageAttachment(attachment)) {
|
|
3547
|
-
onImageClick?.(displayUrl, attachment.filename);
|
|
3548
|
-
return;
|
|
3549
|
-
}
|
|
3550
|
-
if (isPdfAttachment(attachment)) {
|
|
3551
|
-
chatContext?.openPdfSheet(displayUrl, attachment.filename);
|
|
3552
|
-
return;
|
|
3553
|
-
}
|
|
3554
|
-
window.open(displayUrl, "_blank", "noopener,noreferrer");
|
|
3555
|
-
};
|
|
3556
|
-
if (isImage) {
|
|
3557
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FilePreviewBlockLayout, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3558
|
-
FilePreviewShell,
|
|
3559
|
-
{
|
|
3560
|
-
filename: attachment.filename,
|
|
3561
|
-
typeLabel,
|
|
3562
|
-
onClick: openAttachment,
|
|
3563
|
-
"aria-label": `Preview ${attachment.filename}`,
|
|
3564
|
-
thumbnail: /* @__PURE__ */ jsxRuntime.jsx("img", { src: displayUrl, alt: "", draggable: false })
|
|
3565
|
-
}
|
|
3566
|
-
) });
|
|
3567
|
-
}
|
|
3568
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FilePreviewBlockLayout, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3569
|
-
FilePreviewShell,
|
|
3570
|
-
{
|
|
3571
|
-
filename: attachment.filename,
|
|
3572
|
-
typeLabel,
|
|
3573
|
-
onClick: displayUrl ? openAttachment : void 0,
|
|
3574
|
-
"aria-label": `Open ${attachment.filename}`
|
|
3575
|
-
}
|
|
3576
|
-
) });
|
|
3577
|
-
}
|
|
3578
3089
|
function formatMessageTime(timestamp) {
|
|
3579
3090
|
const value = new Date(timestamp);
|
|
3580
3091
|
if (Number.isNaN(value.getTime())) return "";
|
|
@@ -3587,7 +3098,6 @@ function UserMessageV2({
|
|
|
3587
3098
|
message,
|
|
3588
3099
|
onEdit,
|
|
3589
3100
|
onRetry,
|
|
3590
|
-
onImageClick,
|
|
3591
3101
|
retryDisabled = false,
|
|
3592
3102
|
actions
|
|
3593
3103
|
}) {
|
|
@@ -3670,15 +3180,7 @@ function UserMessageV2({
|
|
|
3670
3180
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3671
3181
|
toastPortal,
|
|
3672
3182
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-user-msg payman-v2-fade-in", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-user-msg-group", children: [
|
|
3673
|
-
|
|
3674
|
-
AttachmentPreviewBlock,
|
|
3675
|
-
{
|
|
3676
|
-
attachment,
|
|
3677
|
-
onImageClick
|
|
3678
|
-
},
|
|
3679
|
-
attachment.id
|
|
3680
|
-
)) }),
|
|
3681
|
-
(message.content.trim().length > 0 || !message.attachments?.length) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-user-msg-bubble", children: parsedCommand ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-user-msg-command", children: [
|
|
3183
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-user-msg-bubble", children: parsedCommand ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-user-msg-command", children: [
|
|
3682
3184
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-user-msg-command-chip", children: parsedCommand.command }),
|
|
3683
3185
|
parsedCommand.body.trim() ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-user-msg-text", children: parsedCommand.body }) : null
|
|
3684
3186
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-user-msg-text", children: message.content }) }),
|
|
@@ -3903,44 +3405,9 @@ function MarkdownImageV2({
|
|
|
3903
3405
|
}
|
|
3904
3406
|
) });
|
|
3905
3407
|
}
|
|
3906
|
-
function
|
|
3907
|
-
const autoOpenedHrefRef = react.useRef(null);
|
|
3908
|
-
react.useEffect(() => {
|
|
3909
|
-
if (!autoOpen || autoOpenedHrefRef.current === href) return;
|
|
3910
|
-
autoOpenedHrefRef.current = href;
|
|
3911
|
-
onOpen(href, title, { auto: true });
|
|
3912
|
-
}, [href, autoOpen]);
|
|
3913
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FilePreviewBlockLayout, { "data-payman-file-block": true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3914
|
-
FilePreviewShell,
|
|
3915
|
-
{
|
|
3916
|
-
filename: title,
|
|
3917
|
-
typeLabel: "PDF",
|
|
3918
|
-
onClick: () => onOpen(href, title),
|
|
3919
|
-
"aria-label": `Open PDF: ${title}`
|
|
3920
|
-
}
|
|
3921
|
-
) });
|
|
3922
|
-
}
|
|
3923
|
-
function childrenToText(children) {
|
|
3924
|
-
if (typeof children === "string") return children;
|
|
3925
|
-
if (typeof children === "number") return String(children);
|
|
3926
|
-
if (Array.isArray(children)) return children.map(childrenToText).join("");
|
|
3927
|
-
if (children && typeof children === "object" && "props" in children) {
|
|
3928
|
-
return childrenToText(children.props.children);
|
|
3929
|
-
}
|
|
3930
|
-
return "";
|
|
3931
|
-
}
|
|
3932
|
-
function isFileBlockChild(child) {
|
|
3933
|
-
return react.isValidElement(child) && typeof child.props === "object" && child.props !== null && "data-payman-file-block" in child.props;
|
|
3934
|
-
}
|
|
3935
|
-
function buildComponents(onImageClick, isResolvingRef, onPdfClick, autoOpenPdf) {
|
|
3408
|
+
function buildComponents(onImageClick, isResolvingRef) {
|
|
3936
3409
|
return {
|
|
3937
|
-
p: ({ children }) => {
|
|
3938
|
-
const childArray = react.Children.toArray(children);
|
|
3939
|
-
if (childArray.length === 1 && isFileBlockChild(childArray[0])) {
|
|
3940
|
-
return childArray[0];
|
|
3941
|
-
}
|
|
3942
|
-
return /* @__PURE__ */ jsxRuntime.jsx("p", { children });
|
|
3943
|
-
},
|
|
3410
|
+
p: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("p", { children }),
|
|
3944
3411
|
code: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("code", { children }),
|
|
3945
3412
|
pre: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-markdown-pre", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { children }) }),
|
|
3946
3413
|
ul: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { children }),
|
|
@@ -3953,15 +3420,7 @@ function buildComponents(onImageClick, isResolvingRef, onPdfClick, autoOpenPdf)
|
|
|
3953
3420
|
em: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("em", { children }),
|
|
3954
3421
|
blockquote: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("blockquote", { children }),
|
|
3955
3422
|
hr: () => /* @__PURE__ */ jsxRuntime.jsx("hr", {}),
|
|
3956
|
-
a: ({ href, children }) => {
|
|
3957
|
-
const url = href ?? "";
|
|
3958
|
-
if (onPdfClick && isPdfUrl(url)) {
|
|
3959
|
-
const linkText = childrenToText(children).trim();
|
|
3960
|
-
const title = getPdfTitleFromUrl(url, linkText);
|
|
3961
|
-
return /* @__PURE__ */ jsxRuntime.jsx(PdfBlockV2, { href: url, title, onOpen: onPdfClick, autoOpen: autoOpenPdf });
|
|
3962
|
-
}
|
|
3963
|
-
return /* @__PURE__ */ jsxRuntime.jsx("a", { href, target: "_blank", rel: "noopener noreferrer", children });
|
|
3964
|
-
},
|
|
3423
|
+
a: ({ href, children }) => /* @__PURE__ */ jsxRuntime.jsx("a", { href, target: "_blank", rel: "noopener noreferrer", children }),
|
|
3965
3424
|
img: ({ src, alt }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3966
3425
|
MarkdownImageV2,
|
|
3967
3426
|
{
|
|
@@ -3982,15 +3441,13 @@ function MarkdownRendererV2({
|
|
|
3982
3441
|
content,
|
|
3983
3442
|
isStreaming,
|
|
3984
3443
|
isResolvingImages,
|
|
3985
|
-
onImageClick
|
|
3986
|
-
onPdfClick,
|
|
3987
|
-
autoOpenPdf
|
|
3444
|
+
onImageClick
|
|
3988
3445
|
}) {
|
|
3989
3446
|
const isResolvingRef = react.useRef(isResolvingImages);
|
|
3990
3447
|
isResolvingRef.current = isResolvingImages;
|
|
3991
3448
|
const components = react.useMemo(
|
|
3992
|
-
() => buildComponents(onImageClick, isResolvingRef
|
|
3993
|
-
[onImageClick
|
|
3449
|
+
() => buildComponents(onImageClick, isResolvingRef),
|
|
3450
|
+
[onImageClick]
|
|
3994
3451
|
);
|
|
3995
3452
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3996
3453
|
"div",
|
|
@@ -4359,17 +3816,6 @@ function stripIncompleteImageToken(text) {
|
|
|
4359
3816
|
if (/^!\[[^\]]*\]\([^)]*\)/.test(after)) return text;
|
|
4360
3817
|
return text.slice(0, lastBang);
|
|
4361
3818
|
}
|
|
4362
|
-
function stripIncompleteLinkToken(text) {
|
|
4363
|
-
const lastBracket = text.lastIndexOf("[");
|
|
4364
|
-
if (lastBracket === -1) return text;
|
|
4365
|
-
if (lastBracket > 0 && text[lastBracket - 1] === "!") return text;
|
|
4366
|
-
const after = text.slice(lastBracket);
|
|
4367
|
-
if (/^\[[^\]]*\]\([^)]*\)/.test(after)) return text;
|
|
4368
|
-
return text.slice(0, lastBracket);
|
|
4369
|
-
}
|
|
4370
|
-
function stripIncompleteMarkdownTokens(text) {
|
|
4371
|
-
return stripIncompleteLinkToken(stripIncompleteImageToken(text));
|
|
4372
|
-
}
|
|
4373
3819
|
function getFeedbackState(message) {
|
|
4374
3820
|
const feedback = message.feedback;
|
|
4375
3821
|
if (feedback === "up" || feedback === "down") return feedback;
|
|
@@ -4393,12 +3839,6 @@ function AssistantMessageV2({
|
|
|
4393
3839
|
() => getFeedbackState(message)
|
|
4394
3840
|
);
|
|
4395
3841
|
const [reasonModalOpen, setReasonModalOpen] = react.useState(false);
|
|
4396
|
-
const chatContext = react.useContext(PaymanChatContext);
|
|
4397
|
-
const chatContextRef = react.useRef(chatContext);
|
|
4398
|
-
chatContextRef.current = chatContext;
|
|
4399
|
-
const handlePdfClick = react.useCallback((href, title, options) => {
|
|
4400
|
-
chatContextRef.current?.openPdfSheet(href, title, options);
|
|
4401
|
-
}, []);
|
|
4402
3842
|
const canSubmitFeedback = !!onSubmitFeedback && !!message.executionId;
|
|
4403
3843
|
const [toast, setToast] = react.useState(null);
|
|
4404
3844
|
const copyResetTimerRef = react.useRef(null);
|
|
@@ -4423,7 +3863,7 @@ function AssistantMessageV2({
|
|
|
4423
3863
|
const raw = message.isStreaming ? message.streamingContent || message.content : message.content;
|
|
4424
3864
|
if (!raw) return "";
|
|
4425
3865
|
const normalized = raw.replace(/\\n/g, "\n");
|
|
4426
|
-
return message.isStreaming ?
|
|
3866
|
+
return message.isStreaming ? stripIncompleteImageToken(normalized) : normalized;
|
|
4427
3867
|
})();
|
|
4428
3868
|
const isThinkingStreaming = !!message.isStreaming && !rawResponseContent && !message.isError;
|
|
4429
3869
|
const responseTypingEnabled = hasEverStreamed.current && Boolean(rawResponseContent) && !message.isError;
|
|
@@ -4593,12 +4033,10 @@ function AssistantMessageV2({
|
|
|
4593
4033
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-assistant-msg-content-area", children: displayContent ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4594
4034
|
MarkdownRendererV2,
|
|
4595
4035
|
{
|
|
4596
|
-
content:
|
|
4036
|
+
content: displayContent,
|
|
4597
4037
|
isStreaming: message.isStreaming && !isCancelled || isResponseTyping,
|
|
4598
4038
|
isResolvingImages: message.isResolvingImages,
|
|
4599
|
-
onImageClick
|
|
4600
|
-
onPdfClick: handlePdfClick,
|
|
4601
|
-
autoOpenPdf: hasEverStreamed.current
|
|
4039
|
+
onImageClick
|
|
4602
4040
|
}
|
|
4603
4041
|
) : !isThinkingStreaming ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-assistant-msg-placeholder", children: "..." }) : null }),
|
|
4604
4042
|
isCancelled && message.isStreaming && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-assistant-msg-paused", children: [
|
|
@@ -4815,6 +4253,7 @@ function VerificationInline({
|
|
|
4815
4253
|
const [code, setCode] = react.useState("");
|
|
4816
4254
|
const [errored, setErrored] = react.useState(false);
|
|
4817
4255
|
const [resendSec, setResendSec] = react.useState(0);
|
|
4256
|
+
const [hiddenAfterResend, setHiddenAfterResend] = react.useState(false);
|
|
4818
4257
|
const lastSubmittedRef = react.useRef(null);
|
|
4819
4258
|
const resendTimerRef = react.useRef(void 0);
|
|
4820
4259
|
const status = prompt.status;
|
|
@@ -4828,6 +4267,9 @@ function VerificationInline({
|
|
|
4828
4267
|
lastSubmittedRef.current = null;
|
|
4829
4268
|
}
|
|
4830
4269
|
}, [prompt.subAction, prompt.userActionId]);
|
|
4270
|
+
react.useEffect(() => {
|
|
4271
|
+
setHiddenAfterResend(false);
|
|
4272
|
+
}, [prompt.expirySeconds, prompt.message, prompt.subAction, prompt.userActionId]);
|
|
4831
4273
|
react.useEffect(() => {
|
|
4832
4274
|
if (code.length < codeLen) lastSubmittedRef.current = null;
|
|
4833
4275
|
}, [code, codeLen]);
|
|
@@ -4878,11 +4320,13 @@ function VerificationInline({
|
|
|
4878
4320
|
if (locked || resendSec > 0) return;
|
|
4879
4321
|
setErrored(false);
|
|
4880
4322
|
setCode("");
|
|
4323
|
+
setHiddenAfterResend(true);
|
|
4881
4324
|
lastSubmittedRef.current = null;
|
|
4882
4325
|
try {
|
|
4883
4326
|
await onResend(prompt.userActionId);
|
|
4884
4327
|
startResendCooldown();
|
|
4885
4328
|
} catch {
|
|
4329
|
+
setHiddenAfterResend(false);
|
|
4886
4330
|
}
|
|
4887
4331
|
}, [locked, onResend, prompt.userActionId, resendSec, startResendCooldown]);
|
|
4888
4332
|
const handleCancel = react.useCallback(() => {
|
|
@@ -4890,6 +4334,7 @@ function VerificationInline({
|
|
|
4890
4334
|
void onCancel(prompt.userActionId);
|
|
4891
4335
|
}, [busy, onCancel, prompt.userActionId]);
|
|
4892
4336
|
const description = prompt.message?.trim() || (isNumeric ? `Enter the ${codeLen}-digit code to continue` : "Enter the verification code to continue");
|
|
4337
|
+
if (hiddenAfterResend) return null;
|
|
4893
4338
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-ua", role: "group", "aria-label": "Verification required", children: [
|
|
4894
4339
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-ua-head", children: [
|
|
4895
4340
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ShieldCheck, { className: "payman-v2-ua-icon", size: 15, strokeWidth: 1.75, "aria-hidden": true }),
|
|
@@ -4985,6 +4430,9 @@ function SchemaFormInline({
|
|
|
4985
4430
|
const busy = status === "submitting";
|
|
4986
4431
|
const stale = status === "stale";
|
|
4987
4432
|
const locked = busy || stale || expired;
|
|
4433
|
+
const isUserConfirmation = prompt.subAction === "UserConfirmation";
|
|
4434
|
+
const messageFormat = prompt.metadata?.["payman/messageFormat"];
|
|
4435
|
+
const renderMarkdown = messageFormat === "markdown";
|
|
4988
4436
|
const setValue = (key, value) => {
|
|
4989
4437
|
setValues((prev) => ({ ...prev, [key]: value }));
|
|
4990
4438
|
setErrors((prev) => {
|
|
@@ -5010,8 +4458,8 @@ function SchemaFormInline({
|
|
|
5010
4458
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-title", children: "Action required" }),
|
|
5011
4459
|
typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" : `${secondsLeft}s` })
|
|
5012
4460
|
] }),
|
|
5013
|
-
prompt.message?.trim() && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-desc", children: prompt.message }),
|
|
5014
|
-
stale ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-stale", children: "This request is no longer available." }) : fields.length === 0 ?
|
|
4461
|
+
prompt.message?.trim() && (renderMarkdown ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-markdown", children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownRendererV2, { content: prompt.message }) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-desc", children: prompt.message })),
|
|
4462
|
+
stale ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-stale", children: "This request is no longer available." }) : fields.length === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-form", children: fields.map(([key, field]) => {
|
|
5015
4463
|
const widget = classifyField(field);
|
|
5016
4464
|
const label = field.title || key;
|
|
5017
4465
|
const required = isRequired(schema, key);
|
|
@@ -5084,7 +4532,7 @@ function SchemaFormInline({
|
|
|
5084
4532
|
className: "payman-v2-ua-btn payman-v2-ua-btn-primary",
|
|
5085
4533
|
disabled: locked,
|
|
5086
4534
|
onClick: handleSubmit,
|
|
5087
|
-
children: busy ? "Submitting\u2026" : "Submit"
|
|
4535
|
+
children: busy ? "Submitting\u2026" : isUserConfirmation ? "Confirm" : "Submit"
|
|
5088
4536
|
}
|
|
5089
4537
|
),
|
|
5090
4538
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -5124,26 +4572,51 @@ function useExpiryCountdown(prompt) {
|
|
|
5124
4572
|
setSecondsLeft(void 0);
|
|
5125
4573
|
return;
|
|
5126
4574
|
}
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
}
|
|
5137
|
-
}
|
|
5138
|
-
|
|
4575
|
+
const deadlineMs = Date.now() + initial * 1e3;
|
|
4576
|
+
let intervalId;
|
|
4577
|
+
const remaining = () => Math.max(0, Math.ceil((deadlineMs - Date.now()) / 1e3));
|
|
4578
|
+
const sync = () => {
|
|
4579
|
+
const next = remaining();
|
|
4580
|
+
setSecondsLeft(next);
|
|
4581
|
+
if (next === 0 && intervalId !== void 0) {
|
|
4582
|
+
window.clearInterval(intervalId);
|
|
4583
|
+
intervalId = void 0;
|
|
4584
|
+
}
|
|
4585
|
+
};
|
|
4586
|
+
sync();
|
|
4587
|
+
intervalId = window.setInterval(sync, 1e3);
|
|
4588
|
+
document.addEventListener("visibilitychange", sync);
|
|
4589
|
+
window.addEventListener("focus", sync);
|
|
4590
|
+
window.addEventListener("pageshow", sync);
|
|
4591
|
+
return () => {
|
|
4592
|
+
if (intervalId !== void 0) window.clearInterval(intervalId);
|
|
4593
|
+
document.removeEventListener("visibilitychange", sync);
|
|
4594
|
+
window.removeEventListener("focus", sync);
|
|
4595
|
+
window.removeEventListener("pageshow", sync);
|
|
4596
|
+
};
|
|
5139
4597
|
}, [prompt.userActionId, prompt.subAction, initial]);
|
|
5140
4598
|
const expired = initial !== void 0 && secondsLeft === 0;
|
|
5141
4599
|
return [secondsLeft, expired];
|
|
5142
4600
|
}
|
|
5143
|
-
function UserActionInline({
|
|
4601
|
+
function UserActionInline({
|
|
4602
|
+
prompt,
|
|
4603
|
+
onSubmit,
|
|
4604
|
+
onCancel,
|
|
4605
|
+
onResend,
|
|
4606
|
+
onExpired
|
|
4607
|
+
}) {
|
|
5144
4608
|
const [secondsLeft, expired] = useExpiryCountdown(prompt);
|
|
4609
|
+
react.useEffect(() => {
|
|
4610
|
+
if (expired && prompt.kind !== "notification") onExpired?.();
|
|
4611
|
+
}, [expired, onExpired, prompt.kind]);
|
|
5145
4612
|
let body;
|
|
5146
|
-
if (prompt.kind
|
|
4613
|
+
if (expired && prompt.kind !== "notification") {
|
|
4614
|
+
const note = {
|
|
4615
|
+
id: `${prompt.userActionId}-expired`,
|
|
4616
|
+
message: prompt.kind === "verification" ? "Verification Request Expired" : "User Form Expired"
|
|
4617
|
+
};
|
|
4618
|
+
body = /* @__PURE__ */ jsxRuntime.jsx(NotificationInline, { notification: note });
|
|
4619
|
+
} else if (prompt.kind === "verification") {
|
|
5147
4620
|
body = /* @__PURE__ */ jsxRuntime.jsx(
|
|
5148
4621
|
VerificationInline,
|
|
5149
4622
|
{
|
|
@@ -5183,10 +4656,23 @@ function UserActionInline({ prompt, onSubmit, onCancel, onResend }) {
|
|
|
5183
4656
|
}
|
|
5184
4657
|
var SCROLL_THRESHOLD2 = 100;
|
|
5185
4658
|
var USER_SCROLL_UP_EPSILON = 4;
|
|
4659
|
+
var PROMPT_KEY_SEPARATOR = "";
|
|
4660
|
+
function getPromptSlotKey(prompt) {
|
|
4661
|
+
return prompt.toolCallId || prompt.userActionId;
|
|
4662
|
+
}
|
|
4663
|
+
function getPromptViewKey(prompt) {
|
|
4664
|
+
return [
|
|
4665
|
+
getPromptSlotKey(prompt),
|
|
4666
|
+
prompt.userActionId,
|
|
4667
|
+
prompt.subAction ?? "",
|
|
4668
|
+
prompt.expirySeconds ?? "",
|
|
4669
|
+
prompt.message ?? ""
|
|
4670
|
+
].join(PROMPT_KEY_SEPARATOR);
|
|
4671
|
+
}
|
|
5186
4672
|
var MessageListV2 = react.forwardRef(
|
|
5187
4673
|
function MessageListV22({
|
|
5188
4674
|
messages,
|
|
5189
|
-
isStreaming
|
|
4675
|
+
isStreaming = false,
|
|
5190
4676
|
onEditUserMessage,
|
|
5191
4677
|
onRetryUserMessage,
|
|
5192
4678
|
onImageClick,
|
|
@@ -5198,10 +4684,10 @@ var MessageListV2 = react.forwardRef(
|
|
|
5198
4684
|
onSubmitUserAction,
|
|
5199
4685
|
onCancelUserAction,
|
|
5200
4686
|
onResendUserAction,
|
|
4687
|
+
onExpireUserAction,
|
|
5201
4688
|
onDismissNotification,
|
|
5202
4689
|
onSubmitFeedback,
|
|
5203
|
-
typingSpeed = 4
|
|
5204
|
-
sidePanelOpen = false
|
|
4690
|
+
typingSpeed = 4
|
|
5205
4691
|
}, ref) {
|
|
5206
4692
|
const noop = react.useCallback(async () => {
|
|
5207
4693
|
}, []);
|
|
@@ -5209,11 +4695,11 @@ var MessageListV2 = react.forwardRef(
|
|
|
5209
4695
|
const scrollInnerRef = react.useRef(null);
|
|
5210
4696
|
const isNearBottomRef = react.useRef(true);
|
|
5211
4697
|
const [showScrollBtn, setShowScrollBtn] = react.useState(false);
|
|
4698
|
+
const [expiredPromptViewState, setExpiredPromptViewState] = react.useState({});
|
|
4699
|
+
const expiredUserActionIdsRef = react.useRef(/* @__PURE__ */ new Set());
|
|
5212
4700
|
const prevCountRef = react.useRef(messages.length);
|
|
5213
4701
|
const pauseStickUntilUserMessageRef = react.useRef(false);
|
|
5214
4702
|
const followingBottomRef = react.useRef(true);
|
|
5215
|
-
const sidePanelOpenRef = react.useRef(sidePanelOpen);
|
|
5216
|
-
sidePanelOpenRef.current = sidePanelOpen;
|
|
5217
4703
|
const lastPinAtRef = react.useRef(0);
|
|
5218
4704
|
const prevScrollTopRef = react.useRef(0);
|
|
5219
4705
|
const getDistanceFromBottom = react.useCallback(() => {
|
|
@@ -5221,6 +4707,92 @@ var MessageListV2 = react.forwardRef(
|
|
|
5221
4707
|
if (!el) return 0;
|
|
5222
4708
|
return el.scrollHeight - el.scrollTop - el.clientHeight;
|
|
5223
4709
|
}, []);
|
|
4710
|
+
const messageActivityFingerprint = react.useMemo(() => {
|
|
4711
|
+
const last = messages[messages.length - 1];
|
|
4712
|
+
const promptFingerprint = (userActionPrompts ?? []).map((prompt) => `${getPromptViewKey(prompt)}:${prompt.status}`).join(PROMPT_KEY_SEPARATOR);
|
|
4713
|
+
const notificationFingerprint = (notifications ?? []).map((notification) => notification.id).join(PROMPT_KEY_SEPARATOR);
|
|
4714
|
+
if (!last) {
|
|
4715
|
+
return [
|
|
4716
|
+
0,
|
|
4717
|
+
isStreaming ? "streaming" : "idle",
|
|
4718
|
+
promptFingerprint,
|
|
4719
|
+
notificationFingerprint
|
|
4720
|
+
].join(PROMPT_KEY_SEPARATOR);
|
|
4721
|
+
}
|
|
4722
|
+
return [
|
|
4723
|
+
messages.length,
|
|
4724
|
+
isStreaming ? "streaming" : "idle",
|
|
4725
|
+
last.id,
|
|
4726
|
+
last.role,
|
|
4727
|
+
last.content ?? "",
|
|
4728
|
+
last.isStreaming ? "streaming" : "done",
|
|
4729
|
+
last.streamProgress ?? "",
|
|
4730
|
+
last.steps?.length ?? 0,
|
|
4731
|
+
last.errorDetails ?? "",
|
|
4732
|
+
promptFingerprint,
|
|
4733
|
+
notificationFingerprint
|
|
4734
|
+
].join(PROMPT_KEY_SEPARATOR);
|
|
4735
|
+
}, [isStreaming, messages, notifications, userActionPrompts]);
|
|
4736
|
+
const handleUserActionExpired = react.useCallback(
|
|
4737
|
+
(promptKey, userActionId) => {
|
|
4738
|
+
setExpiredPromptViewState((prev) => {
|
|
4739
|
+
if (prev[promptKey]) return prev;
|
|
4740
|
+
return {
|
|
4741
|
+
...prev,
|
|
4742
|
+
[promptKey]: { baseline: messageActivityFingerprint, hidden: false }
|
|
4743
|
+
};
|
|
4744
|
+
});
|
|
4745
|
+
if (!expiredUserActionIdsRef.current.has(userActionId)) {
|
|
4746
|
+
expiredUserActionIdsRef.current.add(userActionId);
|
|
4747
|
+
void onExpireUserAction?.(userActionId)?.catch(() => {
|
|
4748
|
+
});
|
|
4749
|
+
}
|
|
4750
|
+
},
|
|
4751
|
+
[messageActivityFingerprint, onExpireUserAction]
|
|
4752
|
+
);
|
|
4753
|
+
react.useEffect(() => {
|
|
4754
|
+
setExpiredPromptViewState((prev) => {
|
|
4755
|
+
let changed = false;
|
|
4756
|
+
const next = {};
|
|
4757
|
+
for (const [key, state] of Object.entries(prev)) {
|
|
4758
|
+
if (!state.hidden && state.baseline !== messageActivityFingerprint) {
|
|
4759
|
+
next[key] = { ...state, hidden: true };
|
|
4760
|
+
changed = true;
|
|
4761
|
+
} else {
|
|
4762
|
+
next[key] = state;
|
|
4763
|
+
}
|
|
4764
|
+
}
|
|
4765
|
+
return changed ? next : prev;
|
|
4766
|
+
});
|
|
4767
|
+
}, [messageActivityFingerprint]);
|
|
4768
|
+
react.useEffect(() => {
|
|
4769
|
+
const livePromptKeys = new Set((userActionPrompts ?? []).map(getPromptViewKey));
|
|
4770
|
+
const liveUserActionIds = new Set((userActionPrompts ?? []).map((p) => p.userActionId));
|
|
4771
|
+
for (const userActionId of expiredUserActionIdsRef.current) {
|
|
4772
|
+
if (!liveUserActionIds.has(userActionId)) {
|
|
4773
|
+
expiredUserActionIdsRef.current.delete(userActionId);
|
|
4774
|
+
}
|
|
4775
|
+
}
|
|
4776
|
+
setExpiredPromptViewState((prev) => {
|
|
4777
|
+
let changed = false;
|
|
4778
|
+
const next = {};
|
|
4779
|
+
for (const [key, state] of Object.entries(prev)) {
|
|
4780
|
+
if (livePromptKeys.has(key)) {
|
|
4781
|
+
next[key] = state;
|
|
4782
|
+
} else {
|
|
4783
|
+
changed = true;
|
|
4784
|
+
}
|
|
4785
|
+
}
|
|
4786
|
+
return changed ? next : prev;
|
|
4787
|
+
});
|
|
4788
|
+
}, [userActionPrompts]);
|
|
4789
|
+
const visibleUserActionPrompts = react.useMemo(
|
|
4790
|
+
() => userActionPrompts?.filter((prompt) => {
|
|
4791
|
+
const promptKey = getPromptViewKey(prompt);
|
|
4792
|
+
return !expiredPromptViewState[promptKey]?.hidden;
|
|
4793
|
+
}),
|
|
4794
|
+
[expiredPromptViewState, userActionPrompts]
|
|
4795
|
+
);
|
|
5224
4796
|
const pinToBottom = react.useCallback((behavior = "instant") => {
|
|
5225
4797
|
const el = scrollRef.current;
|
|
5226
4798
|
if (!el) return;
|
|
@@ -5261,25 +4833,17 @@ var MessageListV2 = react.forwardRef(
|
|
|
5261
4833
|
const nearBottom = distance <= SCROLL_THRESHOLD2;
|
|
5262
4834
|
isNearBottomRef.current = nearBottom;
|
|
5263
4835
|
setShowScrollBtn(!nearBottom);
|
|
4836
|
+
const sincePin = performance.now() - lastPinAtRef.current;
|
|
4837
|
+
if (sincePin < 250) return;
|
|
5264
4838
|
const scrolledUp = currentScrollTop < prevScrollTop - USER_SCROLL_UP_EPSILON;
|
|
5265
4839
|
if (scrolledUp) {
|
|
5266
4840
|
followingBottomRef.current = false;
|
|
5267
4841
|
pauseStickUntilUserMessageRef.current = true;
|
|
5268
|
-
|
|
5269
|
-
}
|
|
5270
|
-
const sincePin = performance.now() - lastPinAtRef.current;
|
|
5271
|
-
if (sincePin < 250) return;
|
|
5272
|
-
if (nearBottom) {
|
|
4842
|
+
} else if (nearBottom) {
|
|
5273
4843
|
followingBottomRef.current = true;
|
|
5274
4844
|
pauseStickUntilUserMessageRef.current = false;
|
|
5275
4845
|
}
|
|
5276
4846
|
}, [getDistanceFromBottom]);
|
|
5277
|
-
const handleWheel = react.useCallback((e) => {
|
|
5278
|
-
if (e.deltaY < 0) {
|
|
5279
|
-
followingBottomRef.current = false;
|
|
5280
|
-
pauseStickUntilUserMessageRef.current = true;
|
|
5281
|
-
}
|
|
5282
|
-
}, []);
|
|
5283
4847
|
react.useEffect(() => {
|
|
5284
4848
|
const prevCount = prevCountRef.current;
|
|
5285
4849
|
prevCountRef.current = messages.length;
|
|
@@ -5289,7 +4853,7 @@ var MessageListV2 = react.forwardRef(
|
|
|
5289
4853
|
pauseStickUntilUserMessageRef.current = false;
|
|
5290
4854
|
followingBottomRef.current = true;
|
|
5291
4855
|
requestAnimationFrame(() => scrollToBottom());
|
|
5292
|
-
} else if (!
|
|
4856
|
+
} else if (!pauseStickUntilUserMessageRef.current && followingBottomRef.current) {
|
|
5293
4857
|
requestAnimationFrame(() => scrollToBottom("instant"));
|
|
5294
4858
|
}
|
|
5295
4859
|
}
|
|
@@ -5298,16 +4862,27 @@ var MessageListV2 = react.forwardRef(
|
|
|
5298
4862
|
const inner = scrollInnerRef.current;
|
|
5299
4863
|
if (!inner) return;
|
|
5300
4864
|
const pinIfFollowing = () => {
|
|
5301
|
-
if (sidePanelOpenRef.current) return;
|
|
5302
4865
|
if (pauseStickUntilUserMessageRef.current) return;
|
|
5303
4866
|
if (!followingBottomRef.current) return;
|
|
5304
|
-
if (getDistanceFromBottom() > SCROLL_THRESHOLD2) return;
|
|
5305
4867
|
pinToBottom("instant");
|
|
5306
4868
|
};
|
|
5307
|
-
const ro = new ResizeObserver(
|
|
4869
|
+
const ro = new ResizeObserver(() => {
|
|
4870
|
+
pinIfFollowing();
|
|
4871
|
+
});
|
|
5308
4872
|
ro.observe(inner);
|
|
5309
|
-
|
|
5310
|
-
|
|
4873
|
+
const mo = new MutationObserver(() => {
|
|
4874
|
+
pinIfFollowing();
|
|
4875
|
+
});
|
|
4876
|
+
mo.observe(inner, {
|
|
4877
|
+
childList: true,
|
|
4878
|
+
subtree: true,
|
|
4879
|
+
characterData: true
|
|
4880
|
+
});
|
|
4881
|
+
return () => {
|
|
4882
|
+
ro.disconnect();
|
|
4883
|
+
mo.disconnect();
|
|
4884
|
+
};
|
|
4885
|
+
}, [pinToBottom]);
|
|
5311
4886
|
react.useEffect(() => {
|
|
5312
4887
|
if (messages.length > 0) {
|
|
5313
4888
|
setTimeout(() => scrollToBottom("instant"), 50);
|
|
@@ -5319,7 +4894,6 @@ var MessageListV2 = react.forwardRef(
|
|
|
5319
4894
|
{
|
|
5320
4895
|
ref: scrollRef,
|
|
5321
4896
|
onScroll: handleScroll,
|
|
5322
|
-
onWheel: handleWheel,
|
|
5323
4897
|
className: "payman-v2-message-scroll payman-v2-scrollbar",
|
|
5324
4898
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5325
4899
|
"div",
|
|
@@ -5333,7 +4907,6 @@ var MessageListV2 = react.forwardRef(
|
|
|
5333
4907
|
message,
|
|
5334
4908
|
onEdit: onEditUserMessage,
|
|
5335
4909
|
onRetry: onRetryUserMessage,
|
|
5336
|
-
onImageClick,
|
|
5337
4910
|
retryDisabled,
|
|
5338
4911
|
actions: messageActions?.userMessageActions
|
|
5339
4912
|
}
|
|
@@ -5356,16 +4929,20 @@ var MessageListV2 = react.forwardRef(
|
|
|
5356
4929
|
},
|
|
5357
4930
|
note.id
|
|
5358
4931
|
)),
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
4932
|
+
visibleUserActionPrompts?.map((prompt) => {
|
|
4933
|
+
const promptKey = getPromptViewKey(prompt);
|
|
4934
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4935
|
+
UserActionInline,
|
|
4936
|
+
{
|
|
4937
|
+
prompt,
|
|
4938
|
+
onSubmit: onSubmitUserAction ?? noop,
|
|
4939
|
+
onCancel: onCancelUserAction ?? noop,
|
|
4940
|
+
onResend: onResendUserAction ?? noop,
|
|
4941
|
+
onExpired: () => handleUserActionExpired(promptKey, prompt.userActionId)
|
|
4942
|
+
},
|
|
4943
|
+
promptKey
|
|
4944
|
+
);
|
|
4945
|
+
})
|
|
5369
4946
|
]
|
|
5370
4947
|
}
|
|
5371
4948
|
)
|
|
@@ -5395,121 +4972,11 @@ var MessageListV2 = react.forwardRef(
|
|
|
5395
4972
|
] });
|
|
5396
4973
|
}
|
|
5397
4974
|
);
|
|
5398
|
-
function FilePreviewModal({ src, name, onClose }) {
|
|
5399
|
-
const [isMounted, setIsMounted] = react.useState(false);
|
|
5400
|
-
const [isLoaded, setIsLoaded] = react.useState(false);
|
|
5401
|
-
react.useEffect(() => {
|
|
5402
|
-
setIsMounted(true);
|
|
5403
|
-
return () => setIsMounted(false);
|
|
5404
|
-
}, []);
|
|
5405
|
-
react.useEffect(() => {
|
|
5406
|
-
setIsLoaded(false);
|
|
5407
|
-
}, [src]);
|
|
5408
|
-
const handleKeyDown = react.useCallback(
|
|
5409
|
-
(e) => {
|
|
5410
|
-
if (e.key === "Escape") onClose();
|
|
5411
|
-
},
|
|
5412
|
-
[onClose]
|
|
5413
|
-
);
|
|
5414
|
-
react.useEffect(() => {
|
|
5415
|
-
if (!src || typeof document === "undefined") return;
|
|
5416
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
5417
|
-
const prev = document.body.style.overflow;
|
|
5418
|
-
document.body.style.overflow = "hidden";
|
|
5419
|
-
return () => {
|
|
5420
|
-
document.removeEventListener("keydown", handleKeyDown);
|
|
5421
|
-
document.body.style.overflow = prev;
|
|
5422
|
-
};
|
|
5423
|
-
}, [src, handleKeyDown]);
|
|
5424
|
-
if (!isMounted || typeof document === "undefined") return null;
|
|
5425
|
-
return reactDom.createPortal(
|
|
5426
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: src ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5427
|
-
framerMotion.motion.div,
|
|
5428
|
-
{
|
|
5429
|
-
className: "payman-v2-file-preview-overlay",
|
|
5430
|
-
initial: { opacity: 0 },
|
|
5431
|
-
animate: { opacity: 1 },
|
|
5432
|
-
exit: { opacity: 0 },
|
|
5433
|
-
transition: { duration: 0.18 },
|
|
5434
|
-
onClick: onClose,
|
|
5435
|
-
role: "dialog",
|
|
5436
|
-
"aria-modal": "true",
|
|
5437
|
-
"aria-label": `Preview: ${name}`,
|
|
5438
|
-
children: [
|
|
5439
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5440
|
-
"button",
|
|
5441
|
-
{
|
|
5442
|
-
type: "button",
|
|
5443
|
-
className: "payman-v2-file-preview-close",
|
|
5444
|
-
"aria-label": "Close preview",
|
|
5445
|
-
onClick: (e) => {
|
|
5446
|
-
e.stopPropagation();
|
|
5447
|
-
onClose();
|
|
5448
|
-
},
|
|
5449
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 18, strokeWidth: 2 })
|
|
5450
|
-
}
|
|
5451
|
-
),
|
|
5452
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5453
|
-
framerMotion.motion.div,
|
|
5454
|
-
{
|
|
5455
|
-
className: "payman-v2-file-preview-inner",
|
|
5456
|
-
initial: { scale: 0.93, opacity: 0 },
|
|
5457
|
-
animate: { scale: isLoaded ? 1 : 0.93, opacity: isLoaded ? 1 : 0 },
|
|
5458
|
-
exit: { scale: 0.93, opacity: 0 },
|
|
5459
|
-
transition: { duration: 0.2 },
|
|
5460
|
-
onClick: (e) => e.stopPropagation(),
|
|
5461
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5462
|
-
"img",
|
|
5463
|
-
{
|
|
5464
|
-
src,
|
|
5465
|
-
alt: name,
|
|
5466
|
-
className: "payman-v2-file-preview-img",
|
|
5467
|
-
draggable: false,
|
|
5468
|
-
onLoad: () => setIsLoaded(true)
|
|
5469
|
-
}
|
|
5470
|
-
)
|
|
5471
|
-
}
|
|
5472
|
-
)
|
|
5473
|
-
]
|
|
5474
|
-
},
|
|
5475
|
-
"file-preview"
|
|
5476
|
-
) : null }),
|
|
5477
|
-
document.body
|
|
5478
|
-
);
|
|
5479
|
-
}
|
|
5480
|
-
function normalizeExtension(ext) {
|
|
5481
|
-
return ext.replace(/^\./, "").toLowerCase();
|
|
5482
|
-
}
|
|
5483
|
-
function extOf(filename) {
|
|
5484
|
-
return filename.split(".").pop()?.toLowerCase() ?? "";
|
|
5485
|
-
}
|
|
5486
|
-
function isAllowedImage(file, allowedExtensions) {
|
|
5487
|
-
const allowed = new Set(allowedExtensions.map(normalizeExtension));
|
|
5488
|
-
const ext = extOf(file.name);
|
|
5489
|
-
if (allowed.has(ext)) return true;
|
|
5490
|
-
if (!file.type.startsWith("image/")) return false;
|
|
5491
|
-
const mimeSubtype = file.type.slice("image/".length).toLowerCase();
|
|
5492
|
-
return allowed.has(mimeSubtype) || mimeSubtype === "jpeg" && allowed.has("jpg");
|
|
5493
|
-
}
|
|
5494
|
-
function isAllowedDocument(file, allowedExtensions) {
|
|
5495
|
-
const allowed = new Set(allowedExtensions.map(normalizeExtension));
|
|
5496
|
-
return allowed.has(extOf(file.name));
|
|
5497
|
-
}
|
|
5498
|
-
function fileTypeLabel(file, kind) {
|
|
5499
|
-
if (kind === "image") return "Image";
|
|
5500
|
-
const ext = extOf(file.name);
|
|
5501
|
-
return ext ? ext.toUpperCase() : "Document";
|
|
5502
|
-
}
|
|
5503
4975
|
var ChatInputV2 = react.forwardRef(
|
|
5504
4976
|
function ChatInputV22({
|
|
5505
4977
|
onSend,
|
|
5506
4978
|
disabled = false,
|
|
5507
4979
|
isStreaming = false,
|
|
5508
|
-
isUploadingAttachments = false,
|
|
5509
|
-
attachmentsReady = true,
|
|
5510
|
-
hasAttachmentUploadErrors = false,
|
|
5511
|
-
attachmentUploadStatusById = {},
|
|
5512
|
-
uploadedAttachmentPayloads = [],
|
|
5513
4980
|
placeholder = "Reply...",
|
|
5514
4981
|
enableVoice = false,
|
|
5515
4982
|
voiceAvailable = false,
|
|
@@ -5523,13 +4990,6 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5523
4990
|
showAttachFileButton = true,
|
|
5524
4991
|
onUploadImageClick,
|
|
5525
4992
|
onAttachFileClick,
|
|
5526
|
-
allowedImageExtensions = ["png", "jpg", "jpeg", "gif", "webp"],
|
|
5527
|
-
allowedFileExtensions = ["pdf", "docx", "xlsx", "xls"],
|
|
5528
|
-
maxCount,
|
|
5529
|
-
maxFileBytes,
|
|
5530
|
-
maxTotalBytes,
|
|
5531
|
-
onFilesChange,
|
|
5532
|
-
onAttachmentsChange,
|
|
5533
4993
|
editingMessageId = null,
|
|
5534
4994
|
onClearEditing,
|
|
5535
4995
|
analysisMode,
|
|
@@ -5543,133 +5003,14 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5543
5003
|
const [selectedCommandIndex, setSelectedCommandIndex] = react.useState(0);
|
|
5544
5004
|
const [inlineHint, setInlineHint] = react.useState(null);
|
|
5545
5005
|
const [commandMenuDismissed, setCommandMenuDismissed] = react.useState(false);
|
|
5546
|
-
const [attachedFiles, setAttachedFiles] = react.useState([]);
|
|
5547
|
-
const [previewFile, setPreviewFile] = react.useState(null);
|
|
5548
|
-
const [isSending, setIsSending] = react.useState(false);
|
|
5549
5006
|
const textareaRef = react.useRef(null);
|
|
5550
5007
|
const actionsRef = react.useRef(null);
|
|
5551
|
-
const imageInputRef = react.useRef(null);
|
|
5552
|
-
const fileInputRef = react.useRef(null);
|
|
5553
5008
|
const preRecordTextRef = react.useRef("");
|
|
5554
5009
|
const voiceTooltipTimerRef = react.useRef(
|
|
5555
5010
|
null
|
|
5556
5011
|
);
|
|
5557
5012
|
const voiceDraftSyncActiveRef = react.useRef(false);
|
|
5558
|
-
const
|
|
5559
|
-
react.useEffect(() => {
|
|
5560
|
-
return () => {
|
|
5561
|
-
attachedFiles.forEach((f) => URL.revokeObjectURL(f.objectUrl));
|
|
5562
|
-
};
|
|
5563
|
-
}, []);
|
|
5564
|
-
const notifyAttachmentList = react.useCallback(
|
|
5565
|
-
(files) => {
|
|
5566
|
-
onFilesChange?.(files.map((f) => f.file));
|
|
5567
|
-
onAttachmentsChange?.(files.map((f) => ({ id: f.id, file: f.file })));
|
|
5568
|
-
},
|
|
5569
|
-
[onAttachmentsChange, onFilesChange]
|
|
5570
|
-
);
|
|
5571
|
-
const clearAttachmentsFromInput = react.useCallback(() => {
|
|
5572
|
-
setAttachedFiles((prev) => {
|
|
5573
|
-
prev.forEach((f) => URL.revokeObjectURL(f.objectUrl));
|
|
5574
|
-
return [];
|
|
5575
|
-
});
|
|
5576
|
-
setPreviewFile(null);
|
|
5577
|
-
onFilesChange?.([]);
|
|
5578
|
-
onAttachmentsChange?.([]);
|
|
5579
|
-
}, [onAttachmentsChange, onFilesChange]);
|
|
5580
|
-
const addFiles = react.useCallback(
|
|
5581
|
-
(incoming, source) => {
|
|
5582
|
-
const isImage = source === "image";
|
|
5583
|
-
const allowedExtensions = isImage ? allowedImageExtensions : allowedFileExtensions;
|
|
5584
|
-
const isAllowed = isImage ? isAllowedImage : isAllowedDocument;
|
|
5585
|
-
const kindLabel = isImage ? "image" : "document";
|
|
5586
|
-
setAttachedFiles((prev) => {
|
|
5587
|
-
const accepted = [];
|
|
5588
|
-
let rejectedType = false;
|
|
5589
|
-
let hitCountLimit = false;
|
|
5590
|
-
let hitFileSizeLimit = false;
|
|
5591
|
-
let hitTotalSizeLimit = false;
|
|
5592
|
-
let oversizedName = "";
|
|
5593
|
-
const currentTotalBytes = prev.reduce(
|
|
5594
|
-
(sum, item) => sum + item.file.size,
|
|
5595
|
-
0
|
|
5596
|
-
);
|
|
5597
|
-
let addedBytes = 0;
|
|
5598
|
-
for (const file of incoming) {
|
|
5599
|
-
if (!isAllowed(file, allowedExtensions)) {
|
|
5600
|
-
rejectedType = true;
|
|
5601
|
-
continue;
|
|
5602
|
-
}
|
|
5603
|
-
if (maxFileBytes != null && file.size > maxFileBytes) {
|
|
5604
|
-
hitFileSizeLimit = true;
|
|
5605
|
-
oversizedName = file.name;
|
|
5606
|
-
continue;
|
|
5607
|
-
}
|
|
5608
|
-
if (maxTotalBytes != null && currentTotalBytes + addedBytes + file.size > maxTotalBytes) {
|
|
5609
|
-
hitTotalSizeLimit = true;
|
|
5610
|
-
break;
|
|
5611
|
-
}
|
|
5612
|
-
if (maxCount != null && prev.length + accepted.length >= maxCount) {
|
|
5613
|
-
hitCountLimit = true;
|
|
5614
|
-
break;
|
|
5615
|
-
}
|
|
5616
|
-
accepted.push({
|
|
5617
|
-
id: `${Date.now()}-${Math.random()}`,
|
|
5618
|
-
file,
|
|
5619
|
-
kind: source,
|
|
5620
|
-
objectUrl: URL.createObjectURL(file)
|
|
5621
|
-
});
|
|
5622
|
-
addedBytes += file.size;
|
|
5623
|
-
}
|
|
5624
|
-
if (rejectedType) {
|
|
5625
|
-
setInlineHint(
|
|
5626
|
-
`Unsupported ${kindLabel} type. Allowed: ${allowedExtensions.map(normalizeExtension).join(", ")}.`
|
|
5627
|
-
);
|
|
5628
|
-
} else if (hitFileSizeLimit) {
|
|
5629
|
-
setInlineHint(
|
|
5630
|
-
maxFileBytes != null ? `"${oversizedName}" exceeds the ${formatAttachmentBytes(maxFileBytes)} per-file limit.` : "File exceeds the maximum allowed size."
|
|
5631
|
-
);
|
|
5632
|
-
} else if (hitTotalSizeLimit) {
|
|
5633
|
-
setInlineHint(
|
|
5634
|
-
maxTotalBytes != null ? `Total attachment size would exceed ${formatAttachmentBytes(maxTotalBytes)}.` : "Total attachment size exceeds the limit."
|
|
5635
|
-
);
|
|
5636
|
-
} else if (hitCountLimit) {
|
|
5637
|
-
setInlineHint(
|
|
5638
|
-
maxCount === 1 ? "Only 1 attachment is allowed per message." : `Maximum ${maxCount} attachments allowed per message.`
|
|
5639
|
-
);
|
|
5640
|
-
}
|
|
5641
|
-
if (accepted.length === 0) return prev;
|
|
5642
|
-
const updated = [...prev, ...accepted];
|
|
5643
|
-
notifyAttachmentList(updated);
|
|
5644
|
-
return updated;
|
|
5645
|
-
});
|
|
5646
|
-
},
|
|
5647
|
-
[
|
|
5648
|
-
allowedFileExtensions,
|
|
5649
|
-
allowedImageExtensions,
|
|
5650
|
-
maxCount,
|
|
5651
|
-
maxFileBytes,
|
|
5652
|
-
maxTotalBytes,
|
|
5653
|
-
notifyAttachmentList
|
|
5654
|
-
]
|
|
5655
|
-
);
|
|
5656
|
-
const removeFile = react.useCallback(
|
|
5657
|
-
(id) => {
|
|
5658
|
-
setAttachedFiles((prev) => {
|
|
5659
|
-
const target = prev.find((f) => f.id === id);
|
|
5660
|
-
if (target) URL.revokeObjectURL(target.objectUrl);
|
|
5661
|
-
const updated = prev.filter((f) => f.id !== id);
|
|
5662
|
-
notifyAttachmentList(updated);
|
|
5663
|
-
return updated;
|
|
5664
|
-
});
|
|
5665
|
-
setPreviewFile((p) => p?.id === id ? null : p);
|
|
5666
|
-
},
|
|
5667
|
-
[notifyAttachmentList]
|
|
5668
|
-
);
|
|
5669
|
-
const imageAccept = allowedImageExtensions.map((e) => `.${e.replace(/^\./, "")}`).join(",");
|
|
5670
|
-
const fileAccept = allowedFileExtensions.map((e) => `.${e.replace(/^\./, "")}`).join(",");
|
|
5671
|
-
const isInputBusy = isSending || isUploadingAttachments;
|
|
5672
|
-
const isInputLocked = disabled || isRecording || isInputBusy;
|
|
5013
|
+
const isInputLocked = disabled || isRecording;
|
|
5673
5014
|
const hasAttachmentOptions = showUploadImageButton || showAttachFileButton;
|
|
5674
5015
|
const showAttachmentMenuButton = showAttachmentButton && hasAttachmentOptions;
|
|
5675
5016
|
const showVoiceButton = enableVoice && onVoicePress != null;
|
|
@@ -5709,10 +5050,9 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5709
5050
|
const end = message.length;
|
|
5710
5051
|
textarea.setSelectionRange(end, end);
|
|
5711
5052
|
});
|
|
5712
|
-
}
|
|
5713
|
-
clearAttachments: clearAttachmentsFromInput
|
|
5053
|
+
}
|
|
5714
5054
|
}),
|
|
5715
|
-
[disabled
|
|
5055
|
+
[disabled]
|
|
5716
5056
|
);
|
|
5717
5057
|
react.useEffect(() => {
|
|
5718
5058
|
if (!showActions) return;
|
|
@@ -5746,23 +5086,8 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5746
5086
|
const separator = base && !base.endsWith(" ") && transcribedText ? " " : "";
|
|
5747
5087
|
setValue(`${base}${separator}${transcribedText}`);
|
|
5748
5088
|
}, [isRecording, transcribedText]);
|
|
5749
|
-
|
|
5750
|
-
if (
|
|
5751
|
-
if (status === "error") return "Upload failed";
|
|
5752
|
-
return fileTypeLabel(file, kind);
|
|
5753
|
-
}
|
|
5754
|
-
const handleSend = react.useCallback(async () => {
|
|
5755
|
-
const hasText = value.trim().length > 0;
|
|
5756
|
-
const hasFiles = attachedFiles.length > 0;
|
|
5757
|
-
if (!hasText && !hasFiles || disabled || isSending || isUploadingAttachments) return;
|
|
5758
|
-
if (hasFiles && !attachmentsReady) {
|
|
5759
|
-
setInlineHint("Waiting for attachments to finish uploading.");
|
|
5760
|
-
return;
|
|
5761
|
-
}
|
|
5762
|
-
if (hasFiles && hasAttachmentUploadErrors) {
|
|
5763
|
-
setInlineHint("Remove or re-add attachments that failed to upload.");
|
|
5764
|
-
return;
|
|
5765
|
-
}
|
|
5089
|
+
const handleSend = react.useCallback(() => {
|
|
5090
|
+
if (!value.trim() || disabled) return;
|
|
5766
5091
|
const commandHint = getSlashCommandValidationHint(value);
|
|
5767
5092
|
if (commandHint) {
|
|
5768
5093
|
setInlineHint(commandHint);
|
|
@@ -5772,38 +5097,15 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5772
5097
|
preRecordTextRef.current = "";
|
|
5773
5098
|
setInlineHint(null);
|
|
5774
5099
|
onClearEditing?.();
|
|
5775
|
-
|
|
5776
|
-
const filesToSend = attachedFiles.map((f) => f.file);
|
|
5777
|
-
const attachmentsToSend = [...uploadedAttachmentPayloads];
|
|
5100
|
+
onSend(value.trim());
|
|
5778
5101
|
setValue("");
|
|
5779
|
-
clearAttachmentsFromInput();
|
|
5780
5102
|
requestAnimationFrame(() => {
|
|
5781
5103
|
if (textareaRef.current) {
|
|
5782
5104
|
textareaRef.current.style.height = "auto";
|
|
5783
5105
|
textareaRef.current.focus();
|
|
5784
5106
|
}
|
|
5785
5107
|
});
|
|
5786
|
-
|
|
5787
|
-
try {
|
|
5788
|
-
await onSend(textToSend, filesToSend, attachmentsToSend);
|
|
5789
|
-
} catch {
|
|
5790
|
-
setInlineHint("Failed to send message. Please try again.");
|
|
5791
|
-
} finally {
|
|
5792
|
-
setIsSending(false);
|
|
5793
|
-
}
|
|
5794
|
-
}, [
|
|
5795
|
-
value,
|
|
5796
|
-
attachedFiles,
|
|
5797
|
-
uploadedAttachmentPayloads,
|
|
5798
|
-
disabled,
|
|
5799
|
-
isSending,
|
|
5800
|
-
isUploadingAttachments,
|
|
5801
|
-
attachmentsReady,
|
|
5802
|
-
hasAttachmentUploadErrors,
|
|
5803
|
-
onClearEditing,
|
|
5804
|
-
onSend,
|
|
5805
|
-
clearAttachmentsFromInput
|
|
5806
|
-
]);
|
|
5108
|
+
}, [value, disabled, onClearEditing, onSend]);
|
|
5807
5109
|
const selectCommand = react.useCallback(
|
|
5808
5110
|
(command) => {
|
|
5809
5111
|
const insertText = command.insertText ?? `${command.name} `;
|
|
@@ -5848,30 +5150,18 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5848
5150
|
}
|
|
5849
5151
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
5850
5152
|
e.preventDefault();
|
|
5851
|
-
if (isStreaming
|
|
5852
|
-
|
|
5153
|
+
if (isStreaming) return;
|
|
5154
|
+
handleSend();
|
|
5853
5155
|
}
|
|
5854
5156
|
};
|
|
5855
5157
|
const handleUploadImageClick = () => {
|
|
5856
|
-
imageInputRef.current?.click();
|
|
5857
5158
|
onUploadImageClick?.();
|
|
5858
5159
|
setShowActions(false);
|
|
5859
5160
|
};
|
|
5860
5161
|
const handleAttachFileClick = () => {
|
|
5861
|
-
fileInputRef.current?.click();
|
|
5862
5162
|
onAttachFileClick?.();
|
|
5863
5163
|
setShowActions(false);
|
|
5864
5164
|
};
|
|
5865
|
-
const handleImageFilesSelected = (e) => {
|
|
5866
|
-
const files = Array.from(e.target.files ?? []);
|
|
5867
|
-
if (files.length) addFiles(files, "image");
|
|
5868
|
-
e.target.value = "";
|
|
5869
|
-
};
|
|
5870
|
-
const handleDocFilesSelected = (e) => {
|
|
5871
|
-
const files = Array.from(e.target.files ?? []);
|
|
5872
|
-
if (files.length) addFiles(files, "file");
|
|
5873
|
-
e.target.value = "";
|
|
5874
|
-
};
|
|
5875
5165
|
const hideVoiceTooltip = react.useCallback(() => {
|
|
5876
5166
|
if (voiceTooltipTimerRef.current) {
|
|
5877
5167
|
clearTimeout(voiceTooltipTimerRef.current);
|
|
@@ -5899,39 +5189,9 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5899
5189
|
}
|
|
5900
5190
|
onVoicePress();
|
|
5901
5191
|
};
|
|
5902
|
-
const canSend =
|
|
5903
|
-
const sendDisabled = !canSend || isStreaming
|
|
5192
|
+
const canSend = value.trim().length > 0 && !disabled;
|
|
5193
|
+
const sendDisabled = !canSend || isStreaming;
|
|
5904
5194
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-input-container", children: [
|
|
5905
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5906
|
-
"input",
|
|
5907
|
-
{
|
|
5908
|
-
ref: imageInputRef,
|
|
5909
|
-
type: "file",
|
|
5910
|
-
accept: imageAccept,
|
|
5911
|
-
multiple: maxCount == null || maxCount > 1,
|
|
5912
|
-
style: { display: "none" },
|
|
5913
|
-
onChange: handleImageFilesSelected
|
|
5914
|
-
}
|
|
5915
|
-
),
|
|
5916
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5917
|
-
"input",
|
|
5918
|
-
{
|
|
5919
|
-
ref: fileInputRef,
|
|
5920
|
-
type: "file",
|
|
5921
|
-
accept: fileAccept,
|
|
5922
|
-
multiple: maxCount == null || maxCount > 1,
|
|
5923
|
-
style: { display: "none" },
|
|
5924
|
-
onChange: handleDocFilesSelected
|
|
5925
|
-
}
|
|
5926
|
-
),
|
|
5927
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5928
|
-
FilePreviewModal,
|
|
5929
|
-
{
|
|
5930
|
-
src: previewFile?.kind === "image" ? previewFile.objectUrl : null,
|
|
5931
|
-
name: previewFile?.file.name ?? "",
|
|
5932
|
-
onClose: () => setPreviewFile(null)
|
|
5933
|
-
}
|
|
5934
|
-
),
|
|
5935
5195
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: showCommandSuggestions && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5936
5196
|
framerMotion.motion.div,
|
|
5937
5197
|
{
|
|
@@ -5970,115 +5230,6 @@ var ChatInputV2 = react.forwardRef(
|
|
|
5970
5230
|
),
|
|
5971
5231
|
children: [
|
|
5972
5232
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-input-body", children: [
|
|
5973
|
-
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { initial: false, children: attachedFiles.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5974
|
-
framerMotion.motion.div,
|
|
5975
|
-
{
|
|
5976
|
-
initial: { opacity: 0, height: 0 },
|
|
5977
|
-
animate: { opacity: 1, height: "auto" },
|
|
5978
|
-
exit: { opacity: 0, height: 0 },
|
|
5979
|
-
transition: { duration: 0.15, ease: "easeOut" },
|
|
5980
|
-
className: "payman-v2-file-preview",
|
|
5981
|
-
children: attachedFiles.map((af) => {
|
|
5982
|
-
const uploadStatus = attachmentUploadStatusById[af.id];
|
|
5983
|
-
const isUploadingFile = uploadStatus === "uploading";
|
|
5984
|
-
const hasUploadError = uploadStatus === "error";
|
|
5985
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-file-preview-item", children: [
|
|
5986
|
-
af.kind === "image" ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5987
|
-
"button",
|
|
5988
|
-
{
|
|
5989
|
-
type: "button",
|
|
5990
|
-
className: cn(
|
|
5991
|
-
"payman-v2-file-preview-shell payman-v2-file-preview-shell-clickable",
|
|
5992
|
-
hasUploadError && "payman-v2-file-preview-shell-error"
|
|
5993
|
-
),
|
|
5994
|
-
onClick: () => setPreviewFile(af),
|
|
5995
|
-
disabled: isUploadingFile,
|
|
5996
|
-
"aria-label": `Preview ${af.file.name}`,
|
|
5997
|
-
children: [
|
|
5998
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-file-preview-thumb", children: [
|
|
5999
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6000
|
-
"img",
|
|
6001
|
-
{
|
|
6002
|
-
src: af.objectUrl,
|
|
6003
|
-
alt: "",
|
|
6004
|
-
draggable: false
|
|
6005
|
-
}
|
|
6006
|
-
),
|
|
6007
|
-
isUploadingFile && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-file-preview-uploading", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 14, className: "payman-v2-spin" }) })
|
|
6008
|
-
] }),
|
|
6009
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-file-preview-info", children: [
|
|
6010
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-file-preview-name", children: af.file.name }),
|
|
6011
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-file-preview-type", children: uploadStatusLabel(uploadStatus, af.file, af.kind) })
|
|
6012
|
-
] })
|
|
6013
|
-
]
|
|
6014
|
-
}
|
|
6015
|
-
) : isPdfFile(af.file) ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6016
|
-
"button",
|
|
6017
|
-
{
|
|
6018
|
-
type: "button",
|
|
6019
|
-
className: cn(
|
|
6020
|
-
"payman-v2-file-preview-shell payman-v2-file-preview-shell-clickable",
|
|
6021
|
-
hasUploadError && "payman-v2-file-preview-shell-error"
|
|
6022
|
-
),
|
|
6023
|
-
onClick: () => chatContext?.openPdfSheet(
|
|
6024
|
-
af.objectUrl,
|
|
6025
|
-
af.file.name
|
|
6026
|
-
),
|
|
6027
|
-
disabled: isUploadingFile,
|
|
6028
|
-
"aria-label": `Preview ${af.file.name}`,
|
|
6029
|
-
children: [
|
|
6030
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-file-preview-thumb", children: isUploadingFile ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 16, className: "payman-v2-spin payman-v2-file-preview-doc-icon" }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
6031
|
-
lucideReact.FileText,
|
|
6032
|
-
{
|
|
6033
|
-
size: 16,
|
|
6034
|
-
strokeWidth: 1.75,
|
|
6035
|
-
className: "payman-v2-file-preview-doc-icon"
|
|
6036
|
-
}
|
|
6037
|
-
) }),
|
|
6038
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-file-preview-info", children: [
|
|
6039
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-file-preview-name", children: af.file.name }),
|
|
6040
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-file-preview-type", children: uploadStatusLabel(uploadStatus, af.file, af.kind) })
|
|
6041
|
-
] })
|
|
6042
|
-
]
|
|
6043
|
-
}
|
|
6044
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6045
|
-
"div",
|
|
6046
|
-
{
|
|
6047
|
-
className: cn(
|
|
6048
|
-
"payman-v2-file-preview-shell",
|
|
6049
|
-
hasUploadError && "payman-v2-file-preview-shell-error"
|
|
6050
|
-
),
|
|
6051
|
-
children: [
|
|
6052
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-file-preview-thumb", children: isUploadingFile ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 16, className: "payman-v2-spin payman-v2-file-preview-doc-icon" }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
6053
|
-
lucideReact.FileText,
|
|
6054
|
-
{
|
|
6055
|
-
size: 16,
|
|
6056
|
-
strokeWidth: 1.75,
|
|
6057
|
-
className: "payman-v2-file-preview-doc-icon"
|
|
6058
|
-
}
|
|
6059
|
-
) }),
|
|
6060
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-file-preview-info", children: [
|
|
6061
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-file-preview-name", children: af.file.name }),
|
|
6062
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-file-preview-type", children: uploadStatusLabel(uploadStatus, af.file, af.kind) })
|
|
6063
|
-
] })
|
|
6064
|
-
]
|
|
6065
|
-
}
|
|
6066
|
-
),
|
|
6067
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6068
|
-
"button",
|
|
6069
|
-
{
|
|
6070
|
-
type: "button",
|
|
6071
|
-
className: "payman-v2-file-preview-remove",
|
|
6072
|
-
onClick: () => removeFile(af.id),
|
|
6073
|
-
"aria-label": `Remove ${af.file.name}`,
|
|
6074
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 12, strokeWidth: 2.5 })
|
|
6075
|
-
}
|
|
6076
|
-
)
|
|
6077
|
-
] }, af.id);
|
|
6078
|
-
})
|
|
6079
|
-
},
|
|
6080
|
-
"file-preview"
|
|
6081
|
-
) }),
|
|
6082
5233
|
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { initial: false, children: editingMessageId && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6083
5234
|
framerMotion.motion.div,
|
|
6084
5235
|
{
|
|
@@ -6310,13 +5461,13 @@ var ChatInputV2 = react.forwardRef(
|
|
|
6310
5461
|
"button",
|
|
6311
5462
|
{
|
|
6312
5463
|
type: "button",
|
|
6313
|
-
onClick:
|
|
5464
|
+
onClick: handleSend,
|
|
6314
5465
|
disabled: sendDisabled,
|
|
6315
5466
|
className: cn(
|
|
6316
5467
|
"payman-v2-input-send-btn",
|
|
6317
5468
|
sendDisabled && "payman-v2-input-send-btn-disabled"
|
|
6318
5469
|
),
|
|
6319
|
-
"aria-label":
|
|
5470
|
+
"aria-label": "Send message",
|
|
6320
5471
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6321
5472
|
lucideReact.ArrowUp,
|
|
6322
5473
|
{
|
|
@@ -6851,389 +6002,6 @@ function TimelineBars({
|
|
|
6851
6002
|
)
|
|
6852
6003
|
] });
|
|
6853
6004
|
}
|
|
6854
|
-
|
|
6855
|
-
// src/utils/pdfPreview.ts
|
|
6856
|
-
var PdfPreviewError = class extends Error {
|
|
6857
|
-
constructor(kind, title, userMessage) {
|
|
6858
|
-
super(userMessage);
|
|
6859
|
-
__publicField(this, "kind");
|
|
6860
|
-
__publicField(this, "title");
|
|
6861
|
-
__publicField(this, "userMessage");
|
|
6862
|
-
this.name = "PdfPreviewError";
|
|
6863
|
-
this.kind = kind;
|
|
6864
|
-
this.title = title;
|
|
6865
|
-
this.userMessage = userMessage;
|
|
6866
|
-
}
|
|
6867
|
-
};
|
|
6868
|
-
function classifyErrorBody(body, status) {
|
|
6869
|
-
const text = body.replace(/\s+/g, " ").trim();
|
|
6870
|
-
if (/signed expiry time|must be after signed start time|expired|expir/i.test(text)) {
|
|
6871
|
-
return new PdfPreviewError(
|
|
6872
|
-
"expired",
|
|
6873
|
-
"Link expired",
|
|
6874
|
-
"This download link has expired. Ask the assistant to generate a new copy of the document."
|
|
6875
|
-
);
|
|
6876
|
-
}
|
|
6877
|
-
if (/AuthenticationFailed|authorization header|formed correctly including the signature/i.test(
|
|
6878
|
-
text
|
|
6879
|
-
)) {
|
|
6880
|
-
return new PdfPreviewError(
|
|
6881
|
-
"forbidden",
|
|
6882
|
-
"Link no longer valid",
|
|
6883
|
-
"This preview link is no longer valid. Request a fresh download link and try again."
|
|
6884
|
-
);
|
|
6885
|
-
}
|
|
6886
|
-
if (status === 404 || /BlobNotFound|ResourceNotFound|The specified blob does not exist/i.test(text)) {
|
|
6887
|
-
return new PdfPreviewError(
|
|
6888
|
-
"not_found",
|
|
6889
|
-
"Document not found",
|
|
6890
|
-
"The file is no longer available. It may have been removed or the link is incorrect."
|
|
6891
|
-
);
|
|
6892
|
-
}
|
|
6893
|
-
if (status === 403) {
|
|
6894
|
-
return new PdfPreviewError(
|
|
6895
|
-
"forbidden",
|
|
6896
|
-
"Can't open document",
|
|
6897
|
-
"You may not have access to this file, or the link has expired."
|
|
6898
|
-
);
|
|
6899
|
-
}
|
|
6900
|
-
if (status === 401) {
|
|
6901
|
-
return new PdfPreviewError(
|
|
6902
|
-
"forbidden",
|
|
6903
|
-
"Access denied",
|
|
6904
|
-
"This preview link could not be verified. Request a new download link."
|
|
6905
|
-
);
|
|
6906
|
-
}
|
|
6907
|
-
return new PdfPreviewError(
|
|
6908
|
-
"unknown",
|
|
6909
|
-
"Can't preview document",
|
|
6910
|
-
"Something went wrong while opening this file. Try downloading it or request a new link."
|
|
6911
|
-
);
|
|
6912
|
-
}
|
|
6913
|
-
function normalizePdfPreviewError(error) {
|
|
6914
|
-
if (error instanceof PdfPreviewError) return error;
|
|
6915
|
-
if (error instanceof TypeError) {
|
|
6916
|
-
return new PdfPreviewError(
|
|
6917
|
-
"network",
|
|
6918
|
-
"Connection problem",
|
|
6919
|
-
"Could not load the document. Check your connection and try again."
|
|
6920
|
-
);
|
|
6921
|
-
}
|
|
6922
|
-
return new PdfPreviewError(
|
|
6923
|
-
"unknown",
|
|
6924
|
-
"Can't preview document",
|
|
6925
|
-
"Something went wrong while opening this file. Try downloading it or request a new link."
|
|
6926
|
-
);
|
|
6927
|
-
}
|
|
6928
|
-
async function assertPdfBlob(blob, status) {
|
|
6929
|
-
if (!blob.size) {
|
|
6930
|
-
return Promise.reject(
|
|
6931
|
-
new PdfPreviewError(
|
|
6932
|
-
"empty",
|
|
6933
|
-
"Document unavailable",
|
|
6934
|
-
"The file response was empty. Request a new download link and try again."
|
|
6935
|
-
)
|
|
6936
|
-
);
|
|
6937
|
-
}
|
|
6938
|
-
const head = await blob.slice(0, Math.min(blob.size, 1024)).text();
|
|
6939
|
-
if (head.startsWith("%PDF")) {
|
|
6940
|
-
return blob;
|
|
6941
|
-
}
|
|
6942
|
-
throw classifyErrorBody(head, status);
|
|
6943
|
-
}
|
|
6944
|
-
async function fetchPdfBlob(src) {
|
|
6945
|
-
let response;
|
|
6946
|
-
try {
|
|
6947
|
-
response = await fetch(src, {
|
|
6948
|
-
method: "GET",
|
|
6949
|
-
headers: { Accept: "application/pdf,*/*" }
|
|
6950
|
-
});
|
|
6951
|
-
} catch {
|
|
6952
|
-
throw new PdfPreviewError(
|
|
6953
|
-
"network",
|
|
6954
|
-
"Connection problem",
|
|
6955
|
-
"Could not load the document. Check your connection and try again."
|
|
6956
|
-
);
|
|
6957
|
-
}
|
|
6958
|
-
const blob = await response.blob();
|
|
6959
|
-
if (!response.ok) {
|
|
6960
|
-
const body = await blob.text().catch(() => "");
|
|
6961
|
-
throw classifyErrorBody(body, response.status);
|
|
6962
|
-
}
|
|
6963
|
-
return assertPdfBlob(blob, response.status);
|
|
6964
|
-
}
|
|
6965
|
-
var MIN_WIDTH = 320;
|
|
6966
|
-
var MAX_WIDTH_RATIO = 0.6;
|
|
6967
|
-
var DEFAULT_WIDTH = 520;
|
|
6968
|
-
var SPRING = { type: "spring", stiffness: 340, damping: 34, mass: 0.85 };
|
|
6969
|
-
var SHEET_EXIT = { duration: 0.22, ease: [0.4, 0, 1, 1] };
|
|
6970
|
-
function pdfDownloadName(title) {
|
|
6971
|
-
const base = title.trim() || "document";
|
|
6972
|
-
return base.toLowerCase().endsWith(".pdf") ? base : `${base}.pdf`;
|
|
6973
|
-
}
|
|
6974
|
-
function clampSplitWidth(w) {
|
|
6975
|
-
const maxW = Math.floor(window.innerWidth * MAX_WIDTH_RATIO);
|
|
6976
|
-
return Math.max(MIN_WIDTH, Math.min(maxW, w));
|
|
6977
|
-
}
|
|
6978
|
-
function PdfSheetV2({
|
|
6979
|
-
src,
|
|
6980
|
-
title,
|
|
6981
|
-
onClose,
|
|
6982
|
-
mode = "split"
|
|
6983
|
-
}) {
|
|
6984
|
-
return /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: src && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6985
|
-
PdfSheetPanel,
|
|
6986
|
-
{
|
|
6987
|
-
src,
|
|
6988
|
-
title,
|
|
6989
|
-
onClose,
|
|
6990
|
-
mode
|
|
6991
|
-
},
|
|
6992
|
-
"pdf-panel"
|
|
6993
|
-
) });
|
|
6994
|
-
}
|
|
6995
|
-
function PdfSheetPanel({
|
|
6996
|
-
src,
|
|
6997
|
-
title,
|
|
6998
|
-
onClose,
|
|
6999
|
-
mode
|
|
7000
|
-
}) {
|
|
7001
|
-
const isSheet = mode === "sheet";
|
|
7002
|
-
const [isLoaded, setIsLoaded] = react.useState(false);
|
|
7003
|
-
const [isDownloading, setIsDownloading] = react.useState(false);
|
|
7004
|
-
const [previewUrl, setPreviewUrl] = react.useState(null);
|
|
7005
|
-
const [previewError, setPreviewError] = react.useState(null);
|
|
7006
|
-
const [loadAttempt, setLoadAttempt] = react.useState(0);
|
|
7007
|
-
const blobRef = react.useRef(null);
|
|
7008
|
-
const objectUrlRef = react.useRef(null);
|
|
7009
|
-
const [panelWidth, setPanelWidth] = react.useState(DEFAULT_WIDTH);
|
|
7010
|
-
const [splitOpened, setSplitOpened] = react.useState(false);
|
|
7011
|
-
const [isDragging, setIsDragging] = react.useState(false);
|
|
7012
|
-
react.useEffect(() => {
|
|
7013
|
-
setIsLoaded(false);
|
|
7014
|
-
setPreviewUrl(null);
|
|
7015
|
-
setPreviewError(null);
|
|
7016
|
-
setPanelWidth(DEFAULT_WIDTH);
|
|
7017
|
-
setSplitOpened(false);
|
|
7018
|
-
blobRef.current = null;
|
|
7019
|
-
if (objectUrlRef.current) {
|
|
7020
|
-
URL.revokeObjectURL(objectUrlRef.current);
|
|
7021
|
-
objectUrlRef.current = null;
|
|
7022
|
-
}
|
|
7023
|
-
let cancelled = false;
|
|
7024
|
-
const loadPreview = async () => {
|
|
7025
|
-
try {
|
|
7026
|
-
const blob = await fetchPdfBlob(src);
|
|
7027
|
-
if (cancelled) return;
|
|
7028
|
-
blobRef.current = blob;
|
|
7029
|
-
const objectUrl = URL.createObjectURL(blob);
|
|
7030
|
-
objectUrlRef.current = objectUrl;
|
|
7031
|
-
setPreviewUrl(objectUrl);
|
|
7032
|
-
} catch (error) {
|
|
7033
|
-
if (!cancelled) {
|
|
7034
|
-
setPreviewError(normalizePdfPreviewError(error));
|
|
7035
|
-
}
|
|
7036
|
-
}
|
|
7037
|
-
};
|
|
7038
|
-
void loadPreview();
|
|
7039
|
-
return () => {
|
|
7040
|
-
cancelled = true;
|
|
7041
|
-
if (objectUrlRef.current) {
|
|
7042
|
-
URL.revokeObjectURL(objectUrlRef.current);
|
|
7043
|
-
objectUrlRef.current = null;
|
|
7044
|
-
}
|
|
7045
|
-
blobRef.current = null;
|
|
7046
|
-
};
|
|
7047
|
-
}, [src, loadAttempt]);
|
|
7048
|
-
react.useEffect(() => {
|
|
7049
|
-
if (isSheet) return;
|
|
7050
|
-
const onWindowResize = () => setPanelWidth((size) => clampSplitWidth(size));
|
|
7051
|
-
window.addEventListener("resize", onWindowResize);
|
|
7052
|
-
return () => window.removeEventListener("resize", onWindowResize);
|
|
7053
|
-
}, [isSheet]);
|
|
7054
|
-
const handleKeyDown = react.useCallback(
|
|
7055
|
-
(e) => {
|
|
7056
|
-
if (e.key === "Escape") onClose();
|
|
7057
|
-
},
|
|
7058
|
-
[onClose]
|
|
7059
|
-
);
|
|
7060
|
-
react.useEffect(() => {
|
|
7061
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
7062
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
7063
|
-
}, [handleKeyDown]);
|
|
7064
|
-
const canDownload = isLoaded && previewUrl != null && !previewError;
|
|
7065
|
-
const handleDownload = async () => {
|
|
7066
|
-
const filename = pdfDownloadName(title);
|
|
7067
|
-
setIsDownloading(true);
|
|
7068
|
-
try {
|
|
7069
|
-
const blob = blobRef.current ?? await fetchPdfBlob(src);
|
|
7070
|
-
const objectUrl = URL.createObjectURL(blob);
|
|
7071
|
-
const a = document.createElement("a");
|
|
7072
|
-
a.href = objectUrl;
|
|
7073
|
-
a.download = filename;
|
|
7074
|
-
a.target = "_blank";
|
|
7075
|
-
a.rel = "noopener noreferrer";
|
|
7076
|
-
document.body.appendChild(a);
|
|
7077
|
-
a.click();
|
|
7078
|
-
a.remove();
|
|
7079
|
-
URL.revokeObjectURL(objectUrl);
|
|
7080
|
-
} catch (error) {
|
|
7081
|
-
setPreviewError(normalizePdfPreviewError(error));
|
|
7082
|
-
} finally {
|
|
7083
|
-
setIsDownloading(false);
|
|
7084
|
-
}
|
|
7085
|
-
};
|
|
7086
|
-
const handleRetry = () => {
|
|
7087
|
-
setPreviewError(null);
|
|
7088
|
-
setIsLoaded(false);
|
|
7089
|
-
setPreviewUrl(null);
|
|
7090
|
-
setLoadAttempt((attempt) => attempt + 1);
|
|
7091
|
-
};
|
|
7092
|
-
const handleOpenInNewTab = () => {
|
|
7093
|
-
window.open(src, "_blank", "noopener,noreferrer");
|
|
7094
|
-
};
|
|
7095
|
-
const onResizeMouseDown = (e) => {
|
|
7096
|
-
if (e.button !== 0) return;
|
|
7097
|
-
e.preventDefault();
|
|
7098
|
-
const startX = e.clientX;
|
|
7099
|
-
const startW = panelWidth;
|
|
7100
|
-
setIsDragging(true);
|
|
7101
|
-
const onMove = (ev) => {
|
|
7102
|
-
setPanelWidth(clampSplitWidth(startW + (startX - ev.clientX)));
|
|
7103
|
-
};
|
|
7104
|
-
const onUp = () => {
|
|
7105
|
-
setIsDragging(false);
|
|
7106
|
-
document.removeEventListener("mousemove", onMove);
|
|
7107
|
-
document.removeEventListener("mouseup", onUp);
|
|
7108
|
-
};
|
|
7109
|
-
document.addEventListener("mousemove", onMove);
|
|
7110
|
-
document.addEventListener("mouseup", onUp);
|
|
7111
|
-
};
|
|
7112
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7113
|
-
framerMotion.motion.div,
|
|
7114
|
-
{
|
|
7115
|
-
className: cn(
|
|
7116
|
-
"payman-v2-root payman-v2-pdf-sheet-panel",
|
|
7117
|
-
isSheet && "payman-v2-pdf-sheet-panel--sheet"
|
|
7118
|
-
),
|
|
7119
|
-
style: { minWidth: 0 },
|
|
7120
|
-
initial: isSheet ? { x: "100%", opacity: 0 } : { width: 0, opacity: 0 },
|
|
7121
|
-
animate: isSheet ? { x: 0, opacity: 1 } : { width: panelWidth, opacity: 1 },
|
|
7122
|
-
exit: isSheet ? { x: "100%", opacity: 0, transition: { x: SHEET_EXIT, opacity: SHEET_EXIT } } : { width: 0, opacity: 0, transition: { width: SHEET_EXIT, opacity: SHEET_EXIT } },
|
|
7123
|
-
transition: isSheet ? { x: SPRING, opacity: SPRING } : {
|
|
7124
|
-
width: splitOpened ? { duration: 0 } : SPRING,
|
|
7125
|
-
opacity: SPRING
|
|
7126
|
-
},
|
|
7127
|
-
onAnimationComplete: () => {
|
|
7128
|
-
if (!isSheet && !splitOpened) setSplitOpened(true);
|
|
7129
|
-
},
|
|
7130
|
-
children: [
|
|
7131
|
-
!isSheet && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7132
|
-
"div",
|
|
7133
|
-
{
|
|
7134
|
-
className: "payman-v2-pdf-sheet-resize-handle",
|
|
7135
|
-
onMouseDown: onResizeMouseDown,
|
|
7136
|
-
"aria-hidden": "true",
|
|
7137
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-pdf-sheet-resize-grip" })
|
|
7138
|
-
}
|
|
7139
|
-
),
|
|
7140
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-pdf-sheet-header", children: [
|
|
7141
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-pdf-sheet-header-left", children: [
|
|
7142
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-pdf-sheet-file-icon", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { size: 14, strokeWidth: 1.75 }) }),
|
|
7143
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-pdf-sheet-title", title, children: title || "Document" })
|
|
7144
|
-
] }),
|
|
7145
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-pdf-sheet-header-actions", children: [
|
|
7146
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7147
|
-
"button",
|
|
7148
|
-
{
|
|
7149
|
-
type: "button",
|
|
7150
|
-
className: "payman-v2-pdf-sheet-download-btn",
|
|
7151
|
-
"aria-label": "Download PDF",
|
|
7152
|
-
disabled: !canDownload || isDownloading,
|
|
7153
|
-
onClick: () => void handleDownload(),
|
|
7154
|
-
children: [
|
|
7155
|
-
isDownloading ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 13, strokeWidth: 2, style: { animation: "payman-v2-spin 0.65s linear infinite" } }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { size: 13, strokeWidth: 2 }),
|
|
7156
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: isDownloading ? "Downloading\u2026" : "Download" })
|
|
7157
|
-
]
|
|
7158
|
-
}
|
|
7159
|
-
),
|
|
7160
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7161
|
-
"button",
|
|
7162
|
-
{
|
|
7163
|
-
type: "button",
|
|
7164
|
-
className: "payman-v2-pdf-sheet-close-btn",
|
|
7165
|
-
"aria-label": "Close preview",
|
|
7166
|
-
onClick: (e) => {
|
|
7167
|
-
e.stopPropagation();
|
|
7168
|
-
onClose();
|
|
7169
|
-
},
|
|
7170
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 15, strokeWidth: 2.25 })
|
|
7171
|
-
}
|
|
7172
|
-
)
|
|
7173
|
-
] })
|
|
7174
|
-
] }),
|
|
7175
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-pdf-sheet-body", children: previewError ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-pdf-sheet-error", role: "alert", children: [
|
|
7176
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-pdf-sheet-error-icon", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 22, strokeWidth: 1.75 }) }),
|
|
7177
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-pdf-sheet-error-title", children: previewError.title }),
|
|
7178
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-pdf-sheet-error-message", children: previewError.userMessage }),
|
|
7179
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-pdf-sheet-error-actions", children: [
|
|
7180
|
-
previewError.kind === "network" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7181
|
-
"button",
|
|
7182
|
-
{
|
|
7183
|
-
type: "button",
|
|
7184
|
-
className: "payman-v2-pdf-sheet-error-btn",
|
|
7185
|
-
onClick: handleRetry,
|
|
7186
|
-
children: [
|
|
7187
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { size: 14, strokeWidth: 2 }),
|
|
7188
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Try again" })
|
|
7189
|
-
]
|
|
7190
|
-
}
|
|
7191
|
-
),
|
|
7192
|
-
(previewError.kind === "network" || previewError.kind === "unknown") && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7193
|
-
"button",
|
|
7194
|
-
{
|
|
7195
|
-
type: "button",
|
|
7196
|
-
className: "payman-v2-pdf-sheet-error-btn payman-v2-pdf-sheet-error-btn-secondary",
|
|
7197
|
-
onClick: handleOpenInNewTab,
|
|
7198
|
-
children: [
|
|
7199
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 14, strokeWidth: 2 }),
|
|
7200
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Open link" })
|
|
7201
|
-
]
|
|
7202
|
-
}
|
|
7203
|
-
)
|
|
7204
|
-
] })
|
|
7205
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7206
|
-
(!isLoaded || !previewUrl) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-pdf-sheet-loading", children: [
|
|
7207
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7208
|
-
lucideReact.Loader2,
|
|
7209
|
-
{
|
|
7210
|
-
size: 20,
|
|
7211
|
-
strokeWidth: 2,
|
|
7212
|
-
style: { animation: "payman-v2-spin 0.65s linear infinite", color: "var(--payman-v2-text-3)" }
|
|
7213
|
-
}
|
|
7214
|
-
),
|
|
7215
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-pdf-sheet-loading-text", children: previewUrl ? "Preparing preview\u2026" : "Opening document\u2026" })
|
|
7216
|
-
] }),
|
|
7217
|
-
previewUrl && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7218
|
-
"iframe",
|
|
7219
|
-
{
|
|
7220
|
-
src: previewUrl,
|
|
7221
|
-
title: title || "PDF Preview",
|
|
7222
|
-
className: "payman-v2-pdf-sheet-iframe",
|
|
7223
|
-
style: {
|
|
7224
|
-
opacity: isLoaded ? 1 : 0,
|
|
7225
|
-
transition: "opacity 0.3s ease",
|
|
7226
|
-
pointerEvents: isDragging ? "none" : "auto"
|
|
7227
|
-
},
|
|
7228
|
-
onLoad: () => setIsLoaded(true)
|
|
7229
|
-
},
|
|
7230
|
-
previewUrl
|
|
7231
|
-
)
|
|
7232
|
-
] }) })
|
|
7233
|
-
]
|
|
7234
|
-
}
|
|
7235
|
-
);
|
|
7236
|
-
}
|
|
7237
6005
|
var DEFAULT_USER_ACTION_STATE = {
|
|
7238
6006
|
prompts: [],
|
|
7239
6007
|
notifications: []
|
|
@@ -7328,8 +6096,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
7328
6096
|
onLoadMoreMessages,
|
|
7329
6097
|
isLoadingMoreMessages = false,
|
|
7330
6098
|
hasMoreMessages = false,
|
|
7331
|
-
chat
|
|
7332
|
-
attachmentUpload
|
|
6099
|
+
chat
|
|
7333
6100
|
}, ref) {
|
|
7334
6101
|
const [inputValue, setInputValue] = react.useState("");
|
|
7335
6102
|
const prevInputValueRef = react.useRef(inputValue);
|
|
@@ -7383,6 +6150,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
7383
6150
|
const submitUserAction2 = chat.submitUserAction ?? NOOP_ASYNC;
|
|
7384
6151
|
const cancelUserAction2 = chat.cancelUserAction ?? NOOP_ASYNC;
|
|
7385
6152
|
const resendUserAction2 = chat.resendUserAction ?? NOOP_ASYNC;
|
|
6153
|
+
const expireUserAction2 = chat.expireUserAction ?? NOOP_ASYNC;
|
|
7386
6154
|
const dismissNotification = chat.dismissNotification ?? NOOP;
|
|
7387
6155
|
const isUserActionSupported = typeof chat.submitUserAction === "function" && typeof chat.cancelUserAction === "function" && typeof chat.resendUserAction === "function";
|
|
7388
6156
|
const {
|
|
@@ -7408,19 +6176,6 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
7408
6176
|
}
|
|
7409
6177
|
}
|
|
7410
6178
|
);
|
|
7411
|
-
const [pdfSheet, setPdfSheet] = react.useState(null);
|
|
7412
|
-
const autoOpenedPdfHrefsRef = react.useRef(/* @__PURE__ */ new Set());
|
|
7413
|
-
const pdfPreviewMode = config.pdfPreviewMode ?? "split";
|
|
7414
|
-
const openPdfSheet = react.useCallback((href, title, options) => {
|
|
7415
|
-
if (options?.auto) {
|
|
7416
|
-
if (autoOpenedPdfHrefsRef.current.has(href)) return;
|
|
7417
|
-
autoOpenedPdfHrefsRef.current.add(href);
|
|
7418
|
-
}
|
|
7419
|
-
setPdfSheet({ href, title });
|
|
7420
|
-
}, []);
|
|
7421
|
-
const closePdfSheet = react.useCallback(() => {
|
|
7422
|
-
setPdfSheet(null);
|
|
7423
|
-
}, []);
|
|
7424
6179
|
const contextValue = react.useMemo(
|
|
7425
6180
|
() => ({
|
|
7426
6181
|
resetSession,
|
|
@@ -7429,8 +6184,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
7429
6184
|
cancelStream,
|
|
7430
6185
|
getSessionId,
|
|
7431
6186
|
getMessages,
|
|
7432
|
-
isWaitingForResponse
|
|
7433
|
-
openPdfSheet
|
|
6187
|
+
isWaitingForResponse
|
|
7434
6188
|
}),
|
|
7435
6189
|
[
|
|
7436
6190
|
resetSession,
|
|
@@ -7439,8 +6193,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
7439
6193
|
cancelStream,
|
|
7440
6194
|
getSessionId,
|
|
7441
6195
|
getMessages,
|
|
7442
|
-
isWaitingForResponse
|
|
7443
|
-
openPdfSheet
|
|
6196
|
+
isWaitingForResponse
|
|
7444
6197
|
]
|
|
7445
6198
|
);
|
|
7446
6199
|
const {
|
|
@@ -7496,10 +6249,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
7496
6249
|
setInputValue("");
|
|
7497
6250
|
setLightboxSrc(null);
|
|
7498
6251
|
setLightboxAlt("");
|
|
7499
|
-
setPdfSheet(null);
|
|
7500
|
-
autoOpenedPdfHrefsRef.current.clear();
|
|
7501
6252
|
chatInputV2Ref.current?.setDraft("");
|
|
7502
|
-
chatInputV2Ref.current?.clearAttachments();
|
|
7503
6253
|
clearTranscript();
|
|
7504
6254
|
if (isRecording) {
|
|
7505
6255
|
stopRecording();
|
|
@@ -7550,20 +6300,14 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
7550
6300
|
emptyStateComponent,
|
|
7551
6301
|
showResetSession = false,
|
|
7552
6302
|
enableDeepModeToggle = true,
|
|
6303
|
+
showAttachmentButton = true,
|
|
6304
|
+
showUploadImageButton = true,
|
|
6305
|
+
showAttachFileButton = true,
|
|
7553
6306
|
messageActions: messageActionsConfig,
|
|
7554
6307
|
enableSlashCommands = true,
|
|
7555
6308
|
slashCommands: slashCommandsConfig,
|
|
7556
6309
|
commandPermissions
|
|
7557
6310
|
} = config;
|
|
7558
|
-
const attachmentSettings = react.useMemo(
|
|
7559
|
-
() => resolveChatAttachmentConfig(config),
|
|
7560
|
-
[
|
|
7561
|
-
config.attachments,
|
|
7562
|
-
config.showAttachmentButton,
|
|
7563
|
-
config.showUploadImageButton,
|
|
7564
|
-
config.showAttachFileButton
|
|
7565
|
-
]
|
|
7566
|
-
);
|
|
7567
6311
|
const messageActions = react.useMemo(
|
|
7568
6312
|
() => ({
|
|
7569
6313
|
userMessageActions: {
|
|
@@ -7651,22 +6395,11 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
7651
6395
|
};
|
|
7652
6396
|
const userActionPrompts = isUserActionSupported ? userActionState.prompts : void 0;
|
|
7653
6397
|
const notifications = userActionState.notifications;
|
|
7654
|
-
const
|
|
7655
|
-
(attachments) => {
|
|
7656
|
-
attachmentUpload.syncAttachments(attachments);
|
|
7657
|
-
},
|
|
7658
|
-
[attachmentUpload]
|
|
7659
|
-
);
|
|
7660
|
-
const handleV2Send = (text, files = [], attachments = []) => {
|
|
6398
|
+
const handleV2Send = (text) => {
|
|
7661
6399
|
if (isRecording) stopRecording();
|
|
7662
|
-
if (
|
|
7663
|
-
if (files.length > 0 && attachments.length === 0) return;
|
|
6400
|
+
if (text.trim() && !disableInput && isSessionParamsConfigured) {
|
|
7664
6401
|
setEditingMessageId(null);
|
|
7665
|
-
void sendMessage(text.trim(), {
|
|
7666
|
-
analysisMode: effectiveAnalysisMode,
|
|
7667
|
-
attachments,
|
|
7668
|
-
files
|
|
7669
|
-
});
|
|
6402
|
+
void sendMessage(text.trim(), { analysisMode: effectiveAnalysisMode });
|
|
7670
6403
|
}
|
|
7671
6404
|
};
|
|
7672
6405
|
const handleVoicePress = react.useCallback(async () => {
|
|
@@ -7714,214 +6447,156 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
|
|
|
7714
6447
|
style,
|
|
7715
6448
|
children: [
|
|
7716
6449
|
children,
|
|
7717
|
-
/* @__PURE__ */ jsxRuntime.
|
|
7718
|
-
|
|
6450
|
+
/* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: isEmpty && !hasEverSentMessage ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
6451
|
+
framerMotion.motion.div,
|
|
7719
6452
|
{
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
initial: { opacity: 1 },
|
|
7729
|
-
exit: { opacity: 0 },
|
|
7730
|
-
transition: { duration: 0.3 },
|
|
7731
|
-
className: "payman-v2-chat-layout",
|
|
7732
|
-
style: { justifyContent: "center", alignItems: "center" },
|
|
7733
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", flex: 1, width: "100%" }, children: [
|
|
7734
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7735
|
-
MessageList,
|
|
7736
|
-
{
|
|
7737
|
-
messages,
|
|
7738
|
-
isLoading: false,
|
|
7739
|
-
emptyStateText,
|
|
7740
|
-
showEmptyStateIcon,
|
|
7741
|
-
emptyStateComponent,
|
|
7742
|
-
layout,
|
|
7743
|
-
showTimestamps,
|
|
7744
|
-
stage: config.stage || "DEVELOPMENT",
|
|
7745
|
-
animated,
|
|
7746
|
-
showAgentName,
|
|
7747
|
-
agentName,
|
|
7748
|
-
showAvatars,
|
|
7749
|
-
showUserAvatar,
|
|
7750
|
-
showAssistantAvatar,
|
|
7751
|
-
showExecutionSteps,
|
|
7752
|
-
showStreamingDot,
|
|
7753
|
-
streamingStepsText,
|
|
7754
|
-
completedStepsText,
|
|
7755
|
-
onExecutionTraceClick,
|
|
7756
|
-
onLoadMoreMessages,
|
|
7757
|
-
isLoadingMoreMessages,
|
|
7758
|
-
hasMoreMessages
|
|
7759
|
-
}
|
|
7760
|
-
),
|
|
7761
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7762
|
-
framerMotion.motion.div,
|
|
7763
|
-
{
|
|
7764
|
-
initial: { opacity: 0, y: 12 },
|
|
7765
|
-
animate: { opacity: 1, y: 0 },
|
|
7766
|
-
transition: { delay: 0.2, duration: 0.4, ease: [0.25, 0.46, 0.45, 0.94] },
|
|
7767
|
-
style: { width: "100%" },
|
|
7768
|
-
children: hasAskPermission && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7769
|
-
ChatInputV2,
|
|
7770
|
-
{
|
|
7771
|
-
ref: chatInputV2Ref,
|
|
7772
|
-
onSend: handleV2Send,
|
|
7773
|
-
onCancel: cancelStream,
|
|
7774
|
-
disabled: isV2InputDisabled,
|
|
7775
|
-
isStreaming: isWaitingForResponse,
|
|
7776
|
-
isUploadingAttachments: attachmentUpload.isUploading,
|
|
7777
|
-
attachmentsReady: attachmentUpload.allReady,
|
|
7778
|
-
hasAttachmentUploadErrors: attachmentUpload.hasErrors,
|
|
7779
|
-
attachmentUploadStatusById: attachmentUpload.statusById,
|
|
7780
|
-
uploadedAttachmentPayloads: attachmentUpload.payloads,
|
|
7781
|
-
onAttachmentsChange: handleAttachmentsChange,
|
|
7782
|
-
placeholder: isRecording ? "Listening..." : placeholder,
|
|
7783
|
-
enableVoice: config.enableVoice === true,
|
|
7784
|
-
transcribedText: config.enableVoice === true ? transcribedText : "",
|
|
7785
|
-
voiceAvailable: config.enableVoice === true && voiceAvailable,
|
|
7786
|
-
isRecording,
|
|
7787
|
-
onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
|
|
7788
|
-
onCancelRecording: handleCancelRecording,
|
|
7789
|
-
onConfirmRecording: handleConfirmRecording,
|
|
7790
|
-
showResetSession,
|
|
7791
|
-
onResetSession: requestResetSession,
|
|
7792
|
-
showAttachmentButton: attachmentSettings.showAttachmentButton,
|
|
7793
|
-
showUploadImageButton: attachmentSettings.showUploadImageButton,
|
|
7794
|
-
showAttachFileButton: attachmentSettings.showAttachFileButton,
|
|
7795
|
-
allowedImageExtensions: attachmentSettings.allowedImageExtensions,
|
|
7796
|
-
allowedFileExtensions: attachmentSettings.allowedFileExtensions,
|
|
7797
|
-
maxCount: attachmentSettings.maxCount,
|
|
7798
|
-
maxFileBytes: attachmentSettings.maxFileBytes,
|
|
7799
|
-
maxTotalBytes: attachmentSettings.maxTotalBytes,
|
|
7800
|
-
onUploadImageClick,
|
|
7801
|
-
onAttachFileClick,
|
|
7802
|
-
editingMessageId,
|
|
7803
|
-
onClearEditing: handleClearEditing,
|
|
7804
|
-
analysisMode: enableDeepModeToggle ? analysisMode : void 0,
|
|
7805
|
-
onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
|
|
7806
|
-
slashCommands
|
|
7807
|
-
}
|
|
7808
|
-
)
|
|
7809
|
-
}
|
|
7810
|
-
)
|
|
7811
|
-
] })
|
|
7812
|
-
},
|
|
7813
|
-
"v2-empty"
|
|
7814
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7815
|
-
framerMotion.motion.div,
|
|
7816
|
-
{
|
|
7817
|
-
initial: hasEverSentMessage ? { opacity: 0 } : false,
|
|
7818
|
-
animate: { opacity: 1 },
|
|
7819
|
-
transition: { duration: 0.3 },
|
|
7820
|
-
className: "payman-v2-chat-layout",
|
|
7821
|
-
children: [
|
|
7822
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7823
|
-
MessageListV2,
|
|
7824
|
-
{
|
|
7825
|
-
ref: messageListV2Ref,
|
|
7826
|
-
messages,
|
|
7827
|
-
isStreaming: isWaitingForResponse,
|
|
7828
|
-
sidePanelOpen: !!pdfSheet,
|
|
7829
|
-
onEditUserMessage: handleEditMessageDraft,
|
|
7830
|
-
onRetryUserMessage: handleRetryUserMessage,
|
|
7831
|
-
onImageClick: handleImageClick,
|
|
7832
|
-
onExecutionTraceClick,
|
|
7833
|
-
messageActions,
|
|
7834
|
-
retryDisabled: isWaitingForResponse,
|
|
7835
|
-
typingSpeed: config.typingSpeed ?? 4,
|
|
7836
|
-
userActionPrompts,
|
|
7837
|
-
notifications,
|
|
7838
|
-
onSubmitUserAction: isUserActionSupported ? submitUserAction2 : void 0,
|
|
7839
|
-
onCancelUserAction: isUserActionSupported ? cancelUserAction2 : void 0,
|
|
7840
|
-
onResendUserAction: isUserActionSupported ? resendUserAction2 : void 0,
|
|
7841
|
-
onDismissNotification: dismissNotification,
|
|
7842
|
-
onSubmitFeedback: handleSubmitFeedback
|
|
7843
|
-
}
|
|
7844
|
-
),
|
|
7845
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7846
|
-
StreamingIndicatorV2,
|
|
7847
|
-
{
|
|
7848
|
-
isStreaming: isWaitingForResponse,
|
|
7849
|
-
loadingAnimation: config.loadingAnimation
|
|
7850
|
-
}
|
|
7851
|
-
),
|
|
7852
|
-
hasAskPermission && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7853
|
-
ChatInputV2,
|
|
7854
|
-
{
|
|
7855
|
-
ref: chatInputV2Ref,
|
|
7856
|
-
onSend: handleV2Send,
|
|
7857
|
-
onCancel: cancelStream,
|
|
7858
|
-
disabled: isV2InputDisabled,
|
|
7859
|
-
isStreaming: isWaitingForResponse,
|
|
7860
|
-
isUploadingAttachments: attachmentUpload.isUploading,
|
|
7861
|
-
attachmentsReady: attachmentUpload.allReady,
|
|
7862
|
-
hasAttachmentUploadErrors: attachmentUpload.hasErrors,
|
|
7863
|
-
attachmentUploadStatusById: attachmentUpload.statusById,
|
|
7864
|
-
uploadedAttachmentPayloads: attachmentUpload.payloads,
|
|
7865
|
-
onAttachmentsChange: handleAttachmentsChange,
|
|
7866
|
-
placeholder: isRecording ? "Listening..." : placeholder,
|
|
7867
|
-
enableVoice: config.enableVoice === true,
|
|
7868
|
-
transcribedText: config.enableVoice === true ? transcribedText : "",
|
|
7869
|
-
voiceAvailable: config.enableVoice === true && voiceAvailable,
|
|
7870
|
-
isRecording,
|
|
7871
|
-
onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
|
|
7872
|
-
onCancelRecording: handleCancelRecording,
|
|
7873
|
-
onConfirmRecording: handleConfirmRecording,
|
|
7874
|
-
showResetSession,
|
|
7875
|
-
onResetSession: requestResetSession,
|
|
7876
|
-
showAttachmentButton: attachmentSettings.showAttachmentButton,
|
|
7877
|
-
showUploadImageButton: attachmentSettings.showUploadImageButton,
|
|
7878
|
-
showAttachFileButton: attachmentSettings.showAttachFileButton,
|
|
7879
|
-
allowedImageExtensions: attachmentSettings.allowedImageExtensions,
|
|
7880
|
-
allowedFileExtensions: attachmentSettings.allowedFileExtensions,
|
|
7881
|
-
maxCount: attachmentSettings.maxCount,
|
|
7882
|
-
maxFileBytes: attachmentSettings.maxFileBytes,
|
|
7883
|
-
maxTotalBytes: attachmentSettings.maxTotalBytes,
|
|
7884
|
-
onUploadImageClick,
|
|
7885
|
-
onAttachFileClick,
|
|
7886
|
-
editingMessageId,
|
|
7887
|
-
onClearEditing: handleClearEditing,
|
|
7888
|
-
analysisMode: enableDeepModeToggle ? analysisMode : void 0,
|
|
7889
|
-
onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
|
|
7890
|
-
slashCommands
|
|
7891
|
-
}
|
|
7892
|
-
)
|
|
7893
|
-
]
|
|
7894
|
-
},
|
|
7895
|
-
"v2-chat"
|
|
7896
|
-
) }) }),
|
|
7897
|
-
pdfPreviewMode === "split" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7898
|
-
PdfSheetV2,
|
|
6453
|
+
initial: { opacity: 1 },
|
|
6454
|
+
exit: { opacity: 0 },
|
|
6455
|
+
transition: { duration: 0.3 },
|
|
6456
|
+
className: "payman-v2-chat-layout",
|
|
6457
|
+
style: { justifyContent: "center", alignItems: "center" },
|
|
6458
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", flex: 1, width: "100%" }, children: [
|
|
6459
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6460
|
+
MessageList,
|
|
7899
6461
|
{
|
|
7900
|
-
|
|
7901
|
-
|
|
7902
|
-
|
|
7903
|
-
|
|
6462
|
+
messages,
|
|
6463
|
+
isLoading: false,
|
|
6464
|
+
emptyStateText,
|
|
6465
|
+
showEmptyStateIcon,
|
|
6466
|
+
emptyStateComponent,
|
|
6467
|
+
layout,
|
|
6468
|
+
showTimestamps,
|
|
6469
|
+
stage: config.stage || "DEVELOPMENT",
|
|
6470
|
+
animated,
|
|
6471
|
+
showAgentName,
|
|
6472
|
+
agentName,
|
|
6473
|
+
showAvatars,
|
|
6474
|
+
showUserAvatar,
|
|
6475
|
+
showAssistantAvatar,
|
|
6476
|
+
showExecutionSteps,
|
|
6477
|
+
showStreamingDot,
|
|
6478
|
+
streamingStepsText,
|
|
6479
|
+
completedStepsText,
|
|
6480
|
+
onExecutionTraceClick,
|
|
6481
|
+
onLoadMoreMessages,
|
|
6482
|
+
isLoadingMoreMessages,
|
|
6483
|
+
hasMoreMessages
|
|
7904
6484
|
}
|
|
7905
6485
|
),
|
|
7906
|
-
|
|
7907
|
-
|
|
6486
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6487
|
+
framerMotion.motion.div,
|
|
7908
6488
|
{
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
6489
|
+
initial: { opacity: 0, y: 12 },
|
|
6490
|
+
animate: { opacity: 1, y: 0 },
|
|
6491
|
+
transition: { delay: 0.2, duration: 0.4, ease: [0.25, 0.46, 0.45, 0.94] },
|
|
6492
|
+
style: { width: "100%" },
|
|
6493
|
+
children: hasAskPermission && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6494
|
+
ChatInputV2,
|
|
7913
6495
|
{
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
6496
|
+
ref: chatInputV2Ref,
|
|
6497
|
+
onSend: handleV2Send,
|
|
6498
|
+
onCancel: cancelStream,
|
|
6499
|
+
disabled: isV2InputDisabled,
|
|
6500
|
+
isStreaming: isWaitingForResponse,
|
|
6501
|
+
placeholder: isRecording ? "Listening..." : placeholder,
|
|
6502
|
+
enableVoice: config.enableVoice === true,
|
|
6503
|
+
transcribedText: config.enableVoice === true ? transcribedText : "",
|
|
6504
|
+
voiceAvailable: config.enableVoice === true && voiceAvailable,
|
|
6505
|
+
isRecording,
|
|
6506
|
+
onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
|
|
6507
|
+
onCancelRecording: handleCancelRecording,
|
|
6508
|
+
onConfirmRecording: handleConfirmRecording,
|
|
6509
|
+
showResetSession,
|
|
6510
|
+
onResetSession: requestResetSession,
|
|
6511
|
+
showAttachmentButton,
|
|
6512
|
+
showUploadImageButton,
|
|
6513
|
+
showAttachFileButton,
|
|
6514
|
+
onUploadImageClick,
|
|
6515
|
+
onAttachFileClick,
|
|
6516
|
+
editingMessageId,
|
|
6517
|
+
onClearEditing: handleClearEditing,
|
|
6518
|
+
analysisMode: enableDeepModeToggle ? analysisMode : void 0,
|
|
6519
|
+
onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
|
|
6520
|
+
slashCommands
|
|
7918
6521
|
}
|
|
7919
6522
|
)
|
|
7920
6523
|
}
|
|
7921
6524
|
)
|
|
6525
|
+
] })
|
|
6526
|
+
},
|
|
6527
|
+
"v2-empty"
|
|
6528
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6529
|
+
framerMotion.motion.div,
|
|
6530
|
+
{
|
|
6531
|
+
initial: hasEverSentMessage ? { opacity: 0 } : false,
|
|
6532
|
+
animate: { opacity: 1 },
|
|
6533
|
+
transition: { duration: 0.3 },
|
|
6534
|
+
className: "payman-v2-chat-layout",
|
|
6535
|
+
children: [
|
|
6536
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6537
|
+
MessageListV2,
|
|
6538
|
+
{
|
|
6539
|
+
ref: messageListV2Ref,
|
|
6540
|
+
messages,
|
|
6541
|
+
isStreaming: isWaitingForResponse,
|
|
6542
|
+
onEditUserMessage: handleEditMessageDraft,
|
|
6543
|
+
onRetryUserMessage: handleRetryUserMessage,
|
|
6544
|
+
onImageClick: handleImageClick,
|
|
6545
|
+
onExecutionTraceClick,
|
|
6546
|
+
messageActions,
|
|
6547
|
+
retryDisabled: isWaitingForResponse,
|
|
6548
|
+
typingSpeed: config.typingSpeed ?? 4,
|
|
6549
|
+
userActionPrompts,
|
|
6550
|
+
notifications,
|
|
6551
|
+
onSubmitUserAction: isUserActionSupported ? submitUserAction2 : void 0,
|
|
6552
|
+
onCancelUserAction: isUserActionSupported ? cancelUserAction2 : void 0,
|
|
6553
|
+
onResendUserAction: isUserActionSupported ? resendUserAction2 : void 0,
|
|
6554
|
+
onExpireUserAction: isUserActionSupported ? expireUserAction2 : void 0,
|
|
6555
|
+
onDismissNotification: dismissNotification,
|
|
6556
|
+
onSubmitFeedback: handleSubmitFeedback
|
|
6557
|
+
}
|
|
6558
|
+
),
|
|
6559
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6560
|
+
StreamingIndicatorV2,
|
|
6561
|
+
{
|
|
6562
|
+
isStreaming: isWaitingForResponse,
|
|
6563
|
+
loadingAnimation: config.loadingAnimation
|
|
6564
|
+
}
|
|
6565
|
+
),
|
|
6566
|
+
hasAskPermission && /* @__PURE__ */ jsxRuntime.jsx(
|
|
6567
|
+
ChatInputV2,
|
|
6568
|
+
{
|
|
6569
|
+
ref: chatInputV2Ref,
|
|
6570
|
+
onSend: handleV2Send,
|
|
6571
|
+
onCancel: cancelStream,
|
|
6572
|
+
disabled: isV2InputDisabled,
|
|
6573
|
+
isStreaming: isWaitingForResponse,
|
|
6574
|
+
placeholder: isRecording ? "Listening..." : placeholder,
|
|
6575
|
+
enableVoice: config.enableVoice === true,
|
|
6576
|
+
transcribedText: config.enableVoice === true ? transcribedText : "",
|
|
6577
|
+
voiceAvailable: config.enableVoice === true && voiceAvailable,
|
|
6578
|
+
isRecording,
|
|
6579
|
+
onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
|
|
6580
|
+
onCancelRecording: handleCancelRecording,
|
|
6581
|
+
onConfirmRecording: handleConfirmRecording,
|
|
6582
|
+
showResetSession,
|
|
6583
|
+
onResetSession: requestResetSession,
|
|
6584
|
+
showAttachmentButton,
|
|
6585
|
+
showUploadImageButton,
|
|
6586
|
+
showAttachFileButton,
|
|
6587
|
+
onUploadImageClick,
|
|
6588
|
+
onAttachFileClick,
|
|
6589
|
+
editingMessageId,
|
|
6590
|
+
onClearEditing: handleClearEditing,
|
|
6591
|
+
analysisMode: enableDeepModeToggle ? analysisMode : void 0,
|
|
6592
|
+
onAnalysisModeChange: enableDeepModeToggle ? setAnalysisMode : void 0,
|
|
6593
|
+
slashCommands
|
|
6594
|
+
}
|
|
6595
|
+
)
|
|
7922
6596
|
]
|
|
7923
|
-
}
|
|
7924
|
-
|
|
6597
|
+
},
|
|
6598
|
+
"v2-chat"
|
|
6599
|
+
) }),
|
|
7925
6600
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7926
6601
|
ImageLightboxV2,
|
|
7927
6602
|
{
|
|
@@ -7956,39 +6631,19 @@ var PaymanChat = react.forwardRef(
|
|
|
7956
6631
|
function PaymanChat2(props, ref) {
|
|
7957
6632
|
const mergedCallbacks = useSentryChatCallbacks(props.callbacks, props.config);
|
|
7958
6633
|
const chat = useChatV2(props.config, mergedCallbacks);
|
|
7959
|
-
|
|
7960
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7961
|
-
PaymanChatInner,
|
|
7962
|
-
{
|
|
7963
|
-
...props,
|
|
7964
|
-
chat,
|
|
7965
|
-
attachmentUpload,
|
|
7966
|
-
ref
|
|
7967
|
-
}
|
|
7968
|
-
);
|
|
6634
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PaymanChatInner, { ...props, chat, ref });
|
|
7969
6635
|
}
|
|
7970
6636
|
);
|
|
7971
6637
|
|
|
7972
6638
|
exports.PaymanChat = PaymanChat;
|
|
7973
6639
|
exports.PaymanChatContext = PaymanChatContext;
|
|
7974
|
-
exports.PdfSheetV2 = PdfSheetV2;
|
|
7975
6640
|
exports.UserActionStaleError = UserActionStaleError;
|
|
7976
|
-
exports.buildSignedUrlEndpoint = buildSignedUrlEndpoint;
|
|
7977
6641
|
exports.cancelUserAction = cancelUserAction;
|
|
7978
6642
|
exports.captureSentryError = captureSentryError;
|
|
7979
6643
|
exports.cn = cn;
|
|
7980
|
-
exports.formatAttachmentBytes = formatAttachmentBytes;
|
|
7981
6644
|
exports.formatDate = formatDate;
|
|
7982
|
-
exports.getPdfTitleFromUrl = getPdfTitleFromUrl;
|
|
7983
|
-
exports.isPdfUrl = isPdfUrl;
|
|
7984
|
-
exports.mapExecutionHistoryPageToChatMessages = mapExecutionHistoryPageToChatMessages;
|
|
7985
|
-
exports.mapExecutionHistoryToChatMessages = mapExecutionHistoryToChatMessages;
|
|
7986
6645
|
exports.resendUserAction = resendUserAction;
|
|
7987
|
-
exports.stripAttachmentsSuffixFromIntent = stripAttachmentsSuffixFromIntent;
|
|
7988
6646
|
exports.submitUserAction = submitUserAction;
|
|
7989
|
-
exports.uploadAttachment = uploadAttachment;
|
|
7990
|
-
exports.uploadAttachments = uploadAttachments;
|
|
7991
|
-
exports.useAttachmentUpload = useAttachmentUpload;
|
|
7992
6647
|
exports.useChatV2 = useChatV2;
|
|
7993
6648
|
exports.usePaymanChat = usePaymanChat;
|
|
7994
6649
|
exports.useVoice = useVoice;
|