@paymanai/payman-ask-sdk 2.0.0 → 2.0.2

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
@@ -168,6 +168,7 @@ type MessageListV2Props = {
168
168
  payeeName?: string;
169
169
  };
170
170
  status: "pending" | "verifying" | "approved" | "rejected" | "error";
171
+ clearOtpTrigger?: number;
171
172
  } | null;
172
173
  onApproveAction?: (messageId: string, otp: string) => Promise<void>;
173
174
  onRejectAction?: (messageId: string) => Promise<void>;
package/dist/index.d.ts CHANGED
@@ -168,6 +168,7 @@ type MessageListV2Props = {
168
168
  payeeName?: string;
169
169
  };
170
170
  status: "pending" | "verifying" | "approved" | "rejected" | "error";
171
+ clearOtpTrigger?: number;
171
172
  } | null;
172
173
  onApproveAction?: (messageId: string, otp: string) => Promise<void>;
173
174
  onRejectAction?: (messageId: string) => Promise<void>;
package/dist/index.js CHANGED
@@ -483,7 +483,6 @@ function MarkdownImageV2({
483
483
  setIsLoaded(false);
484
484
  setHasError(false);
485
485
  setRetryCount(0);
486
- setIsVisible(false);
487
486
  }, [src]);
488
487
  react.useEffect(() => {
489
488
  const el = sentinelRef.current;
@@ -507,7 +506,13 @@ function MarkdownImageV2({
507
506
  {
508
507
  className: cn("payman-v2-md-image", "payman-v2-md-image-resolving"),
509
508
  children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "payman-v2-md-image-resolving-inner", children: [
510
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "payman-v2-md-image-loading", "aria-hidden": true }),
509
+ /* @__PURE__ */ jsxRuntime.jsx(
510
+ lucideReact.Loader2,
511
+ {
512
+ style: { animation: "payman-v2-spin 0.7s linear infinite" },
513
+ "aria-hidden": true
514
+ }
515
+ ),
511
516
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Loading image" }),
512
517
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Reference image" })
513
518
  ] })
@@ -546,14 +551,14 @@ function MarkdownImageV2({
546
551
  "aria-busy": !isLoaded,
547
552
  style: {
548
553
  ...frameStyle,
549
- ...!isLoaded ? { minHeight: "10rem" } : {}
554
+ minHeight: isLoaded ? 0 : "10rem"
550
555
  },
551
556
  children: [
552
- !isLoaded && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "payman-v2-md-image-placeholder", children: [
557
+ !isLoaded && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "payman-v2-md-image-loading", children: [
553
558
  /* @__PURE__ */ jsxRuntime.jsx(
554
559
  lucideReact.Loader2,
555
560
  {
556
- className: "payman-v2-md-image-loading",
561
+ style: { animation: "payman-v2-spin 0.7s linear infinite" },
557
562
  "aria-hidden": true
558
563
  }
559
564
  ),
@@ -897,26 +902,29 @@ function parseThinkingContent(content) {
897
902
  }
898
903
  return out;
899
904
  }
905
+ function formatDuration(seconds) {
906
+ if (seconds < 60) return `${seconds}s`;
907
+ const m = Math.floor(seconds / 60);
908
+ const s = seconds % 60;
909
+ return s > 0 ? `${m}m ${s}s` : `${m}m`;
910
+ }
900
911
  function AnimatedSeconds({
901
912
  value,
902
913
  className,
903
914
  ariaLabel
904
915
  }) {
905
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("payman-v2-thinking-seconds", className), "aria-label": ariaLabel, children: [
906
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-thinking-seconds-track", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { initial: false, children: /* @__PURE__ */ jsxRuntime.jsx(
907
- framerMotion.motion.span,
908
- {
909
- className: "payman-v2-thinking-seconds-value",
910
- initial: { opacity: 0, y: 6, filter: "blur(2px)" },
911
- animate: { opacity: 1, y: 0, filter: "blur(0px)" },
912
- exit: { opacity: 0, y: -6, filter: "blur(2px)" },
913
- transition: { duration: 0.2, ease: [0.22, 1, 0.36, 1] },
914
- children: value
915
- },
916
- value
917
- ) }) }),
918
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-thinking-seconds-suffix", "aria-hidden": "true", children: "s" })
919
- ] });
916
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("payman-v2-thinking-seconds", className), "aria-label": ariaLabel, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-thinking-seconds-track", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { initial: false, children: /* @__PURE__ */ jsxRuntime.jsx(
917
+ framerMotion.motion.span,
918
+ {
919
+ className: "payman-v2-thinking-seconds-value",
920
+ initial: { opacity: 0, y: 6, filter: "blur(2px)" },
921
+ animate: { opacity: 1, y: 0, filter: "blur(0px)" },
922
+ exit: { opacity: 0, y: -6, filter: "blur(2px)" },
923
+ transition: { duration: 0.2, ease: [0.22, 1, 0.36, 1] },
924
+ children: formatDuration(value)
925
+ },
926
+ value
927
+ ) }) }) });
920
928
  }
