@paymanai/payman-ask-sdk 4.0.21 → 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.mjs CHANGED
@@ -709,8 +709,7 @@ function buildRequestBody(config, userMessage, sessionId, options) {
709
709
  sessionAttributes,
710
710
  analysisMode: options?.analysisMode,
711
711
  locale: resolveLocale(config.locale),
712
- timezone: resolveTimezone(config.timezone),
713
- ...options?.attachments?.length ? { attachments: options.attachments } : {}
712
+ timezone: resolveTimezone(config.timezone)
714
713
  };
715
714
  }
716
715
  function resolveLocale(configured) {
@@ -755,7 +754,6 @@ function buildResolveImagesUrl(config) {
755
754
  const basePath = normalizedEndpointPath.endsWith("/stream") ? normalizedEndpointPath.slice(0, -"/stream".length) : normalizedEndpointPath;
756
755
  return `${config.api.baseUrl}${basePath}/resolve-image-urls`;
757
756
  }
758
- var NGROK_SKIP_BROWSER_WARNING = "ngrok-skip-browser-warning";
759
757
  function buildRequestHeaders(config) {
760
758
  const headers = {
761
759
  ...config.api.headers
@@ -763,9 +761,6 @@ function buildRequestHeaders(config) {
763
761
  if (config.api.authToken) {
764
762
  headers.Authorization = `Bearer ${config.api.authToken}`;
765
763
  }
766
- if (!headers[NGROK_SKIP_BROWSER_WARNING]) {
767
- headers[NGROK_SKIP_BROWSER_WARNING] = "true";
768
- }
769
764
  return headers;
770
765
  }
771
766
  var RAG_IMAGE_REGEX = /\/api\/rag\/chunks\/[^"'\s]+\/image/;
@@ -1046,81 +1041,6 @@ function createCancelledMessageUpdate(steps, currentMessage) {
1046
1041
  currentMessage: currentMessage || "Thinking..."
1047
1042
  };
1048
1043
  }
1049
- var DEFAULT_SIGNED_URL_ENDPOINT = "/api/files/signed-url";
1050
- function fileExtension(filename) {
1051
- const ext = filename.split(".").pop()?.toLowerCase().replace(/^\./, "");
1052
- return ext && ext.length > 0 ? ext : "bin";
1053
- }
1054
- function resolveMimeType(file) {
1055
- if (file.type && file.type.trim().length > 0) return file.type;
1056
- const ext = fileExtension(file.name);
1057
- const byExt = {
1058
- pdf: "application/pdf",
1059
- png: "image/png",
1060
- jpg: "image/jpeg",
1061
- jpeg: "image/jpeg",
1062
- gif: "image/gif",
1063
- webp: "image/webp"
1064
- };
1065
- return byExt[ext] ?? "application/octet-stream";
1066
- }
1067
- function buildSignedUrlEndpoint(config, ext) {
1068
- const endpoint = config.api.signedUrlEndpoint || DEFAULT_SIGNED_URL_ENDPOINT;
1069
- const queryParams = new URLSearchParams({ extn: ext.replace(/^\./, "") });
1070
- return `${config.api.baseUrl}${endpoint}?${queryParams.toString()}`;
1071
- }
1072
- async function requestSignedUrl(config, ext, signal) {
1073
- const url = buildSignedUrlEndpoint(config, ext);
1074
- const headers = buildRequestHeaders(config);
1075
- const response = await fetch(url, {
1076
- method: "GET",
1077
- headers,
1078
- signal
1079
- });
1080
- if (!response.ok) {
1081
- const errorText = await response.text().catch(() => "");
1082
- throw new Error(
1083
- errorText ? `Failed to get upload URL (${response.status}): ${errorText}` : `Failed to get upload URL (${response.status})`
1084
- );
1085
- }
1086
- const data = await response.json();
1087
- if (!data.key || !data.url) {
1088
- throw new Error("Signed URL response missing key or url");
1089
- }
1090
- return { key: data.key, url: data.url };
1091
- }
1092
- async function uploadToSignedUrl(signedUrl, file, mimeType, signal) {
1093
- const response = await fetch(signedUrl, {
1094
- method: "PUT",
1095
- headers: {
1096
- "Content-Type": mimeType,
1097
- "x-ms-blob-type": "BlockBlob"
1098
- },
1099
- body: file,
1100
- signal
1101
- });
1102
- if (!response.ok) {
1103
- const errorText = await response.text().catch(() => "");
1104
- throw new Error(
1105
- errorText ? `Failed to upload file (${response.status}): ${errorText}` : `Failed to upload file (${response.status})`
1106
- );
1107
- }
1108
- }
1109
- async function uploadAttachment(config, file, signal) {
1110
- const ext = fileExtension(file.name);
1111
- const mimeType = resolveMimeType(file);
1112
- const { key, url } = await requestSignedUrl(config, ext, signal);
1113
- await uploadToSignedUrl(url, file, mimeType, signal);
1114
- return {
1115
- tempKey: key,
1116
- filename: file.name,
1117
- mimeType
1118
- };
1119
- }
1120
- async function uploadAttachments(config, files, signal) {
1121
- const uploads = files.map((file) => uploadAttachment(config, file, signal));
1122
- return Promise.all(uploads);
1123
- }
1124
1044
  var UserActionStaleError = class extends Error {
1125
1045
  constructor(userActionId, message = "User action is no longer actionable") {
1126
1046
  super(message);
@@ -1157,6 +1077,9 @@ async function cancelUserAction(config, userActionId) {
1157
1077
  async function resendUserAction(config, userActionId) {
1158
1078
  return sendUserActionRequest(config, userActionId, "resend");
1159
1079
  }
1080
+ async function expireUserAction(config, userActionId) {
1081
+ return sendUserActionRequest(config, userActionId, "expired");
1082
+ }
1160
1083
  var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
1161
1084
  function upsertPrompt(prompts, req) {
1162
1085
  const active = { ...req, status: "pending" };
@@ -1185,32 +1108,12 @@ function getStoredOrInitialMessages(config) {
1185
1108
  function getSessionIdFromMessages(messages) {
1186
1109
  return messages.find((message) => message.sessionId)?.sessionId;
1187
1110
  }
1188
- var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "gif", "webp", "avif"]);
1189
- function attachmentKindFromFile(file) {
1190
- const ext = file.name.split(".").pop()?.toLowerCase() ?? "";
1191
- if (IMAGE_EXTENSIONS.has(ext) || file.type.startsWith("image/")) return "image";
1192
- return "file";
1193
- }
1194
- function buildMessageAttachments(files) {
1195
- return files.map((file, index) => {
1196
- const kind = attachmentKindFromFile(file);
1197
- return {
1198
- id: `att-${Date.now()}-${index}`,
1199
- filename: file.name,
1200
- mimeType: file.type || "application/octet-stream",
1201
- // Blob URL for all local files so PDFs/docs stay previewable after send.
1202
- previewUrl: URL.createObjectURL(file),
1203
- kind
1204
- };
1205
- });
1206
- }
1207
1111
  function useChatV2(config, callbacks = {}) {
1208
1112
  const [messages, setMessages] = useState(() => getStoredOrInitialMessages(config));
1209
1113
  const [isWaitingForResponse, setIsWaitingForResponse] = useState(() => {
1210
1114
  if (!config.userId) return false;
1211
1115
  return activeStreamStore.get(config.userId)?.isWaiting ?? false;
1212
1116
  });
1213
- const [isUploadingAttachments, setIsUploadingAttachments] = useState(false);
1214
1117
  const sessionIdRef = useRef(
1215
1118
  getSessionIdFromMessages(getStoredOrInitialMessages(config)) ?? config.initialSessionId ?? void 0
1216
1119
  );
@@ -1285,45 +1188,21 @@ function useChatV2(config, callbacks = {}) {
1285
1188
  );
1286
1189
  const sendMessage = useCallback(
1287
1190
  async (userMessage, options) => {
1288
- const trimmedMessage = userMessage.trim();
1289
- const files = options?.files ?? [];
1290
- const hasPreuploadedAttachments = (options?.attachments?.length ?? 0) > 0;
1291
- if (!trimmedMessage && files.length === 0 && !hasPreuploadedAttachments) return;
1292
- let streamAttachments = options?.attachments;
1293
- if (!streamAttachments && files.length > 0) {
1294
- setIsUploadingAttachments(true);
1295
- try {
1296
- streamAttachments = await uploadAttachments(configRef.current, files);
1297
- } catch (error) {
1298
- if (error.name !== "AbortError") {
1299
- callbacksRef.current.onError?.(error);
1300
- }
1301
- throw error;
1302
- } finally {
1303
- setIsUploadingAttachments(false);
1304
- }
1305
- }
1191
+ if (!userMessage.trim()) return;
1306
1192
  if (!sessionIdRef.current && configRef.current.autoGenerateSessionId !== false) {
1307
1193
  sessionIdRef.current = generateId();
1308
1194
  callbacksRef.current.onSessionIdChange?.(sessionIdRef.current);
1309
1195
  }
1310
- const messageAttachments = files.length > 0 ? buildMessageAttachments(files) : streamAttachments?.length ? streamAttachments.map((attachment, index) => ({
1311
- id: `att-${Date.now()}-${index}`,
1312
- filename: attachment.filename,
1313
- mimeType: attachment.mimeType,
1314
- kind: attachment.mimeType.startsWith("image/") ? "image" : "file"
1315
- })) : void 0;
1316
1196
  const userMessageId = `user-${Date.now()}`;
1317
1197
  const userMsg = {
1318
1198
  id: userMessageId,
1319
1199
  sessionId: sessionIdRef.current,
1320
1200
  role: "user",
1321
- content: trimmedMessage,
1322
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1323
- attachments: messageAttachments
1201
+ content: userMessage,
1202
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1324
1203
  };
1325
1204
  setMessages((prev) => [...prev, userMsg]);
1326
- callbacksRef.current.onMessageSent?.(trimmedMessage);
1205
+ callbacksRef.current.onMessageSent?.(userMessage);
1327
1206
  setIsWaitingForResponse(true);
1328
1207
  callbacksRef.current.onStreamStart?.();
1329
1208
  const streamingId = `assistant-${Date.now()}`;
@@ -1350,14 +1229,11 @@ function useChatV2(config, callbacks = {}) {
1350
1229
  activeStreamStore.start(userId, abortController, initialMessages);
1351
1230
  }
1352
1231
  const newSessionId = await startStream(
1353
- trimmedMessage,
1232
+ userMessage,
1354
1233
  streamingId,
1355
1234
  sessionIdRef.current,
1356
1235
  abortController,
1357
- {
1358
- analysisMode: options?.analysisMode,
1359
- attachments: streamAttachments
1360
- }
1236
+ options
1361
1237
  );
1362
1238
  const finalStreamUserId = streamUserIdRef.current ?? userId;
1363
1239
  if (finalStreamUserId) {
@@ -1495,6 +1371,19 @@ function useChatV2(config, callbacks = {}) {
1495
1371
  },
1496
1372
  [setPromptStatus]
1497
1373
  );
1374
+ const expireUserAction2 = useCallback(
1375
+ async (userActionId) => {
1376
+ setPromptStatus(userActionId, "expired");
1377
+ try {
1378
+ await expireUserAction(configRef.current, userActionId);
1379
+ } catch (error) {
1380
+ if (error instanceof UserActionStaleError) return;
1381
+ callbacksRef.current.onError?.(error);
1382
+ throw error;
1383
+ }
1384
+ },
1385
+ [setPromptStatus]
1386
+ );
1498
1387
  const dismissNotification = useCallback((id) => {
1499
1388
  setUserActionState((prev) => ({
1500
1389
  ...prev,
@@ -1535,18 +1424,6 @@ function useChatV2(config, callbacks = {}) {
1535
1424
  setMessages(config.initialMessages);
1536
1425
  sessionIdRef.current = getSessionIdFromMessages(config.initialMessages) ?? config.initialSessionId;
1537
1426
  }, [config.initialMessages, config.initialSessionId, config.userId]);
1538
- const hydratedSessionIdRef = useRef(void 0);
1539
- useEffect(() => {
1540
- if (config.userId) return;
1541
- if (!config.initialMessages?.length) return;
1542
- const sessionId = config.initialSessionId;
1543
- if (hydratedSessionIdRef.current === sessionId && messagesRef.current.length > 0) {
1544
- return;
1545
- }
1546
- hydratedSessionIdRef.current = sessionId;
1547
- setMessages(config.initialMessages);
1548
- sessionIdRef.current = getSessionIdFromMessages(config.initialMessages) ?? sessionId;
1549
- }, [config.initialMessages, config.initialSessionId, config.userId]);
1550
1427
  useEffect(() => {
1551
1428
  const prevUserId = prevUserIdRef.current;
1552
1429
  prevUserIdRef.current = config.userId;
@@ -1581,12 +1458,12 @@ function useChatV2(config, callbacks = {}) {
1581
1458
  getSessionId,
1582
1459
  getMessages,
1583
1460
  isWaitingForResponse,
1584
- isUploadingAttachments,
1585
1461
  sessionId: sessionIdRef.current,
1586
1462
  userActionState,
1587
1463
  submitUserAction: submitUserAction2,
1588
1464
  cancelUserAction: cancelUserAction2,
1589
1465
  resendUserAction: resendUserAction2,
1466
+ expireUserAction: expireUserAction2,
1590
1467
  dismissNotification
1591
1468
  };
1592
1469
  }
@@ -4668,18 +4545,28 @@ function useExpiryCountdown(prompt) {
4668
4545
  setSecondsLeft(void 0);
4669
4546
  return;
4670
4547
  }
4671
- setSecondsLeft(initial);
4672
- const id = window.setInterval(() => {
4673
- setSecondsLeft((s) => {
4674
- if (s === void 0) return s;
4675
- if (s <= 1) {
4676
- window.clearInterval(id);
4677
- return 0;
4678
- }
4679
- return s - 1;
4680
- });
4681
- }, 1e3);
4682
- return () => window.clearInterval(id);
4548
+ const deadlineMs = Date.now() + initial * 1e3;
4549
+ let intervalId;
4550
+ const remaining = () => Math.max(0, Math.ceil((deadlineMs - Date.now()) / 1e3));
4551
+ const sync = () => {
4552
+ const next = remaining();
4553
+ setSecondsLeft(next);
4554
+ if (next === 0 && intervalId !== void 0) {
4555
+ window.clearInterval(intervalId);
4556
+ intervalId = void 0;
4557
+ }
4558
+ };
4559
+ sync();
4560
+ intervalId = window.setInterval(sync, 1e3);
4561
+ document.addEventListener("visibilitychange", sync);
4562
+ window.addEventListener("focus", sync);
4563
+ window.addEventListener("pageshow", sync);
4564
+ return () => {
4565
+ if (intervalId !== void 0) window.clearInterval(intervalId);
4566
+ document.removeEventListener("visibilitychange", sync);
4567
+ window.removeEventListener("focus", sync);
4568
+ window.removeEventListener("pageshow", sync);
4569
+ };
4683
4570
  }, [prompt.userActionId, prompt.subAction, initial]);
4684
4571
  const expired = initial !== void 0 && secondsLeft === 0;
4685
4572
  return [secondsLeft, expired];
@@ -6236,7 +6123,7 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
6236
6123
  const submitUserAction2 = chat.submitUserAction ?? NOOP_ASYNC;
6237
6124
  const cancelUserAction2 = chat.cancelUserAction ?? NOOP_ASYNC;
6238
6125
  const resendUserAction2 = chat.resendUserAction ?? NOOP_ASYNC;
6239
- const expireUserAction = chat.expireUserAction ?? NOOP_ASYNC;
6126
+ const expireUserAction2 = chat.expireUserAction ?? NOOP_ASYNC;
6240
6127
  const dismissNotification = chat.dismissNotification ?? NOOP;
6241
6128
  const isUserActionSupported = typeof chat.submitUserAction === "function" && typeof chat.cancelUserAction === "function" && typeof chat.resendUserAction === "function";
6242
6129
  const {
@@ -6637,7 +6524,7 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
6637
6524
  onSubmitUserAction: isUserActionSupported ? submitUserAction2 : void 0,
6638
6525
  onCancelUserAction: isUserActionSupported ? cancelUserAction2 : void 0,
6639
6526
  onResendUserAction: isUserActionSupported ? resendUserAction2 : void 0,
6640
- onExpireUserAction: isUserActionSupported ? expireUserAction : void 0,
6527
+ onExpireUserAction: isUserActionSupported ? expireUserAction2 : void 0,
6641
6528
  onDismissNotification: dismissNotification,
6642
6529
  onSubmitFeedback: handleSubmitFeedback
6643
6530
  }