@paymanai/payman-ask-sdk 1.0.4 → 1.1.0
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 +39 -2
- package/dist/index.d.ts +39 -2
- package/dist/index.js +513 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +504 -13
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +496 -15
- package/dist/index.native.js.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createContext, useContext, useState, useMemo, useRef, useCallback, useEffect } from 'react';
|
|
2
2
|
import { useChat } from '@paymanai/payman-typescript-ask-sdk';
|
|
3
|
-
export { generateId, streamWorkflowEvents, useChat } from '@paymanai/payman-typescript-ask-sdk';
|
|
3
|
+
export { cancelUserAction, generateId, resendUserAction, streamWorkflowEvents, submitUserAction, useChat } from '@paymanai/payman-typescript-ask-sdk';
|
|
4
4
|
import { clsx } from 'clsx';
|
|
5
5
|
import { twMerge } from 'tailwind-merge';
|
|
6
6
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
7
|
-
import { Bot, Pause, Send,
|
|
8
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
|
+
import { Bot, Pause, Send, ShieldCheck, Loader2, User, CheckCircle2, XCircle, X, ChevronUp, ChevronDown, Check, Binoculars } from 'lucide-react';
|
|
8
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
9
9
|
import ReactMarkdown from 'react-markdown';
|
|
10
10
|
import remarkGfm from 'remark-gfm';
|
|
11
11
|
|
|
@@ -159,7 +159,6 @@ function AgentMessage({
|
|
|
159
159
|
agentName = "Assistant",
|
|
160
160
|
showAvatar = false,
|
|
161
161
|
layout = "full-width",
|
|
162
|
-
showTimestamp = false,
|
|
163
162
|
showExecutionSteps = false,
|
|
164
163
|
showStreamingDot = false,
|
|
165
164
|
streamingStepsText,
|
|
@@ -212,6 +211,13 @@ function AgentMessage({
|
|
|
212
211
|
"min-w-0 flex flex-col",
|
|
213
212
|
layout === "centered" ? "max-w-[85%]" : showAvatar ? "max-w-[85%]" : "max-w-[80%]"
|
|
214
213
|
), children: [
|
|
214
|
+
message.userActionResult && /* @__PURE__ */ jsx("div", { className: "mb-2", children: message.userActionResult === "approved" ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-1 text-xs font-medium rounded-full bg-green-100 text-green-700", children: [
|
|
215
|
+
/* @__PURE__ */ jsx(CheckCircle2, { className: "w-3 h-3" }),
|
|
216
|
+
" OTP Verified"
|
|
217
|
+
] }) : /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-1 text-xs font-medium rounded-full bg-red-100 text-red-700", children: [
|
|
218
|
+
/* @__PURE__ */ jsx(XCircle, { className: "w-3 h-3" }),
|
|
219
|
+
" Rejected"
|
|
220
|
+
] }) }),
|
|
215
221
|
/* @__PURE__ */ jsxs(
|
|
216
222
|
"div",
|
|
217
223
|
{
|
|
@@ -319,7 +325,7 @@ function AgentMessage({
|
|
|
319
325
|
layout === "centered" ? "text-neutral-500 hover:bg-neutral-50" : "text-muted-foreground hover:bg-muted/70"
|
|
320
326
|
),
|
|
321
327
|
children: [
|
|
322
|
-
/* @__PURE__ */ jsx("span", { children: getCompletedStepsText(isStepsExpanded) }),
|
|
328
|
+
/* @__PURE__ */ jsx("span", { children: getCompletedStepsText(!!isStepsExpanded) }),
|
|
323
329
|
isStepsExpanded ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3" })
|
|
324
330
|
]
|
|
325
331
|
}
|
|
@@ -339,7 +345,7 @@ function AgentMessage({
|
|
|
339
345
|
step.status === "pending" && isCancelled && /* @__PURE__ */ jsx(XCircle, { className: "h-3 w-3 text-muted-foreground shrink-0 mt-0.5" }),
|
|
340
346
|
step.status === "pending" && !isCancelled && /* @__PURE__ */ jsx(Loader2, { className: "h-3 w-3 text-primary animate-spin shrink-0 mt-0.5" }),
|
|
341
347
|
step.status === "in_progress" && !isCurrentlyExecuting && /* @__PURE__ */ jsx(Loader2, { className: "h-3 w-3 text-primary animate-spin shrink-0 mt-0.5" }),
|
|
342
|
-
step.status === "completed" && /* @__PURE__ */ jsx(Check, { className: "h-3 w-3
|
|
348
|
+
step.status === "completed" && /* @__PURE__ */ jsx(Check, { className: cn("h-3 w-3 shrink-0 mt-0.5", step.eventType === "USER_ACTION_SUCCESS" ? "text-green-600" : "text-primary") }),
|
|
343
349
|
step.status === "error" && /* @__PURE__ */ jsx(X, { className: "h-3 w-3 text-destructive shrink-0 mt-0.5" }),
|
|
344
350
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
345
351
|
/* @__PURE__ */ jsx(
|
|
@@ -347,7 +353,8 @@ function AgentMessage({
|
|
|
347
353
|
{
|
|
348
354
|
className: cn(
|
|
349
355
|
"text-muted-foreground break-words",
|
|
350
|
-
step.status === "error" && "text-destructive"
|
|
356
|
+
step.status === "error" && "text-destructive",
|
|
357
|
+
step.eventType === "USER_ACTION_SUCCESS" && "text-green-600"
|
|
351
358
|
),
|
|
352
359
|
children: step.message
|
|
353
360
|
}
|
|
@@ -376,7 +383,7 @@ function AgentMessage({
|
|
|
376
383
|
layout === "centered" ? "text-neutral-500 hover:bg-neutral-50" : "text-muted-foreground hover:bg-muted/70"
|
|
377
384
|
),
|
|
378
385
|
children: [
|
|
379
|
-
/* @__PURE__ */ jsx("span", { children: getStreamingStepsText(isStepsExpanded) }),
|
|
386
|
+
/* @__PURE__ */ jsx("span", { children: getStreamingStepsText(!!isStepsExpanded) }),
|
|
380
387
|
isStepsExpanded ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3" })
|
|
381
388
|
]
|
|
382
389
|
}
|
|
@@ -396,7 +403,7 @@ function AgentMessage({
|
|
|
396
403
|
step.status === "pending" && isCancelled && /* @__PURE__ */ jsx(XCircle, { className: "h-3 w-3 text-muted-foreground shrink-0 mt-0.5" }),
|
|
397
404
|
step.status === "pending" && !isCancelled && /* @__PURE__ */ jsx(Loader2, { className: "h-3 w-3 text-primary animate-spin shrink-0 mt-0.5" }),
|
|
398
405
|
step.status === "in_progress" && !isCurrentlyExecuting && /* @__PURE__ */ jsx(Loader2, { className: "h-3 w-3 text-primary animate-spin shrink-0 mt-0.5" }),
|
|
399
|
-
step.status === "completed" && /* @__PURE__ */ jsx(Check, { className: "h-3 w-3
|
|
406
|
+
step.status === "completed" && /* @__PURE__ */ jsx(Check, { className: cn("h-3 w-3 shrink-0 mt-0.5", step.eventType === "USER_ACTION_SUCCESS" ? "text-green-600" : "text-primary") }),
|
|
400
407
|
step.status === "error" && /* @__PURE__ */ jsx(X, { className: "h-3 w-3 text-destructive shrink-0 mt-0.5" }),
|
|
401
408
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
402
409
|
/* @__PURE__ */ jsx(
|
|
@@ -404,7 +411,8 @@ function AgentMessage({
|
|
|
404
411
|
{
|
|
405
412
|
className: cn(
|
|
406
413
|
"text-muted-foreground break-words",
|
|
407
|
-
step.status === "error" && "text-destructive"
|
|
414
|
+
step.status === "error" && "text-destructive",
|
|
415
|
+
step.eventType === "USER_ACTION_SUCCESS" && "text-green-600"
|
|
408
416
|
),
|
|
409
417
|
children: step.message
|
|
410
418
|
}
|
|
@@ -429,7 +437,10 @@ function AgentMessage({
|
|
|
429
437
|
tracingData: message.tracingData,
|
|
430
438
|
executionId: message.executionId
|
|
431
439
|
}),
|
|
432
|
-
className:
|
|
440
|
+
className: cn(
|
|
441
|
+
"p-2 bg-white/5 border border-white/20 rounded-lg shadow-sm hover:bg-white/10 hover:border-highlight transition-colors duration-200 flex-shrink-0",
|
|
442
|
+
message.userActionResult ? "mt-8" : "mt-0.5"
|
|
443
|
+
),
|
|
433
444
|
title: "View execution trace",
|
|
434
445
|
"aria-label": "View execution trace",
|
|
435
446
|
children: /* @__PURE__ */ jsx(Binoculars, { className: "w-4 h-4 text-foreground" })
|
|
@@ -649,6 +660,466 @@ function MessageList({
|
|
|
649
660
|
}
|
|
650
661
|
);
|
|
651
662
|
}
|
|
663
|
+
var DEFAULT_MAX_LENGTH = 6;
|
|
664
|
+
var MAX_SUPPORTED_LENGTH = 12;
|
|
665
|
+
var AUTO_FOCUS_DELAY_MS = 250;
|
|
666
|
+
function OtpInput({ value, onChange, maxLength, disabled = false }) {
|
|
667
|
+
const inputRefs = useRef([]);
|
|
668
|
+
const safeMaxLength = Number.isInteger(maxLength) && maxLength > 0 ? Math.min(maxLength, MAX_SUPPORTED_LENGTH) : DEFAULT_MAX_LENGTH;
|
|
669
|
+
const digits = value.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
|
|
670
|
+
useEffect(() => {
|
|
671
|
+
if (disabled) return;
|
|
672
|
+
const focusTimer = window.setTimeout(() => {
|
|
673
|
+
inputRefs.current[0]?.focus();
|
|
674
|
+
}, AUTO_FOCUS_DELAY_MS);
|
|
675
|
+
return () => window.clearTimeout(focusTimer);
|
|
676
|
+
}, [disabled]);
|
|
677
|
+
const focusInput = (index) => {
|
|
678
|
+
if (index >= 0 && index < safeMaxLength) {
|
|
679
|
+
inputRefs.current[index]?.focus();
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
const updateValue = (newDigits) => {
|
|
683
|
+
onChange(newDigits.join("").slice(0, safeMaxLength));
|
|
684
|
+
};
|
|
685
|
+
const handleChange = (index, char) => {
|
|
686
|
+
if (char && !/^\d$/.test(char)) return;
|
|
687
|
+
const newDigits = [...digits];
|
|
688
|
+
newDigits[index] = char;
|
|
689
|
+
updateValue(newDigits);
|
|
690
|
+
if (char && index < safeMaxLength - 1) {
|
|
691
|
+
focusInput(index + 1);
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
const handleKeyDown = (index, e) => {
|
|
695
|
+
if (e.key === "Enter") {
|
|
696
|
+
e.preventDefault();
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
if (e.key === "Backspace") {
|
|
700
|
+
e.preventDefault();
|
|
701
|
+
if (digits[index]) {
|
|
702
|
+
const newDigits = [...digits];
|
|
703
|
+
newDigits[index] = "";
|
|
704
|
+
updateValue(newDigits);
|
|
705
|
+
} else if (index > 0) {
|
|
706
|
+
const newDigits = [...digits];
|
|
707
|
+
newDigits[index - 1] = "";
|
|
708
|
+
updateValue(newDigits);
|
|
709
|
+
focusInput(index - 1);
|
|
710
|
+
}
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
if (e.key === "ArrowLeft") {
|
|
714
|
+
e.preventDefault();
|
|
715
|
+
focusInput(index - 1);
|
|
716
|
+
} else if (e.key === "ArrowRight") {
|
|
717
|
+
e.preventDefault();
|
|
718
|
+
focusInput(index + 1);
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
const handlePaste = (e) => {
|
|
722
|
+
e.preventDefault();
|
|
723
|
+
const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, safeMaxLength);
|
|
724
|
+
if (!pasted) return;
|
|
725
|
+
const newDigits = pasted.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
|
|
726
|
+
updateValue(newDigits);
|
|
727
|
+
focusInput(Math.min(pasted.length, safeMaxLength - 1));
|
|
728
|
+
};
|
|
729
|
+
return /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "8px", justifyContent: "center" }, children: digits.map((digit, i) => /* @__PURE__ */ jsx(
|
|
730
|
+
"input",
|
|
731
|
+
{
|
|
732
|
+
ref: (el) => {
|
|
733
|
+
inputRefs.current[i] = el;
|
|
734
|
+
},
|
|
735
|
+
type: "text",
|
|
736
|
+
inputMode: "numeric",
|
|
737
|
+
maxLength: 1,
|
|
738
|
+
value: digit,
|
|
739
|
+
disabled,
|
|
740
|
+
onChange: (e) => handleChange(i, e.target.value.slice(-1)),
|
|
741
|
+
onKeyDown: (e) => handleKeyDown(i, e),
|
|
742
|
+
onPaste: handlePaste,
|
|
743
|
+
onFocus: (e) => e.target.select(),
|
|
744
|
+
"aria-label": `Digit ${i + 1}`,
|
|
745
|
+
style: {
|
|
746
|
+
width: "40px",
|
|
747
|
+
height: "48px",
|
|
748
|
+
textAlign: "center",
|
|
749
|
+
fontSize: "20px",
|
|
750
|
+
fontWeight: 600,
|
|
751
|
+
border: "1px solid var(--border, #E5E5E5)",
|
|
752
|
+
borderRadius: "8px",
|
|
753
|
+
outline: "none",
|
|
754
|
+
backgroundColor: disabled ? "var(--muted, #F5F5F5)" : "transparent",
|
|
755
|
+
color: "var(--foreground, #000)",
|
|
756
|
+
opacity: disabled ? 0.5 : 1
|
|
757
|
+
}
|
|
758
|
+
},
|
|
759
|
+
i
|
|
760
|
+
)) });
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// src/components/UserActionModal/constants.ts
|
|
764
|
+
var BUTTON_LABELS = {
|
|
765
|
+
APPROVE: "Verify",
|
|
766
|
+
REJECT: "Reject",
|
|
767
|
+
RESEND: "Resend OTP"
|
|
768
|
+
};
|
|
769
|
+
var RESEND_OTP_COOLDOWN_SECONDS = 30;
|
|
770
|
+
var DEFAULT_OTP_MAX_LENGTH = 6;
|
|
771
|
+
var MIN_OTP_MAX_LENGTH = 1;
|
|
772
|
+
var MAX_OTP_MAX_LENGTH = 12;
|
|
773
|
+
var ACTION_PENDING_TIMEOUT_MS = 15e3;
|
|
774
|
+
var MODAL_CONTENT = {
|
|
775
|
+
TITLE: "Verification Required",
|
|
776
|
+
LOADING_APPROVE: "Verifying...",
|
|
777
|
+
LOADING_REJECT: "Rejecting...",
|
|
778
|
+
LOADING_RESEND: "Resending...",
|
|
779
|
+
RESEND_AVAILABLE_IN: "Resend OTP in"
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
// src/components/UserActionModal/utils.ts
|
|
783
|
+
function getOtpSchemaFromRequest(schema) {
|
|
784
|
+
const properties = schema?.properties;
|
|
785
|
+
const otp = properties?.otp;
|
|
786
|
+
const maxLengthRaw = otp?.maxLength;
|
|
787
|
+
const parsedMaxLength = Number.isInteger(maxLengthRaw) ? Number(maxLengthRaw) : DEFAULT_OTP_MAX_LENGTH;
|
|
788
|
+
const clampedMaxLength = Math.min(
|
|
789
|
+
MAX_OTP_MAX_LENGTH,
|
|
790
|
+
Math.max(MIN_OTP_MAX_LENGTH, parsedMaxLength)
|
|
791
|
+
);
|
|
792
|
+
return {
|
|
793
|
+
maxLength: clampedMaxLength
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
function UserActionModal({
|
|
797
|
+
isOpen,
|
|
798
|
+
userActionRequest,
|
|
799
|
+
onApprove,
|
|
800
|
+
onReject,
|
|
801
|
+
onResend,
|
|
802
|
+
clearOtpTrigger
|
|
803
|
+
}) {
|
|
804
|
+
const [otp, setOtp] = useState("");
|
|
805
|
+
const [actionType, setActionType] = useState(null);
|
|
806
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
807
|
+
const [resendCooldownRemaining, setResendCooldownRemaining] = useState(0);
|
|
808
|
+
const dialogRef = useRef(null);
|
|
809
|
+
const previousFocusedRef = useRef(null);
|
|
810
|
+
const schema = getOtpSchemaFromRequest(userActionRequest?.requestedSchema);
|
|
811
|
+
const resetActionState = useCallback(() => {
|
|
812
|
+
setIsSubmitting(false);
|
|
813
|
+
setActionType(null);
|
|
814
|
+
}, []);
|
|
815
|
+
useEffect(() => {
|
|
816
|
+
if (isOpen) {
|
|
817
|
+
setResendCooldownRemaining(RESEND_OTP_COOLDOWN_SECONDS);
|
|
818
|
+
} else {
|
|
819
|
+
setOtp("");
|
|
820
|
+
resetActionState();
|
|
821
|
+
setResendCooldownRemaining(0);
|
|
822
|
+
}
|
|
823
|
+
}, [isOpen, resetActionState]);
|
|
824
|
+
useEffect(() => {
|
|
825
|
+
if (resendCooldownRemaining <= 0) return;
|
|
826
|
+
const timer = setTimeout(() => {
|
|
827
|
+
setResendCooldownRemaining((prev) => prev - 1);
|
|
828
|
+
}, 1e3);
|
|
829
|
+
return () => clearTimeout(timer);
|
|
830
|
+
}, [resendCooldownRemaining]);
|
|
831
|
+
useEffect(() => {
|
|
832
|
+
if (clearOtpTrigger > 0) {
|
|
833
|
+
setOtp("");
|
|
834
|
+
resetActionState();
|
|
835
|
+
}
|
|
836
|
+
}, [clearOtpTrigger, resetActionState]);
|
|
837
|
+
useEffect(() => {
|
|
838
|
+
if (!isOpen || !isSubmitting) return;
|
|
839
|
+
if (actionType !== "approve" && actionType !== "reject") return;
|
|
840
|
+
const timeout = setTimeout(() => {
|
|
841
|
+
resetActionState();
|
|
842
|
+
}, ACTION_PENDING_TIMEOUT_MS);
|
|
843
|
+
return () => clearTimeout(timeout);
|
|
844
|
+
}, [isOpen, isSubmitting, actionType, resetActionState]);
|
|
845
|
+
useEffect(() => {
|
|
846
|
+
if (!isOpen) return;
|
|
847
|
+
const dialog = dialogRef.current;
|
|
848
|
+
if (!dialog) return;
|
|
849
|
+
previousFocusedRef.current = document.activeElement;
|
|
850
|
+
const originalOverflow = document.body.style.overflow;
|
|
851
|
+
document.body.style.overflow = "hidden";
|
|
852
|
+
const getFocusableElements = () => Array.from(
|
|
853
|
+
dialog.querySelectorAll(
|
|
854
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
855
|
+
)
|
|
856
|
+
).filter((el) => !el.hasAttribute("disabled") && el.tabIndex !== -1);
|
|
857
|
+
const focusables = getFocusableElements();
|
|
858
|
+
(focusables[0] ?? dialog).focus();
|
|
859
|
+
const handleKeyDown = (event) => {
|
|
860
|
+
if (event.key === "Escape") {
|
|
861
|
+
event.preventDefault();
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
if (event.key !== "Tab") return;
|
|
865
|
+
const currentFocusables = getFocusableElements();
|
|
866
|
+
if (currentFocusables.length === 0) {
|
|
867
|
+
event.preventDefault();
|
|
868
|
+
dialog.focus();
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
const first = currentFocusables[0];
|
|
872
|
+
const last = currentFocusables[currentFocusables.length - 1];
|
|
873
|
+
const activeElement = document.activeElement;
|
|
874
|
+
const isInDialog = activeElement ? dialog.contains(activeElement) : false;
|
|
875
|
+
if (event.shiftKey) {
|
|
876
|
+
if (!isInDialog || activeElement === first) {
|
|
877
|
+
event.preventDefault();
|
|
878
|
+
last.focus();
|
|
879
|
+
}
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
if (!isInDialog || activeElement === last) {
|
|
883
|
+
event.preventDefault();
|
|
884
|
+
first.focus();
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
888
|
+
return () => {
|
|
889
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
890
|
+
document.body.style.overflow = originalOverflow;
|
|
891
|
+
previousFocusedRef.current?.focus();
|
|
892
|
+
};
|
|
893
|
+
}, [isOpen]);
|
|
894
|
+
const handleApprove = useCallback(async () => {
|
|
895
|
+
if (otp.length !== schema.maxLength || !/^\d+$/.test(otp)) return;
|
|
896
|
+
setIsSubmitting(true);
|
|
897
|
+
setActionType("approve");
|
|
898
|
+
try {
|
|
899
|
+
await onApprove(otp);
|
|
900
|
+
} catch {
|
|
901
|
+
resetActionState();
|
|
902
|
+
}
|
|
903
|
+
}, [otp, schema.maxLength, onApprove, resetActionState]);
|
|
904
|
+
const handleReject = useCallback(async () => {
|
|
905
|
+
setIsSubmitting(true);
|
|
906
|
+
setActionType("reject");
|
|
907
|
+
try {
|
|
908
|
+
await onReject();
|
|
909
|
+
} catch {
|
|
910
|
+
resetActionState();
|
|
911
|
+
}
|
|
912
|
+
}, [onReject, resetActionState]);
|
|
913
|
+
const handleResend = useCallback(async () => {
|
|
914
|
+
if (resendCooldownRemaining > 0) return;
|
|
915
|
+
setIsSubmitting(true);
|
|
916
|
+
setActionType("resend");
|
|
917
|
+
try {
|
|
918
|
+
await onResend();
|
|
919
|
+
setResendCooldownRemaining(RESEND_OTP_COOLDOWN_SECONDS);
|
|
920
|
+
} catch {
|
|
921
|
+
} finally {
|
|
922
|
+
setActionType(null);
|
|
923
|
+
setIsSubmitting(false);
|
|
924
|
+
}
|
|
925
|
+
}, [resendCooldownRemaining, onResend]);
|
|
926
|
+
if (!isOpen || !userActionRequest) return null;
|
|
927
|
+
const isOtpValid = otp.length === schema.maxLength && /^\d+$/.test(otp);
|
|
928
|
+
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
|
|
929
|
+
"div",
|
|
930
|
+
{
|
|
931
|
+
style: {
|
|
932
|
+
position: "fixed",
|
|
933
|
+
inset: 0,
|
|
934
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
935
|
+
zIndex: 1e4,
|
|
936
|
+
display: "flex",
|
|
937
|
+
alignItems: "center",
|
|
938
|
+
justifyContent: "center"
|
|
939
|
+
},
|
|
940
|
+
children: /* @__PURE__ */ jsxs(
|
|
941
|
+
"div",
|
|
942
|
+
{
|
|
943
|
+
ref: dialogRef,
|
|
944
|
+
role: "dialog",
|
|
945
|
+
"aria-modal": "true",
|
|
946
|
+
style: {
|
|
947
|
+
backgroundColor: "var(--card, #FFFFFF)",
|
|
948
|
+
borderRadius: "12px",
|
|
949
|
+
padding: "24px",
|
|
950
|
+
width: "100%",
|
|
951
|
+
maxWidth: "420px",
|
|
952
|
+
margin: "0 16px",
|
|
953
|
+
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)"
|
|
954
|
+
},
|
|
955
|
+
tabIndex: -1,
|
|
956
|
+
children: [
|
|
957
|
+
/* @__PURE__ */ jsxs("div", { style: { textAlign: "center", marginBottom: "16px" }, children: [
|
|
958
|
+
/* @__PURE__ */ jsx(
|
|
959
|
+
"div",
|
|
960
|
+
{
|
|
961
|
+
style: {
|
|
962
|
+
display: "inline-flex",
|
|
963
|
+
alignItems: "center",
|
|
964
|
+
justifyContent: "center",
|
|
965
|
+
width: "48px",
|
|
966
|
+
height: "48px",
|
|
967
|
+
borderRadius: "50%",
|
|
968
|
+
backgroundColor: "var(--muted, #F5F5F5)",
|
|
969
|
+
marginBottom: "12px"
|
|
970
|
+
},
|
|
971
|
+
children: /* @__PURE__ */ jsx(
|
|
972
|
+
ShieldCheck,
|
|
973
|
+
{
|
|
974
|
+
className: "text-primary",
|
|
975
|
+
style: { width: "24px", height: "24px" }
|
|
976
|
+
}
|
|
977
|
+
)
|
|
978
|
+
}
|
|
979
|
+
),
|
|
980
|
+
/* @__PURE__ */ jsx(
|
|
981
|
+
"h2",
|
|
982
|
+
{
|
|
983
|
+
style: {
|
|
984
|
+
fontSize: "18px",
|
|
985
|
+
fontWeight: 600,
|
|
986
|
+
color: "var(--foreground, #000)",
|
|
987
|
+
margin: 0
|
|
988
|
+
},
|
|
989
|
+
children: MODAL_CONTENT.TITLE
|
|
990
|
+
}
|
|
991
|
+
)
|
|
992
|
+
] }),
|
|
993
|
+
/* @__PURE__ */ jsx(
|
|
994
|
+
"p",
|
|
995
|
+
{
|
|
996
|
+
style: {
|
|
997
|
+
fontSize: "14px",
|
|
998
|
+
color: "var(--muted-foreground, #666)",
|
|
999
|
+
textAlign: "center",
|
|
1000
|
+
margin: "0 0 24px 0",
|
|
1001
|
+
lineHeight: 1.5
|
|
1002
|
+
},
|
|
1003
|
+
children: userActionRequest.message
|
|
1004
|
+
}
|
|
1005
|
+
),
|
|
1006
|
+
/* @__PURE__ */ jsx("div", { style: { marginBottom: "24px" }, children: /* @__PURE__ */ jsx(
|
|
1007
|
+
OtpInput,
|
|
1008
|
+
{
|
|
1009
|
+
value: otp,
|
|
1010
|
+
onChange: setOtp,
|
|
1011
|
+
maxLength: schema.maxLength,
|
|
1012
|
+
disabled: isSubmitting
|
|
1013
|
+
}
|
|
1014
|
+
) }),
|
|
1015
|
+
/* @__PURE__ */ jsxs(
|
|
1016
|
+
"div",
|
|
1017
|
+
{
|
|
1018
|
+
style: {
|
|
1019
|
+
display: "flex",
|
|
1020
|
+
flexDirection: "column",
|
|
1021
|
+
gap: "10px"
|
|
1022
|
+
},
|
|
1023
|
+
children: [
|
|
1024
|
+
/* @__PURE__ */ jsxs(
|
|
1025
|
+
"div",
|
|
1026
|
+
{
|
|
1027
|
+
style: {
|
|
1028
|
+
display: "flex",
|
|
1029
|
+
gap: "8px"
|
|
1030
|
+
},
|
|
1031
|
+
children: [
|
|
1032
|
+
/* @__PURE__ */ jsxs(
|
|
1033
|
+
"button",
|
|
1034
|
+
{
|
|
1035
|
+
onClick: handleReject,
|
|
1036
|
+
disabled: isSubmitting,
|
|
1037
|
+
className: cn(
|
|
1038
|
+
"py-2.5 px-4 rounded-lg text-sm font-medium transition-colors",
|
|
1039
|
+
"bg-destructive/10 text-destructive hover:bg-destructive/20 hover:text-destructive",
|
|
1040
|
+
"disabled:opacity-50 disabled:cursor-not-allowed"
|
|
1041
|
+
),
|
|
1042
|
+
style: {
|
|
1043
|
+
flex: 1,
|
|
1044
|
+
display: "flex",
|
|
1045
|
+
alignItems: "center",
|
|
1046
|
+
justifyContent: "center",
|
|
1047
|
+
gap: "6px",
|
|
1048
|
+
whiteSpace: "nowrap",
|
|
1049
|
+
minWidth: 0
|
|
1050
|
+
},
|
|
1051
|
+
children: [
|
|
1052
|
+
actionType === "reject" && /* @__PURE__ */ jsx(Loader2, { className: "w-4 h-4 animate-spin", style: { flexShrink: 0 } }),
|
|
1053
|
+
actionType === "reject" ? MODAL_CONTENT.LOADING_REJECT : BUTTON_LABELS.REJECT
|
|
1054
|
+
]
|
|
1055
|
+
}
|
|
1056
|
+
),
|
|
1057
|
+
/* @__PURE__ */ jsxs(
|
|
1058
|
+
"button",
|
|
1059
|
+
{
|
|
1060
|
+
onClick: handleApprove,
|
|
1061
|
+
disabled: !isOtpValid || isSubmitting,
|
|
1062
|
+
className: cn(
|
|
1063
|
+
"py-2.5 px-4 rounded-lg text-sm font-medium transition-colors",
|
|
1064
|
+
"bg-primary text-primary-foreground hover:bg-primary/90 active:bg-primary/80",
|
|
1065
|
+
"disabled:opacity-50 disabled:cursor-not-allowed"
|
|
1066
|
+
),
|
|
1067
|
+
style: {
|
|
1068
|
+
flex: 1,
|
|
1069
|
+
display: "flex",
|
|
1070
|
+
alignItems: "center",
|
|
1071
|
+
justifyContent: "center",
|
|
1072
|
+
gap: "6px",
|
|
1073
|
+
whiteSpace: "nowrap",
|
|
1074
|
+
minWidth: 0
|
|
1075
|
+
},
|
|
1076
|
+
children: [
|
|
1077
|
+
actionType === "approve" && /* @__PURE__ */ jsx(Loader2, { className: "w-4 h-4 animate-spin", style: { flexShrink: 0 } }),
|
|
1078
|
+
actionType === "approve" ? MODAL_CONTENT.LOADING_APPROVE : BUTTON_LABELS.APPROVE
|
|
1079
|
+
]
|
|
1080
|
+
}
|
|
1081
|
+
)
|
|
1082
|
+
]
|
|
1083
|
+
}
|
|
1084
|
+
),
|
|
1085
|
+
/* @__PURE__ */ jsxs(
|
|
1086
|
+
"button",
|
|
1087
|
+
{
|
|
1088
|
+
onClick: handleResend,
|
|
1089
|
+
disabled: isSubmitting || resendCooldownRemaining > 0,
|
|
1090
|
+
className: cn(
|
|
1091
|
+
"py-2 px-4 rounded-lg text-xs font-medium transition-colors w-full",
|
|
1092
|
+
"text-muted-foreground hover:text-foreground",
|
|
1093
|
+
"disabled:opacity-50 disabled:cursor-not-allowed"
|
|
1094
|
+
),
|
|
1095
|
+
style: {
|
|
1096
|
+
display: "flex",
|
|
1097
|
+
alignItems: "center",
|
|
1098
|
+
justifyContent: "center",
|
|
1099
|
+
gap: "6px",
|
|
1100
|
+
whiteSpace: "nowrap"
|
|
1101
|
+
},
|
|
1102
|
+
children: [
|
|
1103
|
+
actionType === "resend" && /* @__PURE__ */ jsx(Loader2, { className: "w-3.5 h-3.5 animate-spin", style: { flexShrink: 0 } }),
|
|
1104
|
+
actionType === "resend" ? MODAL_CONTENT.LOADING_RESEND : resendCooldownRemaining > 0 ? `${MODAL_CONTENT.RESEND_AVAILABLE_IN} ${resendCooldownRemaining}s` : BUTTON_LABELS.RESEND
|
|
1105
|
+
]
|
|
1106
|
+
}
|
|
1107
|
+
)
|
|
1108
|
+
]
|
|
1109
|
+
}
|
|
1110
|
+
)
|
|
1111
|
+
]
|
|
1112
|
+
}
|
|
1113
|
+
)
|
|
1114
|
+
}
|
|
1115
|
+
) });
|
|
1116
|
+
}
|
|
1117
|
+
var DEFAULT_USER_ACTION_STATE = {
|
|
1118
|
+
request: null,
|
|
1119
|
+
clearOtpTrigger: 0
|
|
1120
|
+
};
|
|
1121
|
+
var NOOP_ASYNC = async () => {
|
|
1122
|
+
};
|
|
652
1123
|
function PaymanChat({
|
|
653
1124
|
config,
|
|
654
1125
|
callbacks = {},
|
|
@@ -657,6 +1128,7 @@ function PaymanChat({
|
|
|
657
1128
|
children
|
|
658
1129
|
}) {
|
|
659
1130
|
const [inputValue, setInputValue] = useState("");
|
|
1131
|
+
const chat = useChat(config, callbacks);
|
|
660
1132
|
const {
|
|
661
1133
|
messages,
|
|
662
1134
|
sendMessage,
|
|
@@ -666,7 +1138,12 @@ function PaymanChat({
|
|
|
666
1138
|
cancelStream,
|
|
667
1139
|
getSessionId,
|
|
668
1140
|
getMessages
|
|
669
|
-
} =
|
|
1141
|
+
} = chat;
|
|
1142
|
+
const userActionState = chat.userActionState ?? DEFAULT_USER_ACTION_STATE;
|
|
1143
|
+
const approveUserAction = chat.approveUserAction ?? NOOP_ASYNC;
|
|
1144
|
+
const rejectUserAction = chat.rejectUserAction ?? NOOP_ASYNC;
|
|
1145
|
+
const resendOtp = chat.resendOtp ?? NOOP_ASYNC;
|
|
1146
|
+
const isUserActionSupported = typeof chat.approveUserAction === "function" && typeof chat.rejectUserAction === "function" && typeof chat.resendOtp === "function";
|
|
670
1147
|
const contextValue = useMemo(
|
|
671
1148
|
() => ({
|
|
672
1149
|
resetSession,
|
|
@@ -701,6 +1178,7 @@ function PaymanChat({
|
|
|
701
1178
|
agentName = "Assistant",
|
|
702
1179
|
showExecutionSteps = true,
|
|
703
1180
|
showStreamingDot = true,
|
|
1181
|
+
inputStyle = "rounded",
|
|
704
1182
|
layout = "full-width",
|
|
705
1183
|
showTimestamps = false,
|
|
706
1184
|
animated = true,
|
|
@@ -795,7 +1273,20 @@ function PaymanChat({
|
|
|
795
1273
|
placeholder,
|
|
796
1274
|
isWaitingForResponse,
|
|
797
1275
|
hasSelectedSession: true,
|
|
798
|
-
isSessionParamsConfigured
|
|
1276
|
+
isSessionParamsConfigured,
|
|
1277
|
+
inputStyle,
|
|
1278
|
+
layout
|
|
1279
|
+
}
|
|
1280
|
+
),
|
|
1281
|
+
/* @__PURE__ */ jsx(
|
|
1282
|
+
UserActionModal,
|
|
1283
|
+
{
|
|
1284
|
+
isOpen: isUserActionSupported && userActionState.request !== null,
|
|
1285
|
+
userActionRequest: userActionState.request,
|
|
1286
|
+
onApprove: approveUserAction,
|
|
1287
|
+
onReject: rejectUserAction,
|
|
1288
|
+
onResend: resendOtp,
|
|
1289
|
+
clearOtpTrigger: userActionState.clearOtpTrigger
|
|
799
1290
|
}
|
|
800
1291
|
)
|
|
801
1292
|
]
|