@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.d.mts CHANGED
@@ -124,6 +124,8 @@ type UserActionRequest = {
124
124
  subAction?: UserActionSubAction | (string & {});
125
125
  verificationType?: VerificationType;
126
126
  expirySeconds?: number;
127
+ /** Wall-clock expiry (epoch ms). Set when the prompt is first received. */
128
+ expiresAt?: number;
127
129
  message?: string;
128
130
  requestedSchema?: RequestedSchema;
129
131
  metadata?: Record<string, string>;
@@ -639,6 +641,12 @@ declare function cancelUserAction(config: ChatConfig, userActionId: string): Pro
639
641
  declare function resendUserAction(config: ChatConfig, userActionId: string): Promise<UserActionResponse>;
640
642
  declare function expireUserAction(config: ChatConfig, userActionId: string): Promise<UserActionResponse>;
641
643
 
644
+ /** Wall-clock deadline (epoch ms) for a prompt with a positive TTL. */
645
+ declare function resolveUserActionExpiresAt(req: UserActionRequest, existing?: ActiveUserAction): number | undefined;
646
+ /** Seconds remaining before expiry, or undefined when the prompt has no TTL. */
647
+ declare function getUserActionSecondsLeft(prompt: ActiveUserAction): number | undefined;
648
+ declare function isUserActionExpired(prompt: ActiveUserAction): boolean;
649
+
642
650
  declare function migrateActiveStream(oldUserId: string, newUserId: string): void;
643
651
 
644
- export { type APIConfig, type ActiveUserAction, type AgentStage, type AnalysisMode, type ChatCallbacks, type ChatConfig, type ChunkDisplay, type FieldWidget, type JsonSchemaField, type JsonSchemaOption, type MessageDisplay, type MessageFeedbackState, type MessageRole, type RequestedSchema, type SendMessageOptions, type SessionParams, type StreamEvent, type StreamOptions, type StreamProgress, type StreamingStep, type UseChatV2Return, type UseVoiceReturn, type UserActionKind, type UserActionRequest, UserActionStaleError, type UserActionState, type UserActionStatus, type UserActionSubAction, type UserNotification, type V2EventProcessorState, type VerificationType, type VoiceCallbacks, type VoiceConfig, type VoicePermissions, type VoiceResult, type VoiceState, buildContent, cancelUserAction, classifyField, classifyUserActionKind, coerceValue, createInitialV2State, defaultValueFor, expireUserAction, generateId, getOptions, isNestedOrUnsupported, isRequired, migrateActiveStream, processStreamEventV2, renderableFields, resendUserAction, streamWorkflowEvents, submitUserAction, useChatV2, useVoice, validateField, validateForm };
652
+ export { type APIConfig, type ActiveUserAction, type AgentStage, type AnalysisMode, type ChatCallbacks, type ChatConfig, type ChunkDisplay, type FieldWidget, type JsonSchemaField, type JsonSchemaOption, type MessageDisplay, type MessageFeedbackState, type MessageRole, type RequestedSchema, type SendMessageOptions, type SessionParams, type StreamEvent, type StreamOptions, type StreamProgress, type StreamingStep, type UseChatV2Return, type UseVoiceReturn, type UserActionKind, type UserActionRequest, UserActionStaleError, type UserActionState, type UserActionStatus, type UserActionSubAction, type UserNotification, type V2EventProcessorState, type VerificationType, type VoiceCallbacks, type VoiceConfig, type VoicePermissions, type VoiceResult, type VoiceState, 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 };
package/dist/index.d.ts CHANGED
@@ -124,6 +124,8 @@ type UserActionRequest = {
124
124
  subAction?: UserActionSubAction | (string & {});
125
125
  verificationType?: VerificationType;
126
126
  expirySeconds?: number;
127
+ /** Wall-clock expiry (epoch ms). Set when the prompt is first received. */
128
+ expiresAt?: number;
127
129
  message?: string;
128
130
  requestedSchema?: RequestedSchema;
129
131
  metadata?: Record<string, string>;
@@ -639,6 +641,12 @@ declare function cancelUserAction(config: ChatConfig, userActionId: string): Pro
639
641
  declare function resendUserAction(config: ChatConfig, userActionId: string): Promise<UserActionResponse>;
640
642
  declare function expireUserAction(config: ChatConfig, userActionId: string): Promise<UserActionResponse>;
641
643
 
644
+ /** Wall-clock deadline (epoch ms) for a prompt with a positive TTL. */
645
+ declare function resolveUserActionExpiresAt(req: UserActionRequest, existing?: ActiveUserAction): number | undefined;
646
+ /** Seconds remaining before expiry, or undefined when the prompt has no TTL. */
647
+ declare function getUserActionSecondsLeft(prompt: ActiveUserAction): number | undefined;
648
+ declare function isUserActionExpired(prompt: ActiveUserAction): boolean;
649
+
642
650
  declare function migrateActiveStream(oldUserId: string, newUserId: string): void;
643
651
 
644
- export { type APIConfig, type ActiveUserAction, type AgentStage, type AnalysisMode, type ChatCallbacks, type ChatConfig, type ChunkDisplay, type FieldWidget, type JsonSchemaField, type JsonSchemaOption, type MessageDisplay, type MessageFeedbackState, type MessageRole, type RequestedSchema, type SendMessageOptions, type SessionParams, type StreamEvent, type StreamOptions, type StreamProgress, type StreamingStep, type UseChatV2Return, type UseVoiceReturn, type UserActionKind, type UserActionRequest, UserActionStaleError, type UserActionState, type UserActionStatus, type UserActionSubAction, type UserNotification, type V2EventProcessorState, type VerificationType, type VoiceCallbacks, type VoiceConfig, type VoicePermissions, type VoiceResult, type VoiceState, buildContent, cancelUserAction, classifyField, classifyUserActionKind, coerceValue, createInitialV2State, defaultValueFor, expireUserAction, generateId, getOptions, isNestedOrUnsupported, isRequired, migrateActiveStream, processStreamEventV2, renderableFields, resendUserAction, streamWorkflowEvents, submitUserAction, useChatV2, useVoice, validateField, validateForm };
652
+ export { type APIConfig, type ActiveUserAction, type AgentStage, type AnalysisMode, type ChatCallbacks, type ChatConfig, type ChunkDisplay, type FieldWidget, type JsonSchemaField, type JsonSchemaOption, type MessageDisplay, type MessageFeedbackState, type MessageRole, type RequestedSchema, type SendMessageOptions, type SessionParams, type StreamEvent, type StreamOptions, type StreamProgress, type StreamingStep, type UseChatV2Return, type UseVoiceReturn, type UserActionKind, type UserActionRequest, UserActionStaleError, type UserActionState, type UserActionStatus, type UserActionSubAction, type UserNotification, type V2EventProcessorState, type VerificationType, type VoiceCallbacks, type VoiceConfig, type VoicePermissions, type VoiceResult, type VoiceState, 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 };
package/dist/index.js CHANGED
@@ -30,6 +30,7 @@ var chatStore = {
30
30
  };
31
31
 
32
32
  // src/utils/activeStreamStore.ts
33
+ var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
33
34
  var streams = /* @__PURE__ */ new Map();
34
35
  var activeStreamStore = {
35
36
  has(key) {
@@ -38,7 +39,11 @@ var activeStreamStore = {
38
39
  get(key) {
39
40
  const entry = streams.get(key);
40
41
  if (!entry) return null;
41
- return { messages: entry.messages, isWaiting: entry.isWaiting };
42
+ return {
43
+ messages: entry.messages,
44
+ isWaiting: entry.isWaiting,
45
+ userActionState: entry.userActionState
46
+ };
42
47
  },
43
48
  // Called before startStream — registers the controller and initial messages
44
49
  start(key, abortController, initialMessages) {
@@ -46,6 +51,7 @@ var activeStreamStore = {
46
51
  streams.set(key, {
47
52
  messages: initialMessages,
48
53
  isWaiting: true,
54
+ userActionState: EMPTY_USER_ACTION_STATE,
49
55
  abortController,
50
56
  listeners: existing?.listeners ?? /* @__PURE__ */ new Set()
51
57
  });
@@ -56,20 +62,27 @@ var activeStreamStore = {
56
62
  if (!entry) return;
57
63
  const next = typeof updater === "function" ? updater(entry.messages) : updater;
58
64
  entry.messages = next;
59
- entry.listeners.forEach((l) => l(next, entry.isWaiting));
65
+ entry.listeners.forEach((l) => l(next, entry.isWaiting, entry.userActionState));
60
66
  },
61
67
  setWaiting(key, waiting) {
62
68
  const entry = streams.get(key);
63
69
  if (!entry) return;
64
70
  entry.isWaiting = waiting;
65
- entry.listeners.forEach((l) => l(entry.messages, waiting));
71
+ entry.listeners.forEach((l) => l(entry.messages, waiting, entry.userActionState));
72
+ },
73
+ applyUserActionState(key, updater) {
74
+ const entry = streams.get(key);
75
+ if (!entry) return;
76
+ const next = typeof updater === "function" ? updater(entry.userActionState) : updater;
77
+ entry.userActionState = next;
78
+ entry.listeners.forEach((l) => l(entry.messages, entry.isWaiting, next));
66
79
  },
67
80
  // Called when stream completes — persists to chatStore and cleans up
68
81
  complete(key) {
69
82
  const entry = streams.get(key);
70
83
  if (!entry) return;
71
84
  entry.isWaiting = false;
72
- entry.listeners.forEach((l) => l(entry.messages, false));
85
+ entry.listeners.forEach((l) => l(entry.messages, false, entry.userActionState));
73
86
  const toSave = entry.messages.filter((m) => !m.isStreaming);
74
87
  if (toSave.length > 0) chatStore.set(key, toSave);
75
88
  streams.delete(key);
@@ -1094,13 +1107,38 @@ async function expireUserAction(config, userActionId) {
1094
1107
  return sendUserActionRequest(config, userActionId, "expired");
1095
1108
  }
1096
1109
 
1110
+ // src/utils/userActionExpiry.ts
1111
+ function resolveUserActionExpiresAt(req, existing) {
1112
+ if (typeof req.expirySeconds !== "number" || req.expirySeconds <= 0) {
1113
+ return void 0;
1114
+ }
1115
+ if (existing?.expiresAt && existing.userActionId === req.userActionId) {
1116
+ return existing.expiresAt;
1117
+ }
1118
+ return Date.now() + Math.floor(req.expirySeconds) * 1e3;
1119
+ }
1120
+ function getUserActionSecondsLeft(prompt) {
1121
+ if (typeof prompt.expiresAt === "number" && prompt.expiresAt > 0) {
1122
+ return Math.max(0, Math.ceil((prompt.expiresAt - Date.now()) / 1e3));
1123
+ }
1124
+ if (typeof prompt.expirySeconds === "number" && prompt.expirySeconds > 0) {
1125
+ return Math.floor(prompt.expirySeconds);
1126
+ }
1127
+ return void 0;
1128
+ }
1129
+ function isUserActionExpired(prompt) {
1130
+ const left = getUserActionSecondsLeft(prompt);
1131
+ return left !== void 0 && left <= 0;
1132
+ }
1133
+
1097
1134
  // src/hooks/useChatV2.ts
1098
- var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
1135
+ var EMPTY_USER_ACTION_STATE2 = { prompts: [], notifications: [] };
1099
1136
  function upsertPrompt(prompts, req) {
1100
- const active = { ...req, status: "pending" };
1101
1137
  const idx = prompts.findIndex(
1102
1138
  (p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
1103
1139
  );
1140
+ const expiresAt = resolveUserActionExpiresAt(req, idx >= 0 ? prompts[idx] : void 0);
1141
+ const active = { ...req, status: "pending", expiresAt };
1104
1142
  if (idx >= 0) {
1105
1143
  const next = prompts.slice();
1106
1144
  next[idx] = active;
@@ -1171,7 +1209,28 @@ function useChatV2(config, callbacks = {}) {
1171
1209
  // eslint-disable-next-line react-hooks/exhaustive-deps
1172
1210
  []
1173
1211
  );
1174
- const [userActionState, setUserActionState] = react.useState(EMPTY_USER_ACTION_STATE);
1212
+ const [userActionState, setUserActionState] = react.useState(() => {
1213
+ if (!config.userId) return EMPTY_USER_ACTION_STATE2;
1214
+ return activeStreamStore.get(config.userId)?.userActionState ?? EMPTY_USER_ACTION_STATE2;
1215
+ });
1216
+ const storeAwareSetUserActionState = react.useCallback(
1217
+ (updater) => {
1218
+ const streamUserId = streamUserIdRef.current;
1219
+ const currentUserId = configRef.current.userId;
1220
+ const storeKey = streamUserId ?? currentUserId;
1221
+ if (storeKey && activeStreamStore.has(storeKey)) {
1222
+ activeStreamStore.applyUserActionState(
1223
+ storeKey,
1224
+ updater
1225
+ );
1226
+ }
1227
+ if (!streamUserId || streamUserId === currentUserId) {
1228
+ setUserActionState(updater);
1229
+ }
1230
+ },
1231
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1232
+ []
1233
+ );
1175
1234
  const wrappedCallbacks = react.useMemo(() => ({
1176
1235
  ...callbacksRef.current,
1177
1236
  onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
@@ -1181,14 +1240,14 @@ function useChatV2(config, callbacks = {}) {
1181
1240
  onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
1182
1241
  onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
1183
1242
  onUserActionRequired: (request) => {
1184
- setUserActionState((prev) => ({
1243
+ storeAwareSetUserActionState((prev) => ({
1185
1244
  ...prev,
1186
1245
  prompts: upsertPrompt(prev.prompts, request)
1187
1246
  }));
1188
1247
  callbacksRef.current.onUserActionRequired?.(request);
1189
1248
  },
1190
1249
  onUserNotification: (notification) => {
1191
- setUserActionState(
1250
+ storeAwareSetUserActionState(
1192
1251
  (prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
1193
1252
  );
1194
1253
  callbacksRef.current.onUserNotification?.(notification);
@@ -1278,7 +1337,7 @@ function useChatV2(config, callbacks = {}) {
1278
1337
  streamUserIdRef.current = void 0;
1279
1338
  cancelStreamManager();
1280
1339
  setIsWaitingForResponse(false);
1281
- setUserActionState((prev) => ({ ...prev, prompts: [] }));
1340
+ storeAwareSetUserActionState((prev) => ({ ...prev, prompts: [] }));
1282
1341
  setMessages(
1283
1342
  (prev) => prev.map((msg) => {
1284
1343
  if (msg.isStreaming) {
@@ -1293,7 +1352,7 @@ function useChatV2(config, callbacks = {}) {
1293
1352
  return msg;
1294
1353
  })
1295
1354
  );
1296
- }, [cancelStreamManager]);
1355
+ }, [cancelStreamManager, storeAwareSetUserActionState]);
1297
1356
  const resetSession = react.useCallback(() => {
1298
1357
  const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
1299
1358
  if (streamUserId) {
@@ -1307,7 +1366,7 @@ function useChatV2(config, callbacks = {}) {
1307
1366
  sessionIdRef.current = void 0;
1308
1367
  abortControllerRef.current?.abort();
1309
1368
  setIsWaitingForResponse(false);
1310
- setUserActionState(EMPTY_USER_ACTION_STATE);
1369
+ storeAwareSetUserActionState(EMPTY_USER_ACTION_STATE2);
1311
1370
  }, []);
1312
1371
  const getSessionId = react.useCallback(() => {
1313
1372
  return sessionIdRef.current;
@@ -1317,21 +1376,21 @@ function useChatV2(config, callbacks = {}) {
1317
1376
  }, [messages]);
1318
1377
  const setPromptStatus = react.useCallback(
1319
1378
  (userActionId, status) => {
1320
- setUserActionState((prev) => ({
1379
+ storeAwareSetUserActionState((prev) => ({
1321
1380
  ...prev,
1322
1381
  prompts: prev.prompts.map(
1323
1382
  (p) => p.userActionId === userActionId ? { ...p, status } : p
1324
1383
  )
1325
1384
  }));
1326
1385
  },
1327
- []
1386
+ [storeAwareSetUserActionState]
1328
1387
  );
1329
1388
  const removePrompt = react.useCallback((userActionId) => {
1330
- setUserActionState((prev) => ({
1389
+ storeAwareSetUserActionState((prev) => ({
1331
1390
  ...prev,
1332
1391
  prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
1333
1392
  }));
1334
- }, []);
1393
+ }, [storeAwareSetUserActionState]);
1335
1394
  const submitUserAction2 = react.useCallback(
1336
1395
  async (userActionId, content) => {
1337
1396
  setPromptStatus(userActionId, "submitting");
@@ -1400,11 +1459,11 @@ function useChatV2(config, callbacks = {}) {
1400
1459
  [setPromptStatus]
1401
1460
  );
1402
1461
  const dismissNotification = react.useCallback((id) => {
1403
- setUserActionState((prev) => ({
1462
+ storeAwareSetUserActionState((prev) => ({
1404
1463
  ...prev,
1405
1464
  notifications: prev.notifications.filter((n) => n.id !== id)
1406
1465
  }));
1407
- }, []);
1466
+ }, [storeAwareSetUserActionState]);
1408
1467
  react.useEffect(() => {
1409
1468
  const prevSubscriptionUserId = subscriptionPrevUserIdRef.current;
1410
1469
  subscriptionPrevUserIdRef.current = config.userId;
@@ -1413,14 +1472,17 @@ function useChatV2(config, callbacks = {}) {
1413
1472
  if (prevSubscriptionUserId && prevSubscriptionUserId !== userId && streamUserIdRef.current === prevSubscriptionUserId && !activeStreamStore.has(prevSubscriptionUserId) && activeStreamStore.has(userId)) {
1414
1473
  streamUserIdRef.current = userId;
1415
1474
  }
1416
- const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
1475
+ const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting, actions) => {
1417
1476
  setMessages(msgs);
1418
1477
  setIsWaitingForResponse(isWaiting);
1478
+ setUserActionState(actions);
1419
1479
  });
1420
1480
  const active = activeStreamStore.get(userId);
1421
1481
  if (active) {
1482
+ streamUserIdRef.current = userId;
1422
1483
  setMessages(active.messages);
1423
1484
  setIsWaitingForResponse(active.isWaiting);
1485
+ setUserActionState(active.userActionState);
1424
1486
  }
1425
1487
  return unsubscribe;
1426
1488
  }, [config.userId]);
@@ -1448,12 +1510,14 @@ function useChatV2(config, callbacks = {}) {
1448
1510
  setMessages([]);
1449
1511
  sessionIdRef.current = void 0;
1450
1512
  setIsWaitingForResponse(false);
1451
- setUserActionState(EMPTY_USER_ACTION_STATE);
1513
+ setUserActionState(EMPTY_USER_ACTION_STATE2);
1452
1514
  } else if (config.userId) {
1453
1515
  const active = activeStreamStore.get(config.userId);
1454
1516
  if (active) {
1517
+ streamUserIdRef.current = config.userId;
1455
1518
  setMessages(active.messages);
1456
1519
  setIsWaitingForResponse(active.isWaiting);
1520
+ setUserActionState(active.userActionState);
1457
1521
  sessionIdRef.current = getSessionIdFromMessages(active.messages) ?? config.initialSessionId;
1458
1522
  return;
1459
1523
  }
@@ -1832,12 +1896,15 @@ exports.defaultValueFor = defaultValueFor;
1832
1896
  exports.expireUserAction = expireUserAction;
1833
1897
  exports.generateId = generateId;
1834
1898
  exports.getOptions = getOptions;
1899
+ exports.getUserActionSecondsLeft = getUserActionSecondsLeft;
1835
1900
  exports.isNestedOrUnsupported = isNestedOrUnsupported;
1836
1901
  exports.isRequired = isRequired;
1902
+ exports.isUserActionExpired = isUserActionExpired;
1837
1903
  exports.migrateActiveStream = migrateActiveStream;
1838
1904
  exports.processStreamEventV2 = processStreamEventV2;
1839
1905
  exports.renderableFields = renderableFields;
1840
1906
  exports.resendUserAction = resendUserAction;
1907
+ exports.resolveUserActionExpiresAt = resolveUserActionExpiresAt;
1841
1908
  exports.streamWorkflowEvents = streamWorkflowEvents;
1842
1909
  exports.submitUserAction = submitUserAction;
1843
1910
  exports.useChatV2 = useChatV2;