@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.
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);
@@ -261,6 +274,8 @@ function getEventMessage(event) {
261
274
  }
262
275
  case "RUN_IN_PROGRESS":
263
276
  return event.partialText || "Thinking...";
277
+ case "LLM_CALL_STARTED":
278
+ return event.description || "";
264
279
  case "RUN_COMPLETED":
265
280
  return "Agent run completed";
266
281
  case "RUN_FAILED":
@@ -398,7 +413,8 @@ function createInitialV2State() {
398
413
  finalData: void 0,
399
414
  steps: [],
400
415
  stepCounter: 0,
401
- currentExecutingStepId: void 0
416
+ currentExecutingStepId: void 0,
417
+ trailingActivity: false
402
418
  };
403
419
  }
404
420
  function upsertUserAction(state, req) {
@@ -420,6 +436,7 @@ function processStreamEventV2(rawEvent, state) {
420
436
  if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
421
437
  if (event.executionId) state.executionId = event.executionId;
422
438
  if (event.sessionId) state.sessionId = event.sessionId;
439
+ if (state.finalResponse) state.trailingActivity = true;
423
440
  const description = typeof event.description === "string" ? event.description : "";
424
441
  if (description) {
425
442
  for (let i = state.steps.length - 1; i >= 0; i--) {
@@ -454,7 +471,12 @@ function processStreamEventV2(rawEvent, state) {
454
471
  state.lastEventType = eventType;
455
472
  break;
456
473
  }
474
+ case "LLM_CALL_STARTED":
475
+ if (state.finalResponse) state.trailingActivity = true;
476
+ state.lastEventType = eventType;
477
+ break;
457
478
  case "INTENT_STARTED": {
479
+ if (state.finalResponse) state.trailingActivity = true;
458
480
  const stepId = `step-${state.stepCounter++}`;
459
481
  state.steps.push({
460
482
  id: stepId,
@@ -470,6 +492,7 @@ function processStreamEventV2(rawEvent, state) {
470
492
  break;
471
493
  }
472
494
  case "INTENT_COMPLETED": {
495
+ if (state.finalResponse) state.trailingActivity = true;
473
496
  const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
474
497
  if (intentStep) {
475
498
  intentStep.status = "completed";
@@ -501,6 +524,7 @@ function processStreamEventV2(rawEvent, state) {
501
524
  step.status = "completed";
502
525
  }
503
526
  });
527
+ state.trailingActivity = false;
504
528
  state.lastEventType = eventType;
505
529
  break;
506
530
  }
@@ -572,6 +596,7 @@ function processStreamEventV2(rawEvent, state) {
572
596
  case "WORKFLOW_ERROR":
573
597
  state.hasError = true;
574
598
  state.errorMessage = event.errorMessage || event.message || "Workflow error";
599
+ state.trailingActivity = false;
575
600
  state.lastEventType = eventType;
576
601
  break;
577
602
  // ---- K2 pipeline stage lifecycle events ----
@@ -866,7 +891,9 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
866
891
  const latestUsefulStep = [...state.steps].reverse().find(
867
892
  (s) => s.message && !isBlandStatus(s.message)
868
893
  );
869
- const currentMessage = useful(activeStep?.message) ?? useful(lastInProgressStep?.message) ?? latestUsefulStep?.message ?? useful(getEventMessage(event)) ?? // Last-resort: every candidate is bland (very first event,
894
+ const eventTypeUpper = typeof event.eventType === "string" ? event.eventType.toUpperCase() : "";
895
+ const liveEventLabel = eventTypeUpper === "KEEP_ALIVE" || eventTypeUpper === "LLM_CALL_STARTED" ? useful(getEventMessage(event)) : void 0;
896
+ const currentMessage = useful(activeStep?.message) ?? useful(lastInProgressStep?.message) ?? liveEventLabel ?? latestUsefulStep?.message ?? useful(getEventMessage(event)) ?? // Last-resort: every candidate is bland (very first event,
870
897
  // nothing useful seen yet). Render the bland label so the
871
898
  // bubble isn't blank.
872
899
  activeStep?.message ?? lastInProgressStep?.message ?? getEventMessage(event);
@@ -891,6 +918,7 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
891
918
  streamingContent: state.finalResponse,
892
919
  content: "",
893
920
  currentMessage,
921
+ hasTrailingActivity: state.trailingActivity,
894
922
  streamProgress: "processing",
895
923
  isError: false,
896
924
  steps: [...state.steps],
@@ -1092,13 +1120,38 @@ async function expireUserAction(config, userActionId) {
1092
1120
  return sendUserActionRequest(config, userActionId, "expired");
1093
1121
  }
1094
1122
 
1123
+ // src/utils/userActionExpiry.ts
1124
+ function resolveUserActionExpiresAt(req, existing) {
1125
+ if (typeof req.expirySeconds !== "number" || req.expirySeconds <= 0) {
1126
+ return void 0;
1127
+ }
1128
+ if (existing?.expiresAt && existing.userActionId === req.userActionId) {
1129
+ return existing.expiresAt;
1130
+ }
1131
+ return Date.now() + Math.floor(req.expirySeconds) * 1e3;
1132
+ }
1133
+ function getUserActionSecondsLeft(prompt) {
1134
+ if (typeof prompt.expiresAt === "number" && prompt.expiresAt > 0) {
1135
+ return Math.max(0, Math.ceil((prompt.expiresAt - Date.now()) / 1e3));
1136
+ }
1137
+ if (typeof prompt.expirySeconds === "number" && prompt.expirySeconds > 0) {
1138
+ return Math.floor(prompt.expirySeconds);
1139
+ }
1140
+ return void 0;
1141
+ }
1142
+ function isUserActionExpired(prompt) {
1143
+ const left = getUserActionSecondsLeft(prompt);
1144
+ return left !== void 0 && left <= 0;
1145
+ }
1146
+
1095
1147
  // src/hooks/useChatV2.ts
1096
- var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
1148
+ var EMPTY_USER_ACTION_STATE2 = { prompts: [], notifications: [] };
1097
1149
  function upsertPrompt(prompts, req) {
1098
- const active = { ...req, status: "pending" };
1099
1150
  const idx = prompts.findIndex(
1100
1151
  (p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
1101
1152
  );
1153
+ const expiresAt = resolveUserActionExpiresAt(req, idx >= 0 ? prompts[idx] : void 0);
1154
+ const active = { ...req, status: "pending", expiresAt };
1102
1155
  if (idx >= 0) {
1103
1156
  const next = prompts.slice();
1104
1157
  next[idx] = active;
@@ -1169,7 +1222,28 @@ function useChatV2(config, callbacks = {}) {
1169
1222
  // eslint-disable-next-line react-hooks/exhaustive-deps
1170
1223
  []
1171
1224
  );
1172
- const [userActionState, setUserActionState] = useState(EMPTY_USER_ACTION_STATE);
1225
+ const [userActionState, setUserActionState] = useState(() => {
1226
+ if (!config.userId) return EMPTY_USER_ACTION_STATE2;
1227
+ return activeStreamStore.get(config.userId)?.userActionState ?? EMPTY_USER_ACTION_STATE2;
1228
+ });
1229
+ const storeAwareSetUserActionState = useCallback(
1230
+ (updater) => {
1231
+ const streamUserId = streamUserIdRef.current;
1232
+ const currentUserId = configRef.current.userId;
1233
+ const storeKey = streamUserId ?? currentUserId;
1234
+ if (storeKey && activeStreamStore.has(storeKey)) {
1235
+ activeStreamStore.applyUserActionState(
1236
+ storeKey,
1237
+ updater
1238
+ );
1239
+ }
1240
+ if (!streamUserId || streamUserId === currentUserId) {
1241
+ setUserActionState(updater);
1242
+ }
1243
+ },
1244
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1245
+ []
1246
+ );
1173
1247
  const wrappedCallbacks = useMemo(() => ({
1174
1248
  ...callbacksRef.current,
1175
1249
  onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
@@ -1179,14 +1253,14 @@ function useChatV2(config, callbacks = {}) {
1179
1253
  onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
1180
1254
  onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
1181
1255
  onUserActionRequired: (request) => {
1182
- setUserActionState((prev) => ({
1256
+ storeAwareSetUserActionState((prev) => ({
1183
1257
  ...prev,
1184
1258
  prompts: upsertPrompt(prev.prompts, request)
1185
1259
  }));
1186
1260
  callbacksRef.current.onUserActionRequired?.(request);
1187
1261
  },
1188
1262
  onUserNotification: (notification) => {
1189
- setUserActionState(
1263
+ storeAwareSetUserActionState(
1190
1264
  (prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
1191
1265
  );
1192
1266
  callbacksRef.current.onUserNotification?.(notification);
@@ -1276,7 +1350,7 @@ function useChatV2(config, callbacks = {}) {
1276
1350
  streamUserIdRef.current = void 0;
1277
1351
  cancelStreamManager();
1278
1352
  setIsWaitingForResponse(false);
1279
- setUserActionState((prev) => ({ ...prev, prompts: [] }));
1353
+ storeAwareSetUserActionState((prev) => ({ ...prev, prompts: [] }));
1280
1354
  setMessages(
1281
1355
  (prev) => prev.map((msg) => {
1282
1356
  if (msg.isStreaming) {
@@ -1291,7 +1365,7 @@ function useChatV2(config, callbacks = {}) {
1291
1365
  return msg;
1292
1366
  })
1293
1367
  );
1294
- }, [cancelStreamManager]);
1368
+ }, [cancelStreamManager, storeAwareSetUserActionState]);
1295
1369
  const resetSession = useCallback(() => {
1296
1370
  const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
1297
1371
  if (streamUserId) {
@@ -1305,7 +1379,7 @@ function useChatV2(config, callbacks = {}) {
1305
1379
  sessionIdRef.current = void 0;
1306
1380
  abortControllerRef.current?.abort();
1307
1381
  setIsWaitingForResponse(false);
1308
- setUserActionState(EMPTY_USER_ACTION_STATE);
1382
+ storeAwareSetUserActionState(EMPTY_USER_ACTION_STATE2);
1309
1383
  }, []);
1310
1384
  const getSessionId = useCallback(() => {
1311
1385
  return sessionIdRef.current;
@@ -1315,21 +1389,21 @@ function useChatV2(config, callbacks = {}) {
1315
1389
  }, [messages]);
1316
1390
  const setPromptStatus = useCallback(
1317
1391
  (userActionId, status) => {
1318
- setUserActionState((prev) => ({
1392
+ storeAwareSetUserActionState((prev) => ({
1319
1393
  ...prev,
1320
1394
  prompts: prev.prompts.map(
1321
1395
  (p) => p.userActionId === userActionId ? { ...p, status } : p
1322
1396
  )
1323
1397
  }));
1324
1398
  },
1325
- []
1399
+ [storeAwareSetUserActionState]
1326
1400
  );
1327
1401
  const removePrompt = useCallback((userActionId) => {
1328
- setUserActionState((prev) => ({
1402
+ storeAwareSetUserActionState((prev) => ({
1329
1403
  ...prev,
1330
1404
  prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
1331
1405
  }));
1332
- }, []);
1406
+ }, [storeAwareSetUserActionState]);
1333
1407
  const submitUserAction2 = useCallback(
1334
1408
  async (userActionId, content) => {
1335
1409
  setPromptStatus(userActionId, "submitting");
@@ -1398,11 +1472,11 @@ function useChatV2(config, callbacks = {}) {
1398
1472
  [setPromptStatus]
1399
1473
  );
1400
1474
  const dismissNotification = useCallback((id) => {
1401
- setUserActionState((prev) => ({
1475
+ storeAwareSetUserActionState((prev) => ({
1402
1476
  ...prev,
1403
1477
  notifications: prev.notifications.filter((n) => n.id !== id)
1404
1478
  }));
1405
- }, []);
1479
+ }, [storeAwareSetUserActionState]);
1406
1480
  useEffect(() => {
1407
1481
  const prevSubscriptionUserId = subscriptionPrevUserIdRef.current;
1408
1482
  subscriptionPrevUserIdRef.current = config.userId;
@@ -1411,14 +1485,17 @@ function useChatV2(config, callbacks = {}) {
1411
1485
  if (prevSubscriptionUserId && prevSubscriptionUserId !== userId && streamUserIdRef.current === prevSubscriptionUserId && !activeStreamStore.has(prevSubscriptionUserId) && activeStreamStore.has(userId)) {
1412
1486
  streamUserIdRef.current = userId;
1413
1487
  }
1414
- const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
1488
+ const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting, actions) => {
1415
1489
  setMessages(msgs);
1416
1490
  setIsWaitingForResponse(isWaiting);
1491
+ setUserActionState(actions);
1417
1492
  });
1418
1493
  const active = activeStreamStore.get(userId);
1419
1494
  if (active) {
1495
+ streamUserIdRef.current = userId;
1420
1496
  setMessages(active.messages);
1421
1497
  setIsWaitingForResponse(active.isWaiting);
1498
+ setUserActionState(active.userActionState);
1422
1499
  }
1423
1500
  return unsubscribe;
1424
1501
  }, [config.userId]);
@@ -1446,12 +1523,14 @@ function useChatV2(config, callbacks = {}) {
1446
1523
  setMessages([]);
1447
1524
  sessionIdRef.current = void 0;
1448
1525
  setIsWaitingForResponse(false);
1449
- setUserActionState(EMPTY_USER_ACTION_STATE);
1526
+ setUserActionState(EMPTY_USER_ACTION_STATE2);
1450
1527
  } else if (config.userId) {
1451
1528
  const active = activeStreamStore.get(config.userId);
1452
1529
  if (active) {
1530
+ streamUserIdRef.current = config.userId;
1453
1531
  setMessages(active.messages);
1454
1532
  setIsWaitingForResponse(active.isWaiting);
1533
+ setUserActionState(active.userActionState);
1455
1534
  sessionIdRef.current = getSessionIdFromMessages(active.messages) ?? config.initialSessionId;
1456
1535
  return;
1457
1536
  }
@@ -1819,6 +1898,6 @@ function migrateActiveStream(oldUserId, newUserId) {
1819
1898
  activeStreamStore.rename(oldUserId, newUserId);
1820
1899
  }
1821
1900
 
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 };
1901
+ 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
1902
  //# sourceMappingURL=index.mjs.map
1824
1903
  //# sourceMappingURL=index.mjs.map