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

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.
@@ -297,6 +297,8 @@ function getEventMessage(event) {
297
297
  }
298
298
  case "RUN_IN_PROGRESS":
299
299
  return event.partialText || "Thinking...";
300
+ case "LLM_CALL_STARTED":
301
+ return event.description || "";
300
302
  case "RUN_COMPLETED":
301
303
  return "Agent run completed";
302
304
  case "RUN_FAILED":
@@ -434,7 +436,8 @@ function createInitialV2State() {
434
436
  finalData: void 0,
435
437
  steps: [],
436
438
  stepCounter: 0,
437
- currentExecutingStepId: void 0
439
+ currentExecutingStepId: void 0,
440
+ trailingActivity: false
438
441
  };
439
442
  }
440
443
  function upsertUserAction(state, req) {
@@ -456,6 +459,7 @@ function processStreamEventV2(rawEvent, state) {
456
459
  if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
457
460
  if (event.executionId) state.executionId = event.executionId;
458
461
  if (event.sessionId) state.sessionId = event.sessionId;
462
+ if (state.finalResponse) state.trailingActivity = true;
459
463
  const description = typeof event.description === "string" ? event.description : "";
460
464
  if (description) {
461
465
  for (let i = state.steps.length - 1; i >= 0; i--) {
@@ -490,7 +494,12 @@ function processStreamEventV2(rawEvent, state) {
490
494
  state.lastEventType = eventType;
491
495
  break;
492
496
  }
497
+ case "LLM_CALL_STARTED":
498
+ if (state.finalResponse) state.trailingActivity = true;
499
+ state.lastEventType = eventType;
500
+ break;
493
501
  case "INTENT_STARTED": {
502
+ if (state.finalResponse) state.trailingActivity = true;
494
503
  const stepId = `step-${state.stepCounter++}`;
495
504
  state.steps.push({
496
505
  id: stepId,
@@ -506,6 +515,7 @@ function processStreamEventV2(rawEvent, state) {
506
515
  break;
507
516
  }
508
517
  case "INTENT_COMPLETED": {
518
+ if (state.finalResponse) state.trailingActivity = true;
509
519
  const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
510
520
  if (intentStep) {
511
521
  intentStep.status = "completed";
@@ -537,6 +547,7 @@ function processStreamEventV2(rawEvent, state) {
537
547
  step.status = "completed";
538
548
  }
539
549
  });
550
+ state.trailingActivity = false;
540
551
  state.lastEventType = eventType;
541
552
  break;
542
553
  }
@@ -608,6 +619,7 @@ function processStreamEventV2(rawEvent, state) {
608
619
  case "WORKFLOW_ERROR":
609
620
  state.hasError = true;
610
621
  state.errorMessage = event.errorMessage || event.message || "Workflow error";
622
+ state.trailingActivity = false;
611
623
  state.lastEventType = eventType;
612
624
  break;
613
625
  // ---- K2 pipeline stage lifecycle events ----
@@ -902,7 +914,9 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
902
914
  const latestUsefulStep = [...state.steps].reverse().find(
903
915
  (s) => s.message && !isBlandStatus(s.message)
904
916
  );
905
- 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,
906
920
  // nothing useful seen yet). Render the bland label so the
907
921
  // bubble isn't blank.
908
922
  activeStep?.message ?? lastInProgressStep?.message ?? getEventMessage(event);
@@ -927,6 +941,7 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
927
941
  streamingContent: state.finalResponse,
928
942
  content: "",
929
943
  currentMessage,
944
+ hasTrailingActivity: state.trailingActivity,
930
945
  streamProgress: "processing",
931
946
  isError: false,
932
947
  steps: [...state.steps],
@@ -1154,6 +1169,9 @@ function isUserActionExpired(prompt) {
1154
1169
 
1155
1170
  // src/hooks/useChatV2.ts
1156
1171
  var EMPTY_USER_ACTION_STATE2 = { prompts: [], notifications: [] };
1172
+ function promptSlotKey(p) {
1173
+ return p.toolCallId || p.userActionId;
1174
+ }
1157
1175
  function upsertPrompt(prompts, req) {
1158
1176
  const idx = prompts.findIndex(
1159
1177
  (p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
@@ -1200,6 +1218,7 @@ function useChatV2(config, callbacks = {}) {
1200
1218
  configRef.current = config;
1201
1219
  const messagesRef = react.useRef(messages);
1202
1220
  messagesRef.current = messages;
1221
+ const pendingSubmissionsRef = react.useRef(/* @__PURE__ */ new Map());
1203
1222
  const storeAwareSetMessages = react.useCallback(
1204
1223
  (updater) => {
1205
1224
  const streamUserId = streamUserIdRef.current;
@@ -1234,6 +1253,8 @@ function useChatV2(config, callbacks = {}) {
1234
1253
  if (!config.userId) return EMPTY_USER_ACTION_STATE2;
1235
1254
  return activeStreamStore.get(config.userId)?.userActionState ?? EMPTY_USER_ACTION_STATE2;
1236
1255
  });
1256
+ const userActionStateRef = react.useRef(userActionState);
1257
+ userActionStateRef.current = userActionState;
1237
1258
  const storeAwareSetUserActionState = react.useCallback(
1238
1259
  (updater) => {
1239
1260
  const streamUserId = streamUserIdRef.current;
@@ -1261,6 +1282,12 @@ function useChatV2(config, callbacks = {}) {
1261
1282
  onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
1262
1283
  onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
1263
1284
  onUserActionRequired: (request) => {
1285
+ const requestSlotKey = promptSlotKey(request);
1286
+ for (const [pendingId, slotKey] of pendingSubmissionsRef.current) {
1287
+ if (slotKey === requestSlotKey) {
1288
+ pendingSubmissionsRef.current.delete(pendingId);
1289
+ }
1290
+ }
1264
1291
  storeAwareSetUserActionState((prev) => ({
1265
1292
  ...prev,
1266
1293
  prompts: upsertPrompt(prev.prompts, request)
@@ -1272,6 +1299,28 @@ function useChatV2(config, callbacks = {}) {
1272
1299
  (prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
1273
1300
  );
1274
1301
  callbacksRef.current.onUserNotification?.(notification);
1302
+ },
1303
+ // A submitted-but-unconfirmed prompt (see `submitUserAction`) is only
1304
+ // safe to drop once the stream has demonstrably moved on. `onEvent`
1305
+ // in useStreamManagerV2 calls `onStepsUpdate` for *every* processed
1306
+ // stream event, unconditionally — so the first time this fires
1307
+ // after a submission, the event in hand is either the rejection
1308
+ // retry (a fresh `USER_ACTION_REQUIRED`, which the handler above
1309
+ // already deleted this pending entry for, earlier in the very same
1310
+ // event) or genuine forward progress (RUN_IN_PROGRESS, a tool call,
1311
+ // content deltas, RUN_COMPLETED, ...). Anything still pending by
1312
+ // the time we get here therefore means the run resumed normally —
1313
+ // clear it.
1314
+ onStepsUpdate: (steps) => {
1315
+ if (pendingSubmissionsRef.current.size > 0) {
1316
+ const resolved = [...pendingSubmissionsRef.current.keys()];
1317
+ pendingSubmissionsRef.current.clear();
1318
+ storeAwareSetUserActionState((prev) => ({
1319
+ ...prev,
1320
+ prompts: prev.prompts.filter((p) => !resolved.includes(p.userActionId))
1321
+ }));
1322
+ }
1323
+ callbacksRef.current.onStepsUpdate?.(steps);
1275
1324
  }
1276
1325
  // eslint-disable-next-line react-hooks/exhaustive-deps
1277
1326
  }), []);
@@ -1407,6 +1456,7 @@ function useChatV2(config, callbacks = {}) {
1407
1456
  [storeAwareSetUserActionState]
1408
1457
  );
1409
1458
  const removePrompt = react.useCallback((userActionId) => {
1459
+ pendingSubmissionsRef.current.delete(userActionId);
1410
1460
  storeAwareSetUserActionState((prev) => ({
1411
1461
  ...prev,
1412
1462
  prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
@@ -1417,7 +1467,10 @@ function useChatV2(config, callbacks = {}) {
1417
1467
  setPromptStatus(userActionId, "submitting");
1418
1468
  try {
1419
1469
  await submitUserAction(configRef.current, userActionId, content);
1420
- removePrompt(userActionId);
1470
+ const prompt = userActionStateRef.current.prompts.find(
1471
+ (p) => p.userActionId === userActionId
1472
+ );
1473
+ pendingSubmissionsRef.current.set(userActionId, prompt ? promptSlotKey(prompt) : userActionId);
1421
1474
  } catch (error) {
1422
1475
  if (error instanceof UserActionStaleError) {
1423
1476
  setPromptStatus(userActionId, "stale");
@@ -1428,7 +1481,7 @@ function useChatV2(config, callbacks = {}) {
1428
1481
  throw error;
1429
1482
  }
1430
1483
  },
1431
- [removePrompt, setPromptStatus]
1484
+ [setPromptStatus]
1432
1485
  );
1433
1486
  const cancelUserAction2 = react.useCallback(
1434
1487
  async (userActionId) => {