@paymanai/payman-typescript-ask-sdk 4.0.24 → 4.0.25

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
@@ -28,6 +28,7 @@ var chatStore = {
28
28
  };
29
29
 
30
30
  // src/utils/activeStreamStore.ts
31
+ var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
31
32
  var streams = /* @__PURE__ */ new Map();
32
33
  var activeStreamStore = {
33
34
  has(key) {
@@ -36,7 +37,11 @@ var activeStreamStore = {
36
37
  get(key) {
37
38
  const entry = streams.get(key);
38
39
  if (!entry) return null;
39
- return { messages: entry.messages, isWaiting: entry.isWaiting };
40
+ return {
41
+ messages: entry.messages,
42
+ isWaiting: entry.isWaiting,
43
+ userActionState: entry.userActionState
44
+ };
40
45
  },
41
46
  // Called before startStream — registers the controller and initial messages
42
47
  start(key, abortController, initialMessages) {
@@ -44,6 +49,7 @@ var activeStreamStore = {
44
49
  streams.set(key, {
45
50
  messages: initialMessages,
46
51
  isWaiting: true,
52
+ userActionState: EMPTY_USER_ACTION_STATE,
47
53
  abortController,
48
54
  listeners: existing?.listeners ?? /* @__PURE__ */ new Set()
49
55
  });
@@ -54,20 +60,27 @@ var activeStreamStore = {
54
60
  if (!entry) return;
55
61
  const next = typeof updater === "function" ? updater(entry.messages) : updater;
56
62
  entry.messages = next;
57
- entry.listeners.forEach((l) => l(next, entry.isWaiting));
63
+ entry.listeners.forEach((l) => l(next, entry.isWaiting, entry.userActionState));
58
64
  },
59
65
  setWaiting(key, waiting) {
60
66
  const entry = streams.get(key);
61
67
  if (!entry) return;
62
68
  entry.isWaiting = waiting;
63
- entry.listeners.forEach((l) => l(entry.messages, waiting));
69
+ entry.listeners.forEach((l) => l(entry.messages, waiting, entry.userActionState));
70
+ },
71
+ applyUserActionState(key, updater) {
72
+ const entry = streams.get(key);
73
+ if (!entry) return;
74
+ const next = typeof updater === "function" ? updater(entry.userActionState) : updater;
75
+ entry.userActionState = next;
76
+ entry.listeners.forEach((l) => l(entry.messages, entry.isWaiting, next));
64
77
  },
65
78
  // Called when stream completes — persists to chatStore and cleans up
66
79
  complete(key) {
67
80
  const entry = streams.get(key);
68
81
  if (!entry) return;
69
82
  entry.isWaiting = false;
70
- entry.listeners.forEach((l) => l(entry.messages, false));
83
+ entry.listeners.forEach((l) => l(entry.messages, false, entry.userActionState));
71
84
  const toSave = entry.messages.filter((m) => !m.isStreaming);
72
85
  if (toSave.length > 0) chatStore.set(key, toSave);
73
86
  streams.delete(key);
@@ -1092,13 +1105,38 @@ async function expireUserAction(config, userActionId) {
1092
1105
  return sendUserActionRequest(config, userActionId, "expired");
1093
1106
  }
1094
1107
 
1108
+ // src/utils/userActionExpiry.ts
1109
+ function resolveUserActionExpiresAt(req, existing) {
1110
+ if (typeof req.expirySeconds !== "number" || req.expirySeconds <= 0) {
1111
+ return void 0;
1112
+ }
1113
+ if (existing?.expiresAt && existing.userActionId === req.userActionId) {
1114
+ return existing.expiresAt;
1115
+ }
1116
+ return Date.now() + Math.floor(req.expirySeconds) * 1e3;
1117
+ }
1118
+ function getUserActionSecondsLeft(prompt) {
1119
+ if (typeof prompt.expiresAt === "number" && prompt.expiresAt > 0) {
1120
+ return Math.max(0, Math.ceil((prompt.expiresAt - Date.now()) / 1e3));
1121
+ }
1122
+ if (typeof prompt.expirySeconds === "number" && prompt.expirySeconds > 0) {
1123
+ return Math.floor(prompt.expirySeconds);
1124
+ }
1125
+ return void 0;
1126
+ }
1127
+ function isUserActionExpired(prompt) {
1128
+ const left = getUserActionSecondsLeft(prompt);
1129
+ return left !== void 0 && left <= 0;
1130
+ }
1131
+
1095
1132
  // src/hooks/useChatV2.ts
1096
- var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
1133
+ var EMPTY_USER_ACTION_STATE2 = { prompts: [], notifications: [] };
1097
1134
  function upsertPrompt(prompts, req) {
1098
- const active = { ...req, status: "pending" };
1099
1135
  const idx = prompts.findIndex(
1100
1136
  (p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
1101
1137
  );
1138
+ const expiresAt = resolveUserActionExpiresAt(req, idx >= 0 ? prompts[idx] : void 0);
1139
+ const active = { ...req, status: "pending", expiresAt };
1102
1140
  if (idx >= 0) {
1103
1141
  const next = prompts.slice();
1104
1142
  next[idx] = active;
@@ -1169,7 +1207,28 @@ function useChatV2(config, callbacks = {}) {
1169
1207
  // eslint-disable-next-line react-hooks/exhaustive-deps
1170
1208
  []
1171
1209
  );
1172
- const [userActionState, setUserActionState] = useState(EMPTY_USER_ACTION_STATE);
1210
+ const [userActionState, setUserActionState] = useState(() => {
1211
+ if (!config.userId) return EMPTY_USER_ACTION_STATE2;
1212
+ return activeStreamStore.get(config.userId)?.userActionState ?? EMPTY_USER_ACTION_STATE2;
1213
+ });
1214
+ const storeAwareSetUserActionState = useCallback(
1215
+ (updater) => {
1216
+ const streamUserId = streamUserIdRef.current;
1217
+ const currentUserId = configRef.current.userId;
1218
+ const storeKey = streamUserId ?? currentUserId;
1219
+ if (storeKey && activeStreamStore.has(storeKey)) {
1220
+ activeStreamStore.applyUserActionState(
1221
+ storeKey,
1222
+ updater
1223
+ );
1224
+ }
1225
+ if (!streamUserId || streamUserId === currentUserId) {
1226
+ setUserActionState(updater);
1227
+ }
1228
+ },
1229
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1230
+ []
1231
+ );
1173
1232
  const wrappedCallbacks = useMemo(() => ({
1174
1233
  ...callbacksRef.current,
1175
1234
  onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
@@ -1179,14 +1238,14 @@ function useChatV2(config, callbacks = {}) {
1179
1238
  onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
1180
1239
  onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
1181
1240
  onUserActionRequired: (request) => {
1182
- setUserActionState((prev) => ({
1241
+ storeAwareSetUserActionState((prev) => ({
1183
1242
  ...prev,
1184
1243
  prompts: upsertPrompt(prev.prompts, request)
1185
1244
  }));
1186
1245
  callbacksRef.current.onUserActionRequired?.(request);
1187
1246
  },
1188
1247
  onUserNotification: (notification) => {
1189
- setUserActionState(
1248
+ storeAwareSetUserActionState(
1190
1249
  (prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
1191
1250
  );
1192
1251
  callbacksRef.current.onUserNotification?.(notification);
@@ -1276,7 +1335,7 @@ function useChatV2(config, callbacks = {}) {
1276
1335
  streamUserIdRef.current = void 0;
1277
1336
  cancelStreamManager();
1278
1337
  setIsWaitingForResponse(false);
1279
- setUserActionState((prev) => ({ ...prev, prompts: [] }));
1338
+ storeAwareSetUserActionState((prev) => ({ ...prev, prompts: [] }));
1280
1339
  setMessages(
1281
1340
  (prev) => prev.map((msg) => {
1282
1341
  if (msg.isStreaming) {
@@ -1291,7 +1350,7 @@ function useChatV2(config, callbacks = {}) {
1291
1350
  return msg;
1292
1351
  })
1293
1352
  );
1294
- }, [cancelStreamManager]);
1353
+ }, [cancelStreamManager, storeAwareSetUserActionState]);
1295
1354
  const resetSession = useCallback(() => {
1296
1355
  const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
1297
1356
  if (streamUserId) {
@@ -1305,7 +1364,7 @@ function useChatV2(config, callbacks = {}) {
1305
1364
  sessionIdRef.current = void 0;
1306
1365
  abortControllerRef.current?.abort();
1307
1366
  setIsWaitingForResponse(false);
1308
- setUserActionState(EMPTY_USER_ACTION_STATE);
1367
+ storeAwareSetUserActionState(EMPTY_USER_ACTION_STATE2);
1309
1368
  }, []);
1310
1369
  const getSessionId = useCallback(() => {
1311
1370
  return sessionIdRef.current;
@@ -1315,21 +1374,21 @@ function useChatV2(config, callbacks = {}) {
1315
1374
  }, [messages]);
1316
1375
  const setPromptStatus = useCallback(
1317
1376
  (userActionId, status) => {
1318
- setUserActionState((prev) => ({
1377
+ storeAwareSetUserActionState((prev) => ({
1319
1378
  ...prev,
1320
1379
  prompts: prev.prompts.map(
1321
1380
  (p) => p.userActionId === userActionId ? { ...p, status } : p
1322
1381
  )
1323
1382
  }));
1324
1383
  },
1325
- []
1384
+ [storeAwareSetUserActionState]
1326
1385
  );
1327
1386
  const removePrompt = useCallback((userActionId) => {
1328
- setUserActionState((prev) => ({
1387
+ storeAwareSetUserActionState((prev) => ({
1329
1388
  ...prev,
1330
1389
  prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
1331
1390
  }));
1332
- }, []);
1391
+ }, [storeAwareSetUserActionState]);
1333
1392
  const submitUserAction2 = useCallback(
1334
1393
  async (userActionId, content) => {
1335
1394
  setPromptStatus(userActionId, "submitting");
@@ -1398,11 +1457,11 @@ function useChatV2(config, callbacks = {}) {
1398
1457
  [setPromptStatus]
1399
1458
  );
1400
1459
  const dismissNotification = useCallback((id) => {
1401
- setUserActionState((prev) => ({
1460
+ storeAwareSetUserActionState((prev) => ({
1402
1461
  ...prev,
1403
1462
  notifications: prev.notifications.filter((n) => n.id !== id)
1404
1463
  }));
1405
- }, []);
1464
+ }, [storeAwareSetUserActionState]);
1406
1465
  useEffect(() => {
1407
1466
  const prevSubscriptionUserId = subscriptionPrevUserIdRef.current;
1408
1467
  subscriptionPrevUserIdRef.current = config.userId;
@@ -1411,14 +1470,17 @@ function useChatV2(config, callbacks = {}) {
1411
1470
  if (prevSubscriptionUserId && prevSubscriptionUserId !== userId && streamUserIdRef.current === prevSubscriptionUserId && !activeStreamStore.has(prevSubscriptionUserId) && activeStreamStore.has(userId)) {
1412
1471
  streamUserIdRef.current = userId;
1413
1472
  }
1414
- const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
1473
+ const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting, actions) => {
1415
1474
  setMessages(msgs);
1416
1475
  setIsWaitingForResponse(isWaiting);
1476
+ setUserActionState(actions);
1417
1477
  });
1418
1478
  const active = activeStreamStore.get(userId);
1419
1479
  if (active) {
1480
+ streamUserIdRef.current = userId;
1420
1481
  setMessages(active.messages);
1421
1482
  setIsWaitingForResponse(active.isWaiting);
1483
+ setUserActionState(active.userActionState);
1422
1484
  }
1423
1485
  return unsubscribe;
1424
1486
  }, [config.userId]);
@@ -1446,12 +1508,14 @@ function useChatV2(config, callbacks = {}) {
1446
1508
  setMessages([]);
1447
1509
  sessionIdRef.current = void 0;
1448
1510
  setIsWaitingForResponse(false);
1449
- setUserActionState(EMPTY_USER_ACTION_STATE);
1511
+ setUserActionState(EMPTY_USER_ACTION_STATE2);
1450
1512
  } else if (config.userId) {
1451
1513
  const active = activeStreamStore.get(config.userId);
1452
1514
  if (active) {
1515
+ streamUserIdRef.current = config.userId;
1453
1516
  setMessages(active.messages);
1454
1517
  setIsWaitingForResponse(active.isWaiting);
1518
+ setUserActionState(active.userActionState);
1455
1519
  sessionIdRef.current = getSessionIdFromMessages(active.messages) ?? config.initialSessionId;
1456
1520
  return;
1457
1521
  }
@@ -1819,6 +1883,6 @@ function migrateActiveStream(oldUserId, newUserId) {
1819
1883
  activeStreamStore.rename(oldUserId, newUserId);
1820
1884
  }
1821
1885
 
1822
- export { UserActionStaleError, buildContent, cancelUserAction, classifyField, classifyUserActionKind, coerceValue, createInitialV2State, defaultValueFor, expireUserAction, generateId, getOptions, isNestedOrUnsupported, isRequired, migrateActiveStream, processStreamEventV2, renderableFields, resendUserAction, streamWorkflowEvents, submitUserAction, useChatV2, useVoice, validateField, validateForm };
1886
+ export { UserActionStaleError, buildContent, cancelUserAction, classifyField, classifyUserActionKind, coerceValue, createInitialV2State, defaultValueFor, expireUserAction, generateId, getOptions, getUserActionSecondsLeft, isNestedOrUnsupported, isRequired, isUserActionExpired, migrateActiveStream, processStreamEventV2, renderableFields, resendUserAction, resolveUserActionExpiresAt, streamWorkflowEvents, submitUserAction, useChatV2, useVoice, validateField, validateForm };
1823
1887
  //# sourceMappingURL=index.mjs.map
1824
1888
  //# sourceMappingURL=index.mjs.map