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

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);
@@ -284,6 +297,8 @@ function getEventMessage(event) {
284
297
  }
285
298
  case "RUN_IN_PROGRESS":
286
299
  return event.partialText || "Thinking...";
300
+ case "LLM_CALL_STARTED":
301
+ return event.description || "";
287
302
  case "RUN_COMPLETED":
288
303
  return "Agent run completed";
289
304
  case "RUN_FAILED":
@@ -421,7 +436,8 @@ function createInitialV2State() {
421
436
  finalData: void 0,
422
437
  steps: [],
423
438
  stepCounter: 0,
424
- currentExecutingStepId: void 0
439
+ currentExecutingStepId: void 0,
440
+ trailingActivity: false
425
441
  };
426
442
  }
427
443
  function upsertUserAction(state, req) {
@@ -443,6 +459,7 @@ function processStreamEventV2(rawEvent, state) {
443
459
  if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
444
460
  if (event.executionId) state.executionId = event.executionId;
445
461
  if (event.sessionId) state.sessionId = event.sessionId;
462
+ if (state.finalResponse) state.trailingActivity = true;
446
463
  const description = typeof event.description === "string" ? event.description : "";
447
464
  if (description) {
448
465
  for (let i = state.steps.length - 1; i >= 0; i--) {
@@ -477,7 +494,12 @@ function processStreamEventV2(rawEvent, state) {
477
494
  state.lastEventType = eventType;
478
495
  break;
479
496
  }
497
+ case "LLM_CALL_STARTED":
498
+ if (state.finalResponse) state.trailingActivity = true;
499
+ state.lastEventType = eventType;
500
+ break;
480
501
  case "INTENT_STARTED": {
502
+ if (state.finalResponse) state.trailingActivity = true;
481
503
  const stepId = `step-${state.stepCounter++}`;
482
504
  state.steps.push({
483
505
  id: stepId,
@@ -493,6 +515,7 @@ function processStreamEventV2(rawEvent, state) {
493
515
  break;
494
516
  }
495
517
  case "INTENT_COMPLETED": {
518
+ if (state.finalResponse) state.trailingActivity = true;
496
519
  const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
497
520
  if (intentStep) {
498
521
  intentStep.status = "completed";
@@ -524,6 +547,7 @@ function processStreamEventV2(rawEvent, state) {
524
547
  step.status = "completed";
525
548
  }
526
549
  });
550
+ state.trailingActivity = false;
527
551
  state.lastEventType = eventType;
528
552
  break;
529
553
  }
@@ -595,6 +619,7 @@ function processStreamEventV2(rawEvent, state) {
595
619
  case "WORKFLOW_ERROR":
596
620
  state.hasError = true;
597
621
  state.errorMessage = event.errorMessage || event.message || "Workflow error";
622
+ state.trailingActivity = false;
598
623
  state.lastEventType = eventType;
599
624
  break;
600
625
  // ---- K2 pipeline stage lifecycle events ----
@@ -889,7 +914,9 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
889
914
  const latestUsefulStep = [...state.steps].reverse().find(
890
915
  (s) => s.message && !isBlandStatus(s.message)
891
916
  );
892
- const currentMessage = useful(activeStep?.message) ?? useful(lastInProgressStep?.message) ?? latestUsefulStep?.message ?? useful(getEventMessage(event)) ?? // Last-resort: every candidate is bland (very first event,
917
+ const eventTypeUpper = typeof event.eventType === "string" ? event.eventType.toUpperCase() : "";
918
+ const liveEventLabel = eventTypeUpper === "KEEP_ALIVE" || eventTypeUpper === "LLM_CALL_STARTED" ? useful(getEventMessage(event)) : void 0;
919
+ const currentMessage = useful(activeStep?.message) ?? useful(lastInProgressStep?.message) ?? liveEventLabel ?? latestUsefulStep?.message ?? useful(getEventMessage(event)) ?? // Last-resort: every candidate is bland (very first event,
893
920
  // nothing useful seen yet). Render the bland label so the
894
921
  // bubble isn't blank.
895
922
  activeStep?.message ?? lastInProgressStep?.message ?? getEventMessage(event);
@@ -914,6 +941,7 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
914
941
  streamingContent: state.finalResponse,
915
942
  content: "",
916
943
  currentMessage,
944
+ hasTrailingActivity: state.trailingActivity,
917
945
  streamProgress: "processing",
918
946
  isError: false,
919
947
  steps: [...state.steps],
@@ -1115,13 +1143,38 @@ async function expireUserAction(config, userActionId) {
1115
1143
  return sendUserActionRequest(config, userActionId, "expired");
1116
1144
  }
1117
1145
 
1146
+ // src/utils/userActionExpiry.ts
1147
+ function resolveUserActionExpiresAt(req, existing) {
1148
+ if (typeof req.expirySeconds !== "number" || req.expirySeconds <= 0) {
1149
+ return void 0;
1150
+ }
1151
+ if (existing?.expiresAt && existing.userActionId === req.userActionId) {
1152
+ return existing.expiresAt;
1153
+ }
1154
+ return Date.now() + Math.floor(req.expirySeconds) * 1e3;
1155
+ }
1156
+ function getUserActionSecondsLeft(prompt) {
1157
+ if (typeof prompt.expiresAt === "number" && prompt.expiresAt > 0) {
1158
+ return Math.max(0, Math.ceil((prompt.expiresAt - Date.now()) / 1e3));
1159
+ }
1160
+ if (typeof prompt.expirySeconds === "number" && prompt.expirySeconds > 0) {
1161
+ return Math.floor(prompt.expirySeconds);
1162
+ }
1163
+ return void 0;
1164
+ }
1165
+ function isUserActionExpired(prompt) {
1166
+ const left = getUserActionSecondsLeft(prompt);
1167
+ return left !== void 0 && left <= 0;
1168
+ }
1169
+
1118
1170
  // src/hooks/useChatV2.ts
1119
- var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
1171
+ var EMPTY_USER_ACTION_STATE2 = { prompts: [], notifications: [] };
1120
1172
  function upsertPrompt(prompts, req) {
1121
- const active = { ...req, status: "pending" };
1122
1173
  const idx = prompts.findIndex(
1123
1174
  (p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
1124
1175
  );
1176
+ const expiresAt = resolveUserActionExpiresAt(req, idx >= 0 ? prompts[idx] : void 0);
1177
+ const active = { ...req, status: "pending", expiresAt };
1125
1178
  if (idx >= 0) {
1126
1179
  const next = prompts.slice();
1127
1180
  next[idx] = active;
@@ -1192,7 +1245,28 @@ function useChatV2(config, callbacks = {}) {
1192
1245
  // eslint-disable-next-line react-hooks/exhaustive-deps
1193
1246
  []
1194
1247
  );
1195
- const [userActionState, setUserActionState] = react.useState(EMPTY_USER_ACTION_STATE);
1248
+ const [userActionState, setUserActionState] = react.useState(() => {
1249
+ if (!config.userId) return EMPTY_USER_ACTION_STATE2;
1250
+ return activeStreamStore.get(config.userId)?.userActionState ?? EMPTY_USER_ACTION_STATE2;
1251
+ });
1252
+ const storeAwareSetUserActionState = react.useCallback(
1253
+ (updater) => {
1254
+ const streamUserId = streamUserIdRef.current;
1255
+ const currentUserId = configRef.current.userId;
1256
+ const storeKey = streamUserId ?? currentUserId;
1257
+ if (storeKey && activeStreamStore.has(storeKey)) {
1258
+ activeStreamStore.applyUserActionState(
1259
+ storeKey,
1260
+ updater
1261
+ );
1262
+ }
1263
+ if (!streamUserId || streamUserId === currentUserId) {
1264
+ setUserActionState(updater);
1265
+ }
1266
+ },
1267
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1268
+ []
1269
+ );
1196
1270
  const wrappedCallbacks = react.useMemo(() => ({
1197
1271
  ...callbacksRef.current,
1198
1272
  onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
@@ -1202,14 +1276,14 @@ function useChatV2(config, callbacks = {}) {
1202
1276
  onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
1203
1277
  onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
1204
1278
  onUserActionRequired: (request) => {
1205
- setUserActionState((prev) => ({
1279
+ storeAwareSetUserActionState((prev) => ({
1206
1280
  ...prev,
1207
1281
  prompts: upsertPrompt(prev.prompts, request)
1208
1282
  }));
1209
1283
  callbacksRef.current.onUserActionRequired?.(request);
1210
1284
  },
1211
1285
  onUserNotification: (notification) => {
1212
- setUserActionState(
1286
+ storeAwareSetUserActionState(
1213
1287
  (prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
1214
1288
  );
1215
1289
  callbacksRef.current.onUserNotification?.(notification);
@@ -1299,7 +1373,7 @@ function useChatV2(config, callbacks = {}) {
1299
1373
  streamUserIdRef.current = void 0;
1300
1374
  cancelStreamManager();
1301
1375
  setIsWaitingForResponse(false);
1302
- setUserActionState((prev) => ({ ...prev, prompts: [] }));
1376
+ storeAwareSetUserActionState((prev) => ({ ...prev, prompts: [] }));
1303
1377
  setMessages(
1304
1378
  (prev) => prev.map((msg) => {
1305
1379
  if (msg.isStreaming) {
@@ -1314,7 +1388,7 @@ function useChatV2(config, callbacks = {}) {
1314
1388
  return msg;
1315
1389
  })
1316
1390
  );
1317
- }, [cancelStreamManager]);
1391
+ }, [cancelStreamManager, storeAwareSetUserActionState]);
1318
1392
  const resetSession = react.useCallback(() => {
1319
1393
  const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
1320
1394
  if (streamUserId) {
@@ -1328,7 +1402,7 @@ function useChatV2(config, callbacks = {}) {
1328
1402
  sessionIdRef.current = void 0;
1329
1403
  abortControllerRef.current?.abort();
1330
1404
  setIsWaitingForResponse(false);
1331
- setUserActionState(EMPTY_USER_ACTION_STATE);
1405
+ storeAwareSetUserActionState(EMPTY_USER_ACTION_STATE2);
1332
1406
  }, []);
1333
1407
  const getSessionId = react.useCallback(() => {
1334
1408
  return sessionIdRef.current;
@@ -1338,21 +1412,21 @@ function useChatV2(config, callbacks = {}) {
1338
1412
  }, [messages]);
1339
1413
  const setPromptStatus = react.useCallback(
1340
1414
  (userActionId, status) => {
1341
- setUserActionState((prev) => ({
1415
+ storeAwareSetUserActionState((prev) => ({
1342
1416
  ...prev,
1343
1417
  prompts: prev.prompts.map(
1344
1418
  (p) => p.userActionId === userActionId ? { ...p, status } : p
1345
1419
  )
1346
1420
  }));
1347
1421
  },
1348
- []
1422
+ [storeAwareSetUserActionState]
1349
1423
  );
1350
1424
  const removePrompt = react.useCallback((userActionId) => {
1351
- setUserActionState((prev) => ({
1425
+ storeAwareSetUserActionState((prev) => ({
1352
1426
  ...prev,
1353
1427
  prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
1354
1428
  }));
1355
- }, []);
1429
+ }, [storeAwareSetUserActionState]);
1356
1430
  const submitUserAction2 = react.useCallback(
1357
1431
  async (userActionId, content) => {
1358
1432
  setPromptStatus(userActionId, "submitting");
@@ -1421,11 +1495,11 @@ function useChatV2(config, callbacks = {}) {
1421
1495
  [setPromptStatus]
1422
1496
  );
1423
1497
  const dismissNotification = react.useCallback((id) => {
1424
- setUserActionState((prev) => ({
1498
+ storeAwareSetUserActionState((prev) => ({
1425
1499
  ...prev,
1426
1500
  notifications: prev.notifications.filter((n) => n.id !== id)
1427
1501
  }));
1428
- }, []);
1502
+ }, [storeAwareSetUserActionState]);
1429
1503
  react.useEffect(() => {
1430
1504
  const prevSubscriptionUserId = subscriptionPrevUserIdRef.current;
1431
1505
  subscriptionPrevUserIdRef.current = config.userId;
@@ -1434,14 +1508,17 @@ function useChatV2(config, callbacks = {}) {
1434
1508
  if (prevSubscriptionUserId && prevSubscriptionUserId !== userId && streamUserIdRef.current === prevSubscriptionUserId && !activeStreamStore.has(prevSubscriptionUserId) && activeStreamStore.has(userId)) {
1435
1509
  streamUserIdRef.current = userId;
1436
1510
  }
1437
- const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
1511
+ const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting, actions) => {
1438
1512
  setMessages(msgs);
1439
1513
  setIsWaitingForResponse(isWaiting);
1514
+ setUserActionState(actions);
1440
1515
  });
1441
1516
  const active = activeStreamStore.get(userId);
1442
1517
  if (active) {
1518
+ streamUserIdRef.current = userId;
1443
1519
  setMessages(active.messages);
1444
1520
  setIsWaitingForResponse(active.isWaiting);
1521
+ setUserActionState(active.userActionState);
1445
1522
  }
1446
1523
  return unsubscribe;
1447
1524
  }, [config.userId]);
@@ -1469,12 +1546,14 @@ function useChatV2(config, callbacks = {}) {
1469
1546
  setMessages([]);
1470
1547
  sessionIdRef.current = void 0;
1471
1548
  setIsWaitingForResponse(false);
1472
- setUserActionState(EMPTY_USER_ACTION_STATE);
1549
+ setUserActionState(EMPTY_USER_ACTION_STATE2);
1473
1550
  } else if (config.userId) {
1474
1551
  const active = activeStreamStore.get(config.userId);
1475
1552
  if (active) {
1553
+ streamUserIdRef.current = config.userId;
1476
1554
  setMessages(active.messages);
1477
1555
  setIsWaitingForResponse(active.isWaiting);
1556
+ setUserActionState(active.userActionState);
1478
1557
  sessionIdRef.current = getSessionIdFromMessages(active.messages) ?? config.initialSessionId;
1479
1558
  return;
1480
1559
  }
@@ -1753,12 +1832,15 @@ exports.defaultValueFor = defaultValueFor;
1753
1832
  exports.expireUserAction = expireUserAction;
1754
1833
  exports.generateId = generateId;
1755
1834
  exports.getOptions = getOptions;
1835
+ exports.getUserActionSecondsLeft = getUserActionSecondsLeft;
1756
1836
  exports.isNestedOrUnsupported = isNestedOrUnsupported;
1757
1837
  exports.isRequired = isRequired;
1838
+ exports.isUserActionExpired = isUserActionExpired;
1758
1839
  exports.migrateActiveStream = migrateActiveStream;
1759
1840
  exports.processStreamEventV2 = processStreamEventV2;
1760
1841
  exports.renderableFields = renderableFields;
1761
1842
  exports.resendUserAction = resendUserAction;
1843
+ exports.resolveUserActionExpiresAt = resolveUserActionExpiresAt;
1762
1844
  exports.streamWorkflowEvents = streamWorkflowEvents;
1763
1845
  exports.submitUserAction = submitUserAction;
1764
1846
  exports.useChatV2 = useChatV2;