921
929
  function ThinkingBlockV2({
922
930
  content,
@@ -927,8 +935,14 @@ function ThinkingBlockV2({
927
935
  const [open, setOpen] = react.useState(true);
928
936
  const [cursorIdx, setCursorIdx] = react.useState(0);
929
937
  const [elapsedSec, setElapsedSec] = react.useState(
930
- () => startedAt ? Math.max(0, Math.floor((Date.now() - startedAt) / 1e3)) : 0
938
+ () => (
939
+ // Only seed from startedAt when actively streaming — otherwise (e.g.
940
+ // after a hot-reload on a completed message) Date.now()-startedAt would
941
+ // be the time since completion, not the actual thinking duration.
942
+ isStreaming && startedAt ? Math.max(0, Math.floor((Date.now() - startedAt) / 1e3)) : 0
943
+ )
931
944
  );
945
+ const elapsedSecRef = react.useRef(elapsedSec);
932
946
  const frozenSecRef = react.useRef(null);
933
947
  const prevStreaming = react.useRef(isStreaming);
934
948
  const parsed = react.useMemo(() => parseThinkingContent(content), [content]);
@@ -941,25 +955,25 @@ function ThinkingBlockV2({
941
955
  react.useEffect(() => {
942
956
  if (prevStreaming.current && !isStreaming) {
943
957
  setOpen(false);
944
- if (startedAt) {
945
- frozenSecRef.current = Math.max(
946
- 0,
947
- Math.floor((Date.now() - startedAt) / 1e3)
948
- );
949
- }
958
+ frozenSecRef.current = elapsedSecRef.current;
950
959
  }
951
960
  prevStreaming.current = isStreaming;
952
961
  }, [isStreaming, startedAt]);
953
962
  react.useEffect(() => {
954
963
  if (!isStreaming || !startedAt) return;
964
+ let active = true;
955
965
  const tick = () => {
956
- setElapsedSec(
957
- Math.max(0, Math.floor((Date.now() - startedAt) / 1e3))
958
- );
966
+ if (!active) return;
967
+ const val = Math.max(0, Math.floor((Date.now() - startedAt) / 1e3));
968
+ elapsedSecRef.current = val;
969
+ setElapsedSec(val);
959
970
  };
960
971
  tick();
961
972
  const id = window.setInterval(tick, 1e3);
962
- return () => window.clearInterval(id);
973
+ return () => {
974
+ active = false;
975
+ window.clearInterval(id);
976
+ };
963
977
  }, [isStreaming, startedAt]);
964
978
  react.useEffect(() => {
965
979
  if (!isStreaming || isFinalizingPhase) return;
@@ -970,10 +984,11 @@ function ThinkingBlockV2({
970
984
  }, [isStreaming, isFinalizingPhase]);
971
985
  const justStoppedSec = !isStreaming && prevStreaming.current && startedAt ? Math.max(0, Math.floor((Date.now() - startedAt) / 1e3)) : void 0;
972
986
  const finalSec = getMaxDuration(
973
- durationSec,
974
987
  frozenSecRef.current,
975
988
  justStoppedSec,
976
- !isStreaming ? elapsedSec : void 0
989
+ // Only fall back to durationSec when the timer never ran this session
990
+ // (i.e. the message was already complete when this component mounted).
991
+ frozenSecRef.current == null && !prevStreaming.current ? durationSec : void 0
977
992
  );
978
993
  const headerLabel = isStreaming ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "payman-v2-thinking-header-label", children: [
979
994
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-thinking-shimmer", children: "Working on it\u2026" }),
@@ -981,11 +996,11 @@ function ThinkingBlockV2({
981
996
  AnimatedSeconds,
982
997
  {
983
998
  className: "payman-v2-thinking-timer",
984
- ariaLabel: `Elapsed ${elapsedSec} seconds`,
999
+ ariaLabel: `Elapsed ${formatDuration(elapsedSec)}`,
985
1000
  value: elapsedSec
986
1001
  }
987
1002
  )
988
- ] }) : finalSec !== null && finalSec !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "payman-v2-thinking-header-label", children: [
1003
+ ] }) : finalSec != null && finalSec > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "payman-v2-thinking-header-label", children: [
989
1004
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Thought for" }),
990
1005
  /* @__PURE__ */ jsxRuntime.jsx(
991
1006
  AnimatedSeconds,
@@ -994,7 +1009,7 @@ function ThinkingBlockV2({
994
1009
  "payman-v2-thinking-timer",
995
1010
  "payman-v2-thinking-duration"
996
1011
  ),
997
- ariaLabel: `Thought for ${finalSec} seconds`,
1012
+ ariaLabel: `Thought for ${formatDuration(finalSec)}`,
998
1013
  value: finalSec
999
1014
  }
1000
1015
  )
@@ -1116,6 +1131,7 @@ function charDelay(char, speed) {
1116
1131
  return speed.punctuation[0] + Math.random() * speed.punctuation[1];
1117
1132
  return speed.normal[0] + Math.random() * speed.normal[1];
1118
1133
  }
1134
+ var MARKDOWN_IMAGE_REGEX = /^!\[[^\]]*\]\([^)]*\)/;
1119
1135
  var typingProgressCache = /* @__PURE__ */ new Map();
1120
1136
  function useTypingEffect(targetText, enabled, speed = RESPONSE_SPEED, initialDisplayedText, cacheKey) {
1121
1137
  const cached = cacheKey ? typingProgressCache.get(cacheKey) : void 0;
@@ -1153,6 +1169,11 @@ function useTypingEffect(targetText, enabled, speed = RESPONSE_SPEED, initialDis
1153
1169
  }
1154
1170
  return;
1155
1171
  }
1172
+ if (displayedRef.current && !targetRef.current.startsWith(displayedRef.current)) {
1173
+ displayedRef.current = "";
1174
+ setDisplayedText("");
1175
+ if (cacheKeyRef.current) typingProgressCache.delete(cacheKeyRef.current);
1176
+ }
1156
1177
  if (displayedRef.current.length === 0 && initialDisplayedRef.current && targetRef.current.startsWith(initialDisplayedRef.current)) {
1157
1178
  writeDisplayed(initialDisplayedRef.current);
1158
1179
  }
@@ -1163,8 +1184,41 @@ function useTypingEffect(targetText, enabled, speed = RESPONSE_SPEED, initialDis
1163
1184
  runningRef.current = false;
1164
1185
  return;
1165
1186
  }
1187
+ if (displayedRef.current && !targetRef.current.startsWith(displayedRef.current)) {
1188
+ let divergeAt = 0;
1189
+ const minLen = Math.min(displayedRef.current.length, targetRef.current.length);
1190
+ while (divergeAt < minLen && displayedRef.current[divergeAt] === targetRef.current[divergeAt]) {
1191
+ divergeAt++;
1192
+ }
1193
+ const imgStart = targetRef.current.slice(0, divergeAt).lastIndexOf("![");
1194
+ if (imgStart >= 0) {
1195
+ const newImgMatch = MARKDOWN_IMAGE_REGEX.exec(targetRef.current.slice(imgStart));
1196
+ const oldImgMatch = MARKDOWN_IMAGE_REGEX.exec(displayedRef.current.slice(imgStart));
1197
+ if (newImgMatch && oldImgMatch) {
1198
+ const oldImgEnd = imgStart + oldImgMatch[0].length;
1199
+ const newImgEnd = imgStart + newImgMatch[0].length;
1200
+ const newCursor = Math.min(
1201
+ Math.max(displayedRef.current.length + (newImgEnd - oldImgEnd), newImgEnd),
1202
+ targetRef.current.length
1203
+ );
1204
+ writeDisplayed(targetRef.current.slice(0, newCursor));
1205
+ timerRef.current = setTimeout(tick, 0);
1206
+ return;
1207
+ }
1208
+ }
1209
+ writeDisplayed(targetRef.current.slice(0, imgStart >= 0 ? imgStart : divergeAt));
1210
+ timerRef.current = setTimeout(tick, 0);
1211
+ return;
1212
+ }
1166
1213
  if (displayedRef.current.length < targetRef.current.length) {
1167
- const nextChar = targetRef.current[displayedRef.current.length];
1214
+ const remaining = targetRef.current.slice(displayedRef.current.length);
1215
+ const imgMatch = MARKDOWN_IMAGE_REGEX.exec(remaining);
1216
+ if (imgMatch) {
1217
+ writeDisplayed(displayedRef.current + imgMatch[0]);
1218
+ timerRef.current = setTimeout(tick, 0);
1219
+ return;
1220
+ }
1221
+ const nextChar = remaining[0];
1168
1222
  writeDisplayed(displayedRef.current + nextChar);
1169
1223
  const delay = charDelay(nextChar, speed);
1170
1224
  timerRef.current = setTimeout(tick, delay);
@@ -1404,7 +1458,7 @@ function AssistantMessageV2({
1404
1458
  {
1405
1459
  content: thinkingContent,
1406
1460
  isStreaming: isThinkingStreaming,
1407
- durationSec: thinkingDuration,
1461
+ durationSec: message.thinkingDurationSec ?? thinkingDuration,
1408
1462
  startedAt: requestStartedAt
1409
1463
  }
1410
1464
  ),
@@ -1563,6 +1617,7 @@ function VerificationCardV2({
1563
1617
  messageId,
1564
1618
  action,
1565
1619
  status,
1620
+ clearOtpTrigger = 0,
1566
1621
  onApprove,
1567
1622
  onReject,
1568
1623
  onResend
@@ -1570,33 +1625,41 @@ function VerificationCardV2({
1570
1625
  const [otp, setOtp] = react.useState("");
1571
1626
  const [otpErrored, setOtpErrored] = react.useState(false);
1572
1627
  const [resendSec, setResendSec] = react.useState(0);
1628
+ const [localPending, setLocalPending] = react.useState(false);
1573
1629
  const lastSubmittedRef = react.useRef(null);
1574
1630
  const resendTimerRef = react.useRef(void 0);
1575
1631
  react.useEffect(() => {
1576
- if (status !== "error") {
1577
- setOtpErrored(false);
1578
- return;
1579
- }
1632
+ if (clearOtpTrigger <= 0) return;
1580
1633
  setOtpErrored(true);
1581
1634
  const t = window.setTimeout(() => {
1582
1635
  setOtp("");
1583
1636
  setOtpErrored(false);
1637
+ setLocalPending(false);
1584
1638
  lastSubmittedRef.current = null;
1585
1639
  }, 600);
1586
1640
  return () => window.clearTimeout(t);
1587
- }, [status]);
1641
+ }, [clearOtpTrigger]);
1588
1642
  react.useEffect(() => {
1589
1643
  if (otp.length < OTP_LEN) {
1590
1644
  lastSubmittedRef.current = null;
1591
1645
  }
1592
1646
  }, [otp]);
1647
+ react.useEffect(() => {
1648
+ if (status !== "pending") {
1649
+ setLocalPending(false);
1650
+ }
1651
+ }, [status]);
1593
1652
  react.useEffect(() => {
1594
1653
  if (otp.length !== OTP_LEN || !/^\d+$/.test(otp) || status !== "pending") {
1595
1654
  return;
1596
1655
  }
1597
1656
  if (lastSubmittedRef.current === otp) return;
1598
1657
  lastSubmittedRef.current = otp;
1599
- void onApprove(messageId, otp);
1658
+ setLocalPending(true);
1659
+ void onApprove(messageId, otp).catch(() => {
1660
+ lastSubmittedRef.current = null;
1661
+ setLocalPending(false);
1662
+ });
1600
1663
  }, [messageId, onApprove, otp, status]);
1601
1664
  react.useEffect(() => {
1602
1665
  return () => {
@@ -1624,23 +1687,25 @@ function VerificationCardV2({
1624
1687
  }, 1e3);
1625
1688
  }, []);
1626
1689
  const handleResend = react.useCallback(async () => {
1627
- if (resendSec > 0 || status === "verifying") return;
1628
- await onResend(messageId);
1629
- startResendCooldown();
1630
- }, [messageId, onResend, resendSec, startResendCooldown, status]);
1690
+ if (resendSec > 0 || status === "verifying" || localPending) return;
1691
+ setLocalPending(true);
1692
+ try {
1693
+ await onResend(messageId);
1694
+ startResendCooldown();
1695
+ } finally {
1696
+ setLocalPending(false);
1697
+ }
1698
+ }, [localPending, messageId, onResend, resendSec, startResendCooldown, status]);
1631
1699
  const handleCancel = react.useCallback(async () => {
1632
- await onReject(messageId);
1633
- }, [messageId, onReject]);
1634
- react.useCallback(async () => {
1635
- if (otp.length !== OTP_LEN || !/^\d+$/.test(otp) || status !== "pending") {
1636
- return;
1700
+ if (status === "verifying" || localPending) return;
1701
+ setLocalPending(true);
1702
+ try {
1703
+ await onReject(messageId);
1704
+ } finally {
1705
+ setLocalPending(false);
1637
1706
  }
1638
- if (lastSubmittedRef.current === otp) return;
1639
- lastSubmittedRef.current = otp;
1640
- await onApprove(messageId, otp);
1641
- }, [messageId, onApprove, otp, status]);
1642
- const busy = status === "verifying";
1643
- status === "pending" && otp.length === OTP_LEN && /^\d+$/.test(otp);
1707
+ }, [localPending, messageId, onReject, status]);
1708
+ const busy = status === "verifying" || localPending;
1644
1709
  if (status === "approved" || status === "rejected") {
1645
1710
  return null;
1646
1711
  }
@@ -1652,61 +1717,53 @@ function VerificationCardV2({
1652
1717
  animate: { opacity: 1, y: 0 },
1653
1718
  transition: { type: "spring", stiffness: 320, damping: 28 },
1654
1719
  children: [
1655
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-verification-card", children: [
1656
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-verification-header", children: [
1657
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-verification-header-row", children: [
1658
- /* @__PURE__ */ jsxRuntime.jsx(
1659
- lucideReact.ShieldCheck,
1660
- {
1661
- className: "payman-v2-verification-icon",
1662
- size: 18,
1663
- strokeWidth: 1.75,
1664
- "aria-hidden": true
1665
- }
1666
- ),
1667
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-verification-title", children: "Verify" }),
1668
- action.amount != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-verification-amount", children: action.amount }) : action.payeeName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-verification-payee", children: action.payeeName }) : null
1669
- ] }),
1670
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-verification-description", children: "Enter the 6-digit code sent to your phone" }),
1671
- /* @__PURE__ */ jsxRuntime.jsx(
1672
- OtpInputV2,
1673
- {
1674
- value: otp,
1675
- onChange: setOtp,
1676
- maxLength: OTP_LEN,
1677
- disabled: busy,
1678
- error: otpErrored
1679
- }
1720
+ /* @__PURE__ */ jsxRuntime.jsxs(
1721
+ "div",
1722
+ {
1723
+ className: cn(
1724
+ "payman-v2-verification-card",
1725
+ busy && "payman-v2-verification-card-busy"
1680
1726
  ),
1681
- busy ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-verification-submitting", children: [
1682
- /* @__PURE__ */ jsxRuntime.jsx(
1683
- framerMotion.motion.span,
1727
+ children: [
1728
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-verification-header", children: [
1729
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-verification-header-row", children: [
1730
+ /* @__PURE__ */ jsxRuntime.jsx(
1731
+ lucideReact.ShieldCheck,
1732
+ {
1733
+ className: "payman-v2-verification-icon",
1734
+ size: 18,
1735
+ strokeWidth: 1.75,
1736
+ "aria-hidden": true
1737
+ }
1738
+ ),
1739
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-verification-title", children: "Verify" }),
1740
+ action.amount != null ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-verification-amount", children: action.amount }) : action.payeeName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-verification-payee", children: action.payeeName }) : null
1741
+ ] }),
1742
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-verification-description", children: "Enter the 6-digit code sent to your phone" }),
1743
+ /* @__PURE__ */ jsxRuntime.jsx(
1744
+ OtpInputV2,
1745
+ {
1746
+ value: otp,
1747
+ onChange: setOtp,
1748
+ maxLength: OTP_LEN,
1749
+ disabled: busy,
1750
+ error: otpErrored
1751
+ }
1752
+ )
1753
+ ] }),
1754
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-verification-actions", children: /* @__PURE__ */ jsxRuntime.jsx(
1755
+ "button",
1684
1756
  {
1685
- "aria-hidden": true,
1686
- style: { display: "inline-flex" },
1687
- animate: { rotate: 360 },
1688
- transition: {
1689
- repeat: Infinity,
1690
- duration: 0.7,
1691
- ease: "linear"
1692
- },
1693
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 14, strokeWidth: 2 })
1757
+ type: "button",
1758
+ className: "payman-v2-verification-cancel-btn",
1759
+ disabled: busy,
1760
+ onClick: () => void handleCancel(),
1761
+ children: "Cancel"
1694
1762
  }
