@paymanai/payman-ask-sdk 4.0.19 → 4.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import React__default from 'react';
3
3
  import { MessageDisplay, AgentStage, ChatCallbacks as ChatCallbacks$1, ChatConfig as ChatConfig$1, ActiveUserAction, UserNotification } from '@paymanai/payman-typescript-ask-sdk';
4
- export { APIConfig, ActiveUserAction, AgentStage, ChunkDisplay, JsonSchemaField, JsonSchemaOption, MessageDisplay, MessageRole, RequestedSchema, SessionParams, StreamProgress, StreamingStep, UseChatV2Return, UseVoiceReturn, UserActionKind, UserActionRequest, UserActionStaleError, UserActionState, UserActionStatus, UserActionSubAction, UserNotification, VerificationType, VoiceCallbacks, VoiceConfig, VoicePermissions, VoiceResult, VoiceState, cancelUserAction, expireUserAction, resendUserAction, submitUserAction, useChatV2, useVoice } from '@paymanai/payman-typescript-ask-sdk';
4
+ export { APIConfig, ActiveUserAction, AgentStage, ChunkDisplay, JsonSchemaField, JsonSchemaOption, MessageDisplay, MessageRole, RequestedSchema, SessionParams, StreamProgress, StreamingStep, UseChatV2Return, UseVoiceReturn, UserActionKind, UserActionRequest, UserActionStaleError, UserActionState, UserActionStatus, UserActionSubAction, UserNotification, VerificationType, VoiceCallbacks, VoiceConfig, VoicePermissions, VoiceResult, VoiceState, cancelUserAction, resendUserAction, submitUserAction, useChatV2, useVoice } from '@paymanai/payman-typescript-ask-sdk';
5
5
  import { ClassValue } from 'clsx';
6
6
 
