@paymanai/payman-typescript-ask-sdk 4.0.23 → 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.
@@ -36,6 +36,7 @@ var chatStore = {
36
36
  };
37
37
 
38
38
  // src/utils/activeStreamStore.ts
39
+ var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
39
40
  var streams = /* @__PURE__ */ new Map();
40
41
  var activeStreamStore = {
41
42
  has(key) {
@@ -44,7 +45,11 @@ var activeStreamStore = {
44
45
  get(key) {
45
46
  const entry = streams.get(key);
46
47
  if (!entry) return null;
47
- return { messages: entry.messages, isWaiting: entry.isWaiting };
48
+ return {
49
+ messages: entry.messages,
50
+ isWaiting: entry.isWaiting,
51
+ userActionState: entry.userActionState
52
+ };
48
53
  },
49
54
  // Called before startStream — registers the controller and initial messages
50
55
  start(key, abortController, initialMessages) {
@@ -52,6 +57,7 @@ var activeStreamStore = {
52
57
  streams.set(key, {
53
58
  messages: initialMessages,
54
59
  isWaiting: true,
60
+ userActionState: EMPTY_USER_ACTION_STATE,
55
61
  abortController,
56
62
  listeners: existing?.listeners ?? /* @__PURE__ */ new Set()
57
63
  });
@@ -62,20 +68,27 @@ var activeStreamStore = {
62
68
  if (!entry) return;
63
69
  const next = typeof updater === "function" ? updater(entry.messages) : updater;
64
70
  entry.messages = next;
65
- entry.listeners.forEach((l) => l(next, entry.isWaiting));
71
+ entry.listeners.forEach((l) => l(next, entry.isWaiting, entry.userActionState));
66
72
  },
67
73
  setWaiting(key, waiting) {
68
74
  const entry = streams.get(key);
69
75
  if (!entry) return;
70
76
  entry.isWaiting = waiting;
71
- entry.listeners.forEach((l) => l(entry.messages, waiting));
77
+ entry.listeners.forEach((l) => l(entry.messages, waiting, entry.userActionState));
78
+ },
79
+ applyUserActionState(key, updater) {
80
+ const entry = streams.get(key);
81
+ if (!entry) return;
82
+ const next = typeof updater === "function" ? updater(entry.userActionState) : updater;
83
+ entry.userActionState = next;
84
+ entry.listeners.forEach((l) => l(entry.messages, entry.isWaiting, next));
72
85
  },
73
86
  // Called when stream completes — persists to chatStore and cleans up
74
87
  complete(key) {
75
88
  const entry = streams.get(key);
76
89
  if (!entry) return;
77
90
  entry.isWaiting = false;
78
- entry.listeners.forEach((l) => l(entry.messages, false));
91
+ entry.listeners.forEach((l) => l(entry.messages, false, entry.userActionState));
79
92
  const toSave = entry.messages.filter((m) => !m.isStreaming);
80
93
  if (toSave.length > 0) chatStore.set(key, toSave);
81
94
  streams.delete(key);
@@ -1115,13 +1128,38 @@ async function expireUserAction(config, userActionId) {
1115
1128
  return sendUserActionRequest(config, userActionId, "expired");
1116
1129
  }
1117
1130
 
1131
+ // src/utils/userActionExpiry.ts
1132
+ function resolveUserActionExpiresAt(req, existing) {
1133
+ if (typeof req.expirySeconds !== "number" || req.expirySeconds <= 0) {
1134
+ return void 0;
1135
+ }
1136
+ if (existing?.expiresAt && existing.userActionId === req.userActionId) {
1137
+ return existing.expiresAt;
1138
+ }
1139
+ return Date.now() + Math.floor(req.expirySeconds) * 1e3;
1140
+ }
1141
+ function getUserActionSecondsLeft(prompt) {
1142
+ if (typeof prompt.expiresAt === "number" && prompt.expiresAt > 0) {
1143
+ return Math.max(0, Math.ceil((prompt.expiresAt - Date.now()) / 1e3));
1144
+ }
1145
+ if (typeof prompt.expirySeconds === "number" && prompt.expirySeconds > 0) {
1146
+ return Math.floor(prompt.expirySeconds);
1147
+ }
1148
+ return void 0;
1149
+ }
1150
+ function isUserActionExpired(prompt) {
1151
+ const left = getUserActionSecondsLeft(prompt);
1152
+ return left !== void 0 && left <= 0;
1153
+ }
1154
+
1118
1155
  // src/hooks/useChatV2.ts
1119
- var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
1156
+ var EMPTY_USER_ACTION_STATE2 = { prompts: [], notifications: [] };
1120
1157
  function upsertPrompt(prompts, req) {
1121
- const active = { ...req, status: "pending" };
1122
1158
  const idx = prompts.findIndex(
1123
1159
  (p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
1124
1160
  );
1161
+ const expiresAt = resolveUserActionExpiresAt(req, idx >= 0 ? prompts[idx] : void 0);
1162
+ const active = { ...req, status: "pending", expiresAt };
1125
1163
  if (idx >= 0) {
1126
1164
  const next = prompts.slice();
1127
1165
  next[idx] = active;
@@ -1192,7 +1230,28 @@ function useChatV2(config, callbacks = {}) {
1192
1230
  // eslint-disable-next-line react-hooks/exhaustive-deps
1193
1231
  []
1194
1232
  );
1195
- const [userActionState, setUserActionState] = react.useState(EMPTY_USER_ACTION_STATE);
1233
+ const [userActionState, setUserActionState] = react.useState(() => {
1234
+ if (!config.userId) return EMPTY_USER_ACTION_STATE2;
1235
+ return activeStreamStore.get(config.userId)?.userActionState ?? EMPTY_USER_ACTION_STATE2;
1236
+ });
1237
+ const storeAwareSetUserActionState = react.useCallback(
1238
+ (updater) => {
1239
+ const streamUserId = streamUserIdRef.current;
1240
+ const currentUserId = configRef.current.userId;
1241
+ const storeKey = streamUserId ?? currentUserId;
1242
+ if (storeKey && activeStreamStore.has(storeKey)) {
1243
+ activeStreamStore.applyUserActionState(
1244
+ storeKey,
1245
+ updater
1246
+ );
1247
+ }
1248
+ if (!streamUserId || streamUserId === currentUserId) {
1249
+ setUserActionState(updater);
1250
+ }
1251
+ },
1252
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1253
+ []
1254
+ );
1196
1255
  const wrappedCallbacks = react.useMemo(() => ({
1197
1256
  ...callbacksRef.current,
1198
1257
  onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
@@ -1202,14 +1261,14 @@ function useChatV2(config, callbacks = {}) {
1202
1261
  onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
1203
1262
  onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
1204
1263
  onUserActionRequired: (request) => {
1205
- setUserActionState((prev) => ({
1264
+ storeAwareSetUserActionState((prev) => ({
1206
1265
  ...prev,
1207
1266
  prompts: upsertPrompt(prev.prompts, request)
1208
1267
  }));
1209
1268
  callbacksRef.current.onUserActionRequired?.(request);
1210
1269
  },
1211
1270
  onUserNotification: (notification) => {
1212
- setUserActionState(
1271
+ storeAwareSetUserActionState(
1213
1272
  (prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
1214
1273
  );
1215
1274
  callbacksRef.current.onUserNotification?.(notification);
@@ -1299,7 +1358,7 @@ function useChatV2(config, callbacks = {}) {
1299
1358
  streamUserIdRef.current = void 0;
1300
1359
  cancelStreamManager();
1301
1360
  setIsWaitingForResponse(false);
1302
- setUserActionState((prev) => ({ ...prev, prompts: [] }));
1361
+ storeAwareSetUserActionState((prev) => ({ ...prev, prompts: [] }));
1303
1362
  setMessages(
1304
1363
  (prev) => prev.map((msg) => {
1305
1364
  if (msg.isStreaming) {
@@ -1314,7 +1373,7 @@ function useChatV2(config, callbacks = {}) {
1314
1373
  return msg;
1315
1374
  })
1316
1375
  );
1317
- }, [cancelStreamManager]);
1376
+ }, [cancelStreamManager, storeAwareSetUserActionState]);
1318
1377
  const resetSession = react.useCallback(() => {
1319
1378
  const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
1320
1379
  if (streamUserId) {
@@ -1328,7 +1387,7 @@ function useChatV2(config, callbacks = {}) {
1328
1387
  sessionIdRef.current = void 0;
1329
1388
  abortControllerRef.current?.abort();
1330
1389
  setIsWaitingForResponse(false);
1331
- setUserActionState(EMPTY_USER_ACTION_STATE);
1390
+ storeAwareSetUserActionState(EMPTY_USER_ACTION_STATE2);
1332
1391
  }, []);
1333
1392
  const getSessionId = react.useCallback(() => {
1334
1393
  return sessionIdRef.current;
@@ -1338,21 +1397,21 @@ function useChatV2(config, callbacks = {}) {
1338
1397
  }, [messages]);
1339
1398
  const setPromptStatus = react.useCallback(
1340
1399
  (userActionId, status) => {
1341
- setUserActionState((prev) => ({
1400
+ storeAwareSetUserActionState((prev) => ({
1342
1401
  ...prev,
1343
1402
  prompts: prev.prompts.map(
1344
1403
  (p) => p.userActionId === userActionId ? { ...p, status } : p
1345
1404
  )
1346
1405
  }));
1347
1406
  },
1348
- []
1407
+ [storeAwareSetUserActionState]
1349
1408
  );
1350
1409
  const removePrompt = react.useCallback((userActionId) => {
1351
- setUserActionState((prev) => ({
1410
+ storeAwareSetUserActionState((prev) => ({
1352
1411
  ...prev,
1353
1412
  prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
1354
1413
  }));
1355
- }, []);
1414
+ }, [storeAwareSetUserActionState]);
1356
1415
  const submitUserAction2 = react.useCallback(
1357
1416
  async (userActionId, content) => {
1358
1417
  setPromptStatus(userActionId, "submitting");
@@ -1421,11 +1480,11 @@ function useChatV2(config, callbacks = {}) {
1421
1480
  [setPromptStatus]
1422
1481
  );
1423
1482
  const dismissNotification = react.useCallback((id) => {
1424
- setUserActionState((prev) => ({
1483
+ storeAwareSetUserActionState((prev) => ({
1425
1484
  ...prev,
1426
1485
  notifications: prev.notifications.filter((n) => n.id !== id)
1427
1486
  }));
1428
- }, []);
1487
+ }, [storeAwareSetUserActionState]);
1429
1488
  react.useEffect(() => {
1430
1489
  const prevSubscriptionUserId = subscriptionPrevUserIdRef.current;
1431
1490
  subscriptionPrevUserIdRef.current = config.userId;
@@ -1434,14 +1493,17 @@ function useChatV2(config, callbacks = {}) {
1434
1493
  if (prevSubscriptionUserId && prevSubscriptionUserId !== userId && streamUserIdRef.current === prevSubscriptionUserId && !activeStreamStore.has(prevSubscriptionUserId) && activeStreamStore.has(userId)) {
1435
1494
  streamUserIdRef.current = userId;
1436
1495
  }
1437
- const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
1496
+ const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting, actions) => {
1438
1497
  setMessages(msgs);
1439
1498
  setIsWaitingForResponse(isWaiting);
1499
+ setUserActionState(actions);
1440
1500
  });
1441
1501
  const active = activeStreamStore.get(userId);
1442
1502
  if (active) {
1503
+ streamUserIdRef.current = userId;
1443
1504
  setMessages(active.messages);
1444
1505
  setIsWaitingForResponse(active.isWaiting);
1506
+ setUserActionState(active.userActionState);
1445
1507
  }
1446
1508
  return unsubscribe;
1447
1509
  }, [config.userId]);
@@ -1469,12 +1531,14 @@ function useChatV2(config, callbacks = {}) {
1469
1531
  setMessages([]);
1470
1532
  sessionIdRef.current = void 0;
1471
1533
  setIsWaitingForResponse(false);
1472
- setUserActionState(EMPTY_USER_ACTION_STATE);
1534
+ setUserActionState(EMPTY_USER_ACTION_STATE2);
1473
1535
  } else if (config.userId) {
1474
1536
  const active = activeStreamStore.get(config.userId);
1475
1537
  if (active) {
1538
+ streamUserIdRef.current = config.userId;
1476
1539
  setMessages(active.messages);
1477
1540
  setIsWaitingForResponse(active.isWaiting);
1541
+ setUserActionState(active.userActionState);
1478
1542
  sessionIdRef.current = getSessionIdFromMessages(active.messages) ?? config.initialSessionId;
1479
1543
  return;
1480
1544
  }
@@ -1753,12 +1817,15 @@ exports.defaultValueFor = defaultValueFor;
1753
1817
  exports.expireUserAction = expireUserAction;
1754
1818
  exports.generateId = generateId;
1755
1819
  exports.getOptions = getOptions;
1820
+ exports.getUserActionSecondsLeft = getUserActionSecondsLeft;
1756
1821
  exports.isNestedOrUnsupported = isNestedOrUnsupported;
1757
1822
  exports.isRequired = isRequired;
1823
+ exports.isUserActionExpired = isUserActionExpired;
1758
1824
  exports.migrateActiveStream = migrateActiveStream;
1759
1825
  exports.processStreamEventV2 = processStreamEventV2;
1760
1826
  exports.renderableFields = renderableFields;
1761
1827
  exports.resendUserAction = resendUserAction;
1828
+ exports.resolveUserActionExpiresAt = resolveUserActionExpiresAt;
1762
1829
  exports.streamWorkflowEvents = streamWorkflowEvents;
1763
1830
  exports.submitUserAction = submitUserAction;
1764
1831
  exports.useChatV2 = useChatV2;