1695
- ),
1696
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-verification-submitting-text", children: "Verifying..." })
1697
- ] }) : null
1698
- ] }),
1699
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-verification-actions", children: /* @__PURE__ */ jsxRuntime.jsx(
1700
- "button",
1701
- {
1702
- type: "button",
1703
- className: "payman-v2-verification-cancel-btn",
1704
- disabled: busy,
1705
- onClick: () => void handleCancel(),
1706
- children: "Cancel"
1707
- }
1708
- ) })
1709
- ] }),
1763
+ ) })
1764
+ ]
1765
+ }
1766
+ ),
1710
1767
  /* @__PURE__ */ jsxRuntime.jsx(
1711
1768
  "button",
1712
1769
  {
@@ -1899,6 +1956,7 @@ var MessageListV2 = react.forwardRef(
1899
1956
  messageId: userAction.messageId,
1900
1957
  action: userAction.action,
1901
1958
  status: userAction.status,
1959
+ clearOtpTrigger: userAction.clearOtpTrigger,
1902
1960
  onApprove: onApproveAction ?? (async () => {
1903
1961
  }),
1904
1962
  onReject: onRejectAction ?? (async () => {
@@ -3051,17 +3109,7 @@ function SessionList({
3051
3109
  [sessions, formattedNow]
3052
3110
  );
3053
3111
  if (!isReady) {
3054
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-sidebar-notice", children: [
3055
- "Pass ",
3056
- /* @__PURE__ */ jsxRuntime.jsx(InlineCode, { children: "workflow.id" }),
3057
- " (or",
3058
- " ",
3059
- /* @__PURE__ */ jsxRuntime.jsx(InlineCode, { children: "workflow.name" }),
3060
- ") and",
3061
- " ",
3062
- /* @__PURE__ */ jsxRuntime.jsx(InlineCode, { children: "session.owner.id" }),
3063
- " in your chat config to view recent sessions."
3064
- ] });
3112
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-sidebar-notice-shell", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-sidebar-notice", children: "Configure the chat settings." }) });
3065
3113
  }