7
7
  declare const NEGATIVE_FEEDBACK_REASONS: readonly [{
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import React__default from 'react';
3
3
  import { MessageDisplay, AgentStage, ChatCallbacks as ChatCallbacks$1, ChatConfig as ChatConfig$1, ActiveUserAction, UserNotification } from '@paymanai/payman-typescript-ask-sdk';
4
- export { APIConfig, ActiveUserAction, AgentStage, ChunkDisplay, JsonSchemaField, JsonSchemaOption, MessageDisplay, MessageRole, RequestedSchema, SessionParams, StreamProgress, StreamingStep, UseChatV2Return, UseVoiceReturn, UserActionKind, UserActionRequest, UserActionStaleError, UserActionState, UserActionStatus, UserActionSubAction, UserNotification, VerificationType, VoiceCallbacks, VoiceConfig, VoicePermissions, VoiceResult, VoiceState, cancelUserAction, expireUserAction, resendUserAction, submitUserAction, useChatV2, useVoice } from '@paymanai/payman-typescript-ask-sdk';
4
+ export { APIConfig, ActiveUserAction, AgentStage, ChunkDisplay, JsonSchemaField, JsonSchemaOption, MessageDisplay, MessageRole, RequestedSchema, SessionParams, StreamProgress, StreamingStep, UseChatV2Return, UseVoiceReturn, UserActionKind, UserActionRequest, UserActionStaleError, UserActionState, UserActionStatus, UserActionSubAction, UserNotification, VerificationType, VoiceCallbacks, VoiceConfig, VoicePermissions, VoiceResult, VoiceState, cancelUserAction, resendUserAction, submitUserAction, useChatV2, useVoice } from '@paymanai/payman-typescript-ask-sdk';
5
5
  import { ClassValue } from 'clsx';
6
6
 
7
7
  declare const NEGATIVE_FEEDBACK_REASONS: readonly [{
package/dist/index.js CHANGED
@@ -736,7 +736,8 @@ function buildRequestBody(config, userMessage, sessionId, options) {
736
736
  sessionAttributes,
737
737
  analysisMode: options?.analysisMode,
738
738
  locale: resolveLocale(config.locale),
739
- timezone: resolveTimezone(config.timezone)
739
+ timezone: resolveTimezone(config.timezone),
740
+ ...options?.attachments?.length ? { attachments: options.attachments } : {}
740
741
  };
741
742
  }
742
743
  function resolveLocale(configured) {
@@ -781,6 +782,7 @@ function buildResolveImagesUrl(config) {
781
782
  const basePath = normalizedEndpointPath.endsWith("/stream") ? normalizedEndpointPath.slice(0, -"/stream".length) : normalizedEndpointPath;
782
783
  return `${config.api.baseUrl}${basePath}/resolve-image-urls`;
783
784
  }
785
+ var NGROK_SKIP_BROWSER_WARNING = "ngrok-skip-browser-warning";
784
786
  function buildRequestHeaders(config) {
785
787
  const headers = {
786
788
  ...config.api.headers
@@ -788,6 +790,9 @@ function buildRequestHeaders(config) {
788
790
  if (config.api.authToken) {
789
791
  headers.Authorization = `Bearer ${config.api.authToken}`;
790
792
  }
793
+ if (!headers[NGROK_SKIP_BROWSER_WARNING]) {
794
+ headers[NGROK_SKIP_BROWSER_WARNING] = "true";
795
+ }
791
796
  return headers;
792
797
  }
793
798
  var RAG_IMAGE_REGEX = /\/api\/rag\/chunks\/[^"'\s]+\/image/;
@@ -1068,6 +1073,81 @@ function createCancelledMessageUpdate(steps, currentMessage) {
1068
1073
  currentMessage: currentMessage || "Thinking..."
1069
1074
  };
1070
1075
  }
1076
+ var DEFAULT_SIGNED_URL_ENDPOINT = "/api/files/signed-url";
1077
+ function fileExtension(filename) {
1078
+ const ext = filename.split(".").pop()?.toLowerCase().replace(/^\./, "");
1079
+ return ext && ext.length > 0 ? ext : "bin";
1080
+ }
1081
+ function resolveMimeType(file) {
1082
+ if (file.type && file.type.trim().length > 0) return file.type;
1083
+ const ext = fileExtension(file.name);
1084
+ const byExt = {
1085
+ pdf: "application/pdf",
1086
+ png: "image/png",
1087
+ jpg: "image/jpeg",
1088
+ jpeg: "image/jpeg",
1089
+ gif: "image/gif",
1090
+ webp: "image/webp"
1091
+ };
1092
+ return byExt[ext] ?? "application/octet-stream";
1093
+ }
1094
+ function buildSignedUrlEndpoint(config, ext) {
1095
+ const endpoint = config.api.signedUrlEndpoint || DEFAULT_SIGNED_URL_ENDPOINT;
1096
+ const queryParams = new URLSearchParams({ extn: ext.replace(/^\./, "") });
1097
+ return `${config.api.baseUrl}${endpoint}?${queryParams.toString()}`;
1098
+ }
1099
+ async function requestSignedUrl(config, ext, signal) {
1100
+ const url = buildSignedUrlEndpoint(config, ext);
1101
+ const headers = buildRequestHeaders(config);
1102
+ const response = await fetch(url, {
1103
+ method: "GET",
1104
+ headers,
1105
+ signal
1106
+ });
1107
+ if (!response.ok) {
1108
+ const errorText = await response.text().catch(() => "");
1109
+ throw new Error(
1110
+ errorText ? `Failed to get upload URL (${response.status}): ${errorText}` : `Failed to get upload URL (${response.status})`
1111
+ );
1112
+ }
1113
+ const data = await response.json();
1114
+ if (!data.key || !data.url) {
1115
+ throw new Error("Signed URL response missing key or url");
1116
+ }
1117
+ return { key: data.key, url: data.url };
1118
+ }
1119
+ async function uploadToSignedUrl(signedUrl, file, mimeType, signal) {
1120
+ const response = await fetch(signedUrl, {
1121
+ method: "PUT",
1122
+ headers: {
1123
+ "Content-Type": mimeType,
1124
+ "x-ms-blob-type": "BlockBlob"
1125
+ },
1126
+ body: file,
1127
+ signal
1128
+ });
1129
+ if (!response.ok) {
1130
+ const errorText = await response.text().catch(() => "");
1131
+ throw new Error(
1132
+ errorText ? `Failed to upload file (${response.status}): ${errorText}` : `Failed to upload file (${response.status})`
1133
+ );
1134
+ }
1135
+ }
1136
+ async function uploadAttachment(config, file, signal) {
1137
+ const ext = fileExtension(file.name);
1138
+ const mimeType = resolveMimeType(file);
1139
+ const { key, url } = await requestSignedUrl(config, ext, signal);
1140
+ await uploadToSignedUrl(url, file, mimeType, signal);
1141
+ return {
1142
+ tempKey: key,
1143
+ filename: file.name,
1144
+ mimeType
1145
+ };
1146
+ }
1147
+ async function uploadAttachments(config, files, signal) {
1148
+ const uploads = files.map((file) => uploadAttachment(config, file, signal));
1149
+ return Promise.all(uploads);
1150
+ }
1071
1151
  var UserActionStaleError = class extends Error {
1072
1152
  constructor(userActionId, message = "User action is no longer actionable") {
1073
1153
  super(message);
@@ -1104,9 +1184,6 @@ async function cancelUserAction(config, userActionId) {
1104
1184
  async function resendUserAction(config, userActionId) {
1105
1185
  return sendUserActionRequest(config, userActionId, "resend");
1106
1186
  }
1107
- async function expireUserAction(config, userActionId) {
1108
- return sendUserActionRequest(config, userActionId, "expired");
1109
- }
1110
1187
  var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
1111
1188
  function upsertPrompt(prompts, req) {
1112
1189
  const active = { ...req, status: "pending" };
@@ -1135,12 +1212,32 @@ function getStoredOrInitialMessages(config) {
1135
1212
  function getSessionIdFromMessages(messages) {
1136
1213
  return messages.find((message) => message.sessionId)?.sessionId;
1137
1214
  }
1215
+ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "gif", "webp", "avif"]);
1216
+ function attachmentKindFromFile(file) {
1217
+ const ext = file.name.split(".").pop()?.toLowerCase() ?? "";
1218
+ if (IMAGE_EXTENSIONS.has(ext) || file.type.startsWith("image/")) return "image";
1219
+ return "file";
1220
+ }
1221
+ function buildMessageAttachments(files) {
1222
+ return files.map((file, index) => {
1223
+ const kind = attachmentKindFromFile(file);
1224
+ return {
1225
+ id: `att-${Date.now()}-${index}`,
1226
+ filename: file.name,
1227
+ mimeType: file.type || "application/octet-stream",
1228
+ // Blob URL for all local files so PDFs/docs stay previewable after send.
1229
+ previewUrl: URL.createObjectURL(file),
1230
+ kind
1231
+ };
1232
+ });
1233
+ }
1138
1234
  function useChatV2(config, callbacks = {}) {
1139
1235
  const [messages, setMessages] = react.useState(() => getStoredOrInitialMessages(config));
1140
1236
  const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(() => {
1141
1237
  if (!config.userId) return false;
1142
1238
  return activeStreamStore.get(config.userId)?.isWaiting ?? false;
1143
1239
  });
1240
+ const [isUploadingAttachments, setIsUploadingAttachments] = react.useState(false);
1144
1241
  const sessionIdRef = react.useRef(
1145
1242
  getSessionIdFromMessages(getStoredOrInitialMessages(config)) ?? config.initialSessionId ?? void 0
1146
1243
  );
@@ -1215,21 +1312,45 @@ function useChatV2(config, callbacks = {}) {
1215
1312
  );
1216
1313
  const sendMessage = react.useCallback(
1217
1314
  async (userMessage, options) => {
1218
- if (!userMessage.trim()) return;
1315
+ const trimmedMessage = userMessage.trim();
1316
+ const files = options?.files ?? [];
1317
+ const hasPreuploadedAttachments = (options?.attachments?.length ?? 0) > 0;
1318
+ if (!trimmedMessage && files.length === 0 && !hasPreuploadedAttachments) return;
1319
+ let streamAttachments = options?.attachments;
1320
+ if (!streamAttachments && files.length > 0) {
1321
+ setIsUploadingAttachments(true);
1322
+ try {
1323
+ streamAttachments = await uploadAttachments(configRef.current, files);
1324
+ } catch (error) {
1325
+ if (error.name !== "AbortError") {
1326
+ callbacksRef.current.onError?.(error);
1327
+ }
1328
+ throw error;
1329
+ } finally {
1330
+ setIsUploadingAttachments(false);
1331
+ }
1332
+ }
1219
1333
  if (!sessionIdRef.current && configRef.current.autoGenerateSessionId !== false) {
1220
1334
  sessionIdRef.current = generateId();
1221
1335
  callbacksRef.current.onSessionIdChange?.(sessionIdRef.current);
1222
1336
  }
1337
+ const messageAttachments = files.length > 0 ? buildMessageAttachments(files) : streamAttachments?.length ? streamAttachments.map((attachment, index) => ({
1338
+ id: `att-${Date.now()}-${index}`,
1339
+ filename: attachment.filename,
1340
+ mimeType: attachment.mimeType,
1341
+ kind: attachment.mimeType.startsWith("image/") ? "image" : "file"
1342
+ })) : void 0;
1223
1343
  const userMessageId = `user-${Date.now()}`;
1224
1344
  const userMsg = {
1225
1345
  id: userMessageId,
1226
1346
  sessionId: sessionIdRef.current,
1227
1347
  role: "user",
1228
- content: userMessage,
1229
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1348
+ content: trimmedMessage,
1349
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1350
+ attachments: messageAttachments
1230
1351
  };
1231
1352
  setMessages((prev) => [...prev, userMsg]);
1232
- callbacksRef.current.onMessageSent?.(userMessage);
1353
+ callbacksRef.current.onMessageSent?.(trimmedMessage);
1233
1354
  setIsWaitingForResponse(true);
1234
1355
  callbacksRef.current.onStreamStart?.();
1235
1356
  const streamingId = `assistant-${Date.now()}`;
@@ -1256,11 +1377,14 @@ function useChatV2(config, callbacks = {}) {
1256
1377
  activeStreamStore.start(userId, abortController, initialMessages);
1257
1378
  }
1258
1379
  const newSessionId = await startStream(
1259
- userMessage,
1380
+ trimmedMessage,
1260
1381
  streamingId,
1261
1382
  sessionIdRef.current,
1262
1383
  abortController,
1263
- options
1384
+ {
1385
+ analysisMode: options?.analysisMode,
1386
+ attachments: streamAttachments
1387
+ }
1264
1388
  );
1265
1389
  const finalStreamUserId = streamUserIdRef.current ?? userId;
1266
1390
  if (finalStreamUserId) {
@@ -1398,19 +1522,6 @@ function useChatV2(config, callbacks = {}) {
1398
1522
  },
1399
1523
  [setPromptStatus]
1400
1524
  );
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
- );
1414
1525
  const dismissNotification = react.useCallback((id) => {
1415
1526
  setUserActionState((prev) => ({
1416
1527
  ...prev,
@@ -1451,6 +1562,18 @@ function useChatV2(config, callbacks = {}) {
1451
1562
  setMessages(config.initialMessages);
1452
1563
  sessionIdRef.current = getSessionIdFromMessages(config.initialMessages) ?? config.initialSessionId;
1453
1564
  }, [config.initialMessages, config.initialSessionId, config.userId]);
1565
+ const hydratedSessionIdRef = react.useRef(void 0);
1566
+ react.useEffect(() => {
1567
+ if (config.userId) return;
1568
+ if (!config.initialMessages?.length) return;
1569
+ const sessionId = config.initialSessionId;
1570
+ if (hydratedSessionIdRef.current === sessionId && messagesRef.current.length > 0) {
1571
+ return;
1572
+ }
1573
+ hydratedSessionIdRef.current = sessionId;
1574
+ setMessages(config.initialMessages);
1575
+ sessionIdRef.current = getSessionIdFromMessages(config.initialMessages) ?? sessionId;
1576
+ }, [config.initialMessages, config.initialSessionId, config.userId]);
1454
1577
  react.useEffect(() => {
1455
1578
  const prevUserId = prevUserIdRef.current;
1456
1579
  prevUserIdRef.current = config.userId;
@@ -1485,12 +1608,12 @@ function useChatV2(config, callbacks = {}) {
1485
1608
  getSessionId,
1486
1609
  getMessages,
1487
1610
  isWaitingForResponse,
1611
+ isUploadingAttachments,
1488
1612
  sessionId: sessionIdRef.current,
1489
1613
  userActionState,
1490
1614
  submitUserAction: submitUserAction2,
1491
1615
  cancelUserAction: cancelUserAction2,
1492
1616
  resendUserAction: resendUserAction2,
1493
- expireUserAction: expireUserAction2,
1494
1617
  dismissNotification
1495
1618
  };
1496
1619
  }
@@ -6140,7 +6263,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6140
6263
  const submitUserAction2 = chat.submitUserAction ?? NOOP_ASYNC;
6141
6264
  const cancelUserAction2 = chat.cancelUserAction ?? NOOP_ASYNC;
6142
6265
  const resendUserAction2 = chat.resendUserAction ?? NOOP_ASYNC;
6143
- const expireUserAction2 = chat.expireUserAction ?? NOOP_ASYNC;
6266
+ const expireUserAction = chat.expireUserAction ?? NOOP_ASYNC;
6144
6267
  const dismissNotification = chat.dismissNotification ?? NOOP;
6145
6268
  const isUserActionSupported = typeof chat.submitUserAction === "function" && typeof chat.cancelUserAction === "function" && typeof chat.resendUserAction === "function";
6146
6269
  const {
@@ -6541,7 +6664,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6541
6664
  onSubmitUserAction: isUserActionSupported ? submitUserAction2 : void 0,
6542
6665
  onCancelUserAction: isUserActionSupported ? cancelUserAction2 : void 0,
6543
6666
  onResendUserAction: isUserActionSupported ? resendUserAction2 : void 0,
6544
- onExpireUserAction: isUserActionSupported ? expireUserAction2 : void 0,
6667
+ onExpireUserAction: isUserActionSupported ? expireUserAction : void 0,
6545
6668
  onDismissNotification: dismissNotification,
6546
6669
  onSubmitFeedback: handleSubmitFeedback
6547
6670
  }
@@ -6631,7 +6754,6 @@ exports.UserActionStaleError = UserActionStaleError;
6631
6754
  exports.cancelUserAction = cancelUserAction;
6632
6755
  exports.captureSentryError = captureSentryError;
6633
6756
  exports.cn = cn;
6634
- exports.expireUserAction = expireUserAction;
6635
6757
  exports.formatDate = formatDate;
6636
6758
  exports.resendUserAction = resendUserAction;
6637
6759
  exports.submitUserAction = submitUserAction;