3066
3114
  return /* @__PURE__ */ jsxRuntime.jsxs(
3067
3115
  "div",
@@ -3228,9 +3276,6 @@ function Spinner({ size = 12 }) {
3228
3276
  }
3229
3277
  );
3230
3278
  }
3231
- function InlineCode({ children }) {
3232
- return /* @__PURE__ */ jsxRuntime.jsx("code", { className: "payman-sidebar-inline-code", children });
3233
- }
3234
3279
  function groupSessionsByDate(sessions, now) {
3235
3280
  const groups = /* @__PURE__ */ new Map();
3236
3281
  const orderedGroups = [];
@@ -3707,6 +3752,14 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
3707
3752
  }),
3708
3753
  [performResetSession, clearMessages, cancelStream, getSessionId, getMessages, loadSession]
3709
3754
  );
3755
+ const [v2VerificationPending, setV2VerificationPending] = react.useState(false);
3756
+ react.useEffect(() => {
3757
+ setV2VerificationPending(false);
3758
+ }, [
3759
+ userActionState.request?.userActionId,
3760
+ userActionState.clearOtpTrigger,
3761
+ userActionState.result
3762
+ ]);
3710
3763
  if (availability.state === "disabled") {
3711
3764
  return /* @__PURE__ */ jsxRuntime.jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
3712
3765
  "div",
@@ -3729,7 +3782,8 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
3729
3782
  if (!userActionState.request) return null;
3730
3783
  const req = userActionState.request;
3731
3784
  let status = "pending";
3732
- if (userActionState.result === "approved") status = "approved";
3785
+ if (v2VerificationPending) status = "verifying";
3786
+ else if (userActionState.result === "approved") status = "approved";
3733
3787
  else if (userActionState.result === "rejected") status = "rejected";
3734
3788
  return {
3735
3789
  messageId: `ua-${req.userActionId || Date.now()}`,
@@ -3739,9 +3793,15 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
3739
3793
  amount: req.metadata?.amount,
3740
3794
  payeeName: req.metadata?.payeeName
3741
3795
  },
3742
- status
3796
+ status,
3797
+ clearOtpTrigger: userActionState.clearOtpTrigger
3743
3798
  };
3744
- }, [userActionState.request, userActionState.result]);
3799
+ }, [
3800
+ userActionState.request,
3801
+ userActionState.result,
3802
+ userActionState.clearOtpTrigger,
3803
+ v2VerificationPending
3804
+ ]);
3745
3805
  const hideV2SendDuringVerification = v2UserAction != null && v2UserAction.status !== "approved" && v2UserAction.status !== "rejected";
3746
3806
  const handleV2Send = (text) => {
3747
3807
  if (isRecording) stopRecording();
@@ -3877,7 +3937,8 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
3877
3937
  alignItems: "center",
3878
3938
  justifyContent: "center",
3879
3939
  width: "100%",
3880
- minHeight: 0
3940
+ minHeight: 0,
3941
+ marginTop: "1.5rem"
3881
3942
  },
3882
3943
  children: /* @__PURE__ */ jsxRuntime.jsx(
3883
3944
  EmptyState2,
@@ -3903,10 +3964,22 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
3903
3964
  retryDisabled: isWaitingForResponse,
3904
3965
  userAction: v2UserAction,
3905
3966
  onApproveAction: async (_id, otp) => {
3906
- await approveUserAction(otp);
3967
+ setV2VerificationPending(true);
3968
+ try {
3969
+ await approveUserAction(otp);
3970
+ } catch (error) {
3971
+ setV2VerificationPending(false);
3972
+ throw error;
3973
+ }
3907
3974
  },
3908
3975
  onRejectAction: async () => {
3909
- await rejectUserAction();
3976
+ setV2VerificationPending(true);
3977
+ try {
3978
+ await rejectUserAction();
3979
+ } catch (error) {
3980
+ setV2VerificationPending(false);
3981
+ throw error;
3982
+ }
3910
3983
  },
3911
3984
  onResendAction: async () => {
3912
3985
  await resendOtp();