@paymanai/payman-ask-sdk 1.2.23 → 1.2.25

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
@@ -1,15 +1,16 @@
1
- import { useChat, useVoice } from '@paymanai/payman-typescript-ask-sdk';
2
- export { cancelUserAction, generateId, resendUserAction, streamWorkflowEvents, submitUserAction, useChat, useVoice } from '@paymanai/payman-typescript-ask-sdk';
1
+ import { useVoice, useChat, useChatV2, buildFormattedThinking } from '@paymanai/payman-typescript-ask-sdk';
2
+ export { buildFormattedThinking, cancelUserAction, createInitialV2State, generateId, processStreamEventV2, resendUserAction, streamWorkflowEvents, submitUserAction, useChat, useChatV2, useVoice } from '@paymanai/payman-typescript-ask-sdk';
3
3
  import { AnimatePresence, motion } from 'framer-motion';
4
- import { createContext, forwardRef, useState, useRef, useEffect, useMemo, useImperativeHandle, useCallback, useLayoutEffect, useContext } from 'react';
4
+ import { createContext, forwardRef, useRef, useState, useCallback, useImperativeHandle, useEffect, useMemo, useLayoutEffect, useContext } from 'react';
5
5
  import { clsx } from 'clsx';
6
6
  import { twMerge } from 'tailwind-merge';
7
7
  import * as Sentry from '@sentry/react';
8
- import { Check, RotateCcw, Mic, ArrowUp, ArrowDown, X, Loader2, User, Clock, Sparkles, Binoculars, ChevronDown, ChevronRight } from 'lucide-react';
9
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
+ import { ArrowDown, Pencil, X, RotateCcw, Plus, ImagePlus, Paperclip, Mic, ArrowUp, Check, AlertCircle, Copy, WifiOff, SearchCode, ShieldCheck, Loader2, Download, ChevronRight, User, Clock, Sparkles, Binoculars, ImageOff, Eye, ChevronDown } from 'lucide-react';
9
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
10
10
  import ReactMarkdown from 'react-markdown';
11
11
  import remarkGfm from 'remark-gfm';
12
12
  import { createPortal } from 'react-dom';
13
+ import { interpolate } from 'flubber';
13
14
 
14
15
  var PaymanChatContext = createContext(void 0);
15
16
  function usePaymanChat() {
@@ -454,7 +455,7 @@ function ImageLightbox({
454
455
  background: "rgba(2, 6, 23, 0.92)",
455
456
  isolation: "isolate"
456
457
  };
457
- const frameStyle = {
458
+ const frameStyle2 = {
458
459
  position: "relative",
459
460
  width: "min(92vw, 1280px)",
460
461
  height: "min(88vh, 920px)",
@@ -514,7 +515,7 @@ function ImageLightbox({
514
515
  children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
515
516
  }
516
517
  ),
517
- /* @__PURE__ */ jsxs("div", { style: frameStyle, onClick: (event) => event.stopPropagation(), children: [
518
+ /* @__PURE__ */ jsxs("div", { style: frameStyle2, onClick: (event) => event.stopPropagation(), children: [
518
519
  !isImageLoaded ? /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center gap-2", children: [
519
520
  /* @__PURE__ */ jsx(Loader2, { className: "h-5 w-5 animate-spin text-white/80" }),
520
521
  /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-white/90", children: "Loading image" }),
@@ -1398,6 +1399,101 @@ function MessageList({
1398
1399
  }
1399
1400
  ) });
1400
1401
  }
1402
+ function ResetSessionConfirmModal({
1403
+ isOpen,
1404
+ onClose,
1405
+ onConfirm
1406
+ }) {
1407
+ const handleKeyDown = useCallback(
1408
+ (event) => {
1409
+ if (event.key === "Escape") {
1410
+ onClose();
1411
+ }
1412
+ },
1413
+ [onClose]
1414
+ );
1415
+ useEffect(() => {
1416
+ if (!isOpen || typeof document === "undefined") return;
1417
+ document.addEventListener("keydown", handleKeyDown);
1418
+ const previousOverflow = document.body.style.overflow;
1419
+ document.body.style.overflow = "hidden";
1420
+ return () => {
1421
+ document.removeEventListener("keydown", handleKeyDown);
1422
+ document.body.style.overflow = previousOverflow;
1423
+ };
1424
+ }, [handleKeyDown, isOpen]);
1425
+ return /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen ? /* @__PURE__ */ jsxs(
1426
+ motion.div,
1427
+ {
1428
+ className: "payman-reset-session-modal-backdrop",
1429
+ initial: { opacity: 0 },
1430
+ animate: { opacity: 1 },
1431
+ exit: { opacity: 0 },
1432
+ transition: { duration: 0.18 },
1433
+ onClick: onClose,
1434
+ role: "presentation",
1435
+ children: [
1436
+ /* @__PURE__ */ jsx("div", { className: "payman-reset-session-modal-overlay" }),
1437
+ /* @__PURE__ */ jsxs(
1438
+ motion.div,
1439
+ {
1440
+ initial: { opacity: 0, y: 12, scale: 0.98 },
1441
+ animate: { opacity: 1, y: 0, scale: 1 },
1442
+ exit: { opacity: 0, y: 8, scale: 0.98 },
1443
+ transition: { duration: 0.2, ease: [0.16, 1, 0.3, 1] },
1444
+ className: "payman-reset-session-modal-dialog",
1445
+ onClick: (event) => event.stopPropagation(),
1446
+ role: "dialog",
1447
+ "aria-modal": "true",
1448
+ "aria-labelledby": "payman-reset-session-title",
1449
+ "aria-describedby": "payman-reset-session-description",
1450
+ children: [
1451
+ /* @__PURE__ */ jsxs("div", { className: "payman-reset-session-modal-copy", children: [
1452
+ /* @__PURE__ */ jsx("p", { className: "payman-reset-session-modal-eyebrow", children: "New Session" }),
1453
+ /* @__PURE__ */ jsx(
1454
+ "h2",
1455
+ {
1456
+ id: "payman-reset-session-title",
1457
+ className: "payman-reset-session-modal-title",
1458
+ children: "Start a new session?"
1459
+ }
1460
+ ),
1461
+ /* @__PURE__ */ jsx(
1462
+ "p",
1463
+ {
1464
+ id: "payman-reset-session-description",
1465
+ className: "payman-reset-session-modal-description",
1466
+ children: "This will clear the current conversation and start fresh."
1467
+ }
1468
+ )
1469
+ ] }),
1470
+ /* @__PURE__ */ jsxs("div", { className: "payman-reset-session-modal-actions", children: [
1471
+ /* @__PURE__ */ jsx(
1472
+ "button",
1473
+ {
1474
+ type: "button",
1475
+ onClick: onClose,
1476
+ className: "payman-reset-session-modal-btn payman-reset-session-modal-btn-secondary",
1477
+ children: "Cancel"
1478
+ }
1479
+ ),
1480
+ /* @__PURE__ */ jsx(
1481
+ "button",
1482
+ {
1483
+ type: "button",
1484
+ onClick: onConfirm,
1485
+ className: "payman-reset-session-modal-btn payman-reset-session-modal-btn-primary",
1486
+ children: "New Session"
1487
+ }
1488
+ )
1489
+ ] })
1490
+ ]
1491
+ }
1492
+ )
1493
+ ]
1494
+ }
1495
+ ) : null });
1496
+ }
1401
1497
 
1402
1498
  // src/assets/payman-mono-crop-blue.png
1403
1499
  var payman_mono_crop_blue_default = "data:image/png;base64,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";
@@ -2054,139 +2150,2304 @@ function UserActionModal({
2054
2150
  }
2055
2151
  );
2056
2152
  }
2057
- var DEFAULT_USER_ACTION_STATE = {
2058
- request: null,
2059
- clearOtpTrigger: 0
2060
- };
2061
- var NOOP_ASYNC = async () => {
2062
- };
2063
- var PaymanChat = forwardRef(function PaymanChat2({
2064
- config,
2065
- callbacks = {},
2066
- className,
2067
- style,
2068
- children,
2069
- onLoadMoreMessages,
2070
- isLoadingMoreMessages = false,
2071
- hasMoreMessages = false
2072
- }, ref) {
2073
- const [inputValue, setInputValue] = useState("");
2074
- const prevInputValueRef = useRef(inputValue);
2075
- const [hasEverSentMessage, setHasEverSentMessage] = useState(false);
2153
+ function ActionTooltipV2({ label, children }) {
2154
+ return /* @__PURE__ */ jsxs("div", { className: "payman-v2-tooltip", children: [
2155
+ children,
2156
+ /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "payman-v2-tooltip-content", children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-tooltip-text", children: [
2157
+ label,
2158
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-tooltip-arrow" })
2159
+ ] }) })
2160
+ ] });
2161
+ }
2162
+ function formatMessageTime(timestamp) {
2163
+ const value = new Date(timestamp);
2164
+ if (Number.isNaN(value.getTime())) return "";
2165
+ return new Intl.DateTimeFormat(void 0, {
2166
+ hour: "numeric",
2167
+ minute: "2-digit"
2168
+ }).format(value);
2169
+ }
2170
+ function UserMessageV2({
2171
+ message,
2172
+ onEdit,
2173
+ onRetry,
2174
+ retryDisabled = false,
2175
+ actions
2176
+ }) {
2177
+ const [copied, setCopied] = useState(false);
2178
+ const [toast, setToast] = useState(null);
2179
+ const copyResetTimerRef = useRef(null);
2180
+ const toastTimerRef = useRef(null);
2181
+ const showCopyAction = actions?.copy ?? true;
2182
+ const showEditAction = actions?.edit ?? false;
2183
+ const showRetryAction = actions?.retry ?? false;
2076
2184
  useEffect(() => {
2077
- if (config.sentryDsn) {
2078
- initSentryIfNeeded(config.sentryDsn);
2185
+ return () => {
2186
+ if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
2187
+ if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
2188
+ };
2189
+ }, []);
2190
+ const showToast = (label, tone) => {
2191
+ if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
2192
+ setToast({ label, tone });
2193
+ toastTimerRef.current = setTimeout(() => setToast(null), 1800);
2194
+ };
2195
+ const handleCopy = async () => {
2196
+ try {
2197
+ if (!navigator.clipboard?.writeText) {
2198
+ throw new Error("Clipboard unavailable");
2199
+ }
2200
+ await navigator.clipboard.writeText(message.content);
2201
+ if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
2202
+ setCopied(true);
2203
+ copyResetTimerRef.current = setTimeout(() => setCopied(false), 1800);
2204
+ showToast("Copied to clipboard", "success");
2205
+ } catch {
2206
+ setCopied(false);
2207
+ showToast("Could not copy", "error");
2079
2208
  }
2080
- }, [config.sentryDsn]);
2081
- const sentryCtxRef = useRef({});
2082
- const callbacksRef = useRef(callbacks);
2083
- callbacksRef.current = callbacks;
2084
- const initialSessionId = config.initialSessionId;
2085
- const apiHeaders = config.api.headers;
2209
+ };
2210
+ const timestamp = formatMessageTime(message.timestamp);
2211
+ const hasVisibleActions = showCopyAction || showEditAction && !!onEdit || showRetryAction && !!onRetry;
2212
+ const toastPortal = typeof document !== "undefined" ? createPortal(
2213
+ /* @__PURE__ */ jsx(AnimatePresence, { children: toast && /* @__PURE__ */ jsx(
2214
+ motion.div,
2215
+ {
2216
+ initial: { opacity: 0, y: -18, scale: 0.96 },
2217
+ animate: { opacity: 1, y: 0, scale: 1 },
2218
+ exit: { opacity: 0, y: -12, scale: 0.96 },
2219
+ transition: {
2220
+ type: "spring",
2221
+ stiffness: 360,
2222
+ damping: 26,
2223
+ mass: 0.7
2224
+ },
2225
+ className: "payman-v2-toast",
2226
+ role: "status",
2227
+ "aria-live": "polite",
2228
+ children: /* @__PURE__ */ jsxs(
2229
+ "div",
2230
+ {
2231
+ className: cn(
2232
+ "payman-v2-toast-inner",
2233
+ toast.tone === "success" ? "payman-v2-toast-success" : "payman-v2-toast-error"
2234
+ ),
2235
+ children: [
2236
+ toast.tone === "success" ? /* @__PURE__ */ jsx(Check, { className: "h-4 w-4", style: { color: "#059669" } }) : /* @__PURE__ */ jsx(
2237
+ AlertCircle,
2238
+ {
2239
+ className: "h-4 w-4",
2240
+ style: { color: "#ef4444" }
2241
+ }
2242
+ ),
2243
+ /* @__PURE__ */ jsx("span", { children: toast.label })
2244
+ ]
2245
+ }
2246
+ )
2247
+ }
2248
+ ) }),
2249
+ document.body
2250
+ ) : null;
2251
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2252
+ toastPortal,
2253
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-user-msg payman-v2-fade-in", children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-user-msg-group", children: [
2254
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-user-msg-bubble", children: /* @__PURE__ */ jsx("p", { className: "payman-v2-user-msg-text", children: message.content }) }),
2255
+ message.isError && message.errorDetails && (() => {
2256
+ const resolvedError = getConflictErrorMessage(message.errorDetails) ?? message.errorDetails;
2257
+ return /* @__PURE__ */ jsxs("div", { className: "payman-v2-user-msg-error", children: [
2258
+ /* @__PURE__ */ jsx(
2259
+ AlertCircle,
2260
+ {
2261
+ className: "h-3.5 w-3.5 shrink-0",
2262
+ style: { color: "rgba(239, 68, 68, 0.7)", marginTop: "2px" }
2263
+ }
2264
+ ),
2265
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-user-msg-error-text", children: resolvedError })
2266
+ ] });
2267
+ })(),
2268
+ (timestamp || hasVisibleActions) && /* @__PURE__ */ jsxs("div", { className: "payman-v2-user-msg-actions", children: [
2269
+ timestamp ? /* @__PURE__ */ jsx("span", { className: "payman-v2-user-msg-timestamp", children: timestamp }) : null,
2270
+ showCopyAction && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Copy", children: /* @__PURE__ */ jsx(
2271
+ "button",
2272
+ {
2273
+ type: "button",
2274
+ onClick: () => void handleCopy(),
2275
+ className: "payman-v2-user-msg-action-btn",
2276
+ "aria-label": "Copy message",
2277
+ children: copied ? /* @__PURE__ */ jsx(
2278
+ Check,
2279
+ {
2280
+ className: "h-3.5 w-3.5",
2281
+ style: { color: "#059669" }
2282
+ }
2283
+ ) : /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" })
2284
+ }
2285
+ ) }),
2286
+ showEditAction && onEdit && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Edit", children: /* @__PURE__ */ jsx(
2287
+ "button",
2288
+ {
2289
+ type: "button",
2290
+ onClick: () => onEdit(message.id),
2291
+ className: "payman-v2-user-msg-action-btn",
2292
+ "aria-label": "Edit message",
2293
+ children: /* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" })
2294
+ }
2295
+ ) }),
2296
+ showRetryAction && onRetry && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Retry", children: /* @__PURE__ */ jsx(
2297
+ "button",
2298
+ {
2299
+ type: "button",
2300
+ onClick: () => onRetry(message.id),
2301
+ disabled: retryDisabled,
2302
+ className: "payman-v2-user-msg-action-btn",
2303
+ "aria-label": "Retry message",
2304
+ children: /* @__PURE__ */ jsx(RotateCcw, { className: "h-3.5 w-3.5" })
2305
+ }
2306
+ ) })
2307
+ ] })
2308
+ ] }) })
2309
+ ] });
2310
+ }
2311
+ var RAG_IMAGE_PATH_REGEX2 = /^(?:https?:\/\/[^/\s]+)?\/api\/rag\/chunks\/[^"'\s]+\/image(?:[?#][^"'\s]*)?$/;
2312
+ function isUnresolvedRagImageSource2(src) {
2313
+ return RAG_IMAGE_PATH_REGEX2.test(src);
2314
+ }
2315
+ var frameStyle = {
2316
+ width: "min(100%, 32rem)",
2317
+ maxWidth: "100%"
2318
+ };
2319
+ var imgStyle = {
2320
+ display: "block",
2321
+ width: "100%",
2322
+ height: "auto",
2323
+ maxWidth: "100%",
2324
+ maxHeight: "22rem",
2325
+ objectFit: "contain"
2326
+ };
2327
+ function MarkdownImageV2({
2328
+ src,
2329
+ alt,
2330
+ isResolving = false,
2331
+ onImageClick
2332
+ }) {
2333
+ const [isVisible, setIsVisible] = useState(false);
2334
+ const [isLoaded, setIsLoaded] = useState(false);
2335
+ const [hasError, setHasError] = useState(false);
2336
+ const [retryCount, setRetryCount] = useState(0);
2337
+ const sentinelRef = useRef(null);
2338
+ const isUnresolvedRag = useMemo(
2339
+ () => src ? isUnresolvedRagImageSource2(src) : false,
2340
+ [src]
2341
+ );
2342
+ const isResolvingRag = Boolean(isResolving && isUnresolvedRag);
2086
2343
  useEffect(() => {
2087
- sentryCtxRef.current.workflowName = config.workflowName;
2088
- sentryCtxRef.current.sessionOwnerId = config.sessionParams?.id;
2089
- if (initialSessionId) {
2090
- sentryCtxRef.current.sessionId = initialSessionId;
2091
- }
2092
- if (apiHeaders) {
2093
- sentryCtxRef.current.customerId = apiHeaders["x-paygent-wf-mcp-customer-id"] ?? sentryCtxRef.current.customerId;
2094
- sentryCtxRef.current.customerEmail = apiHeaders["x-paygent-wf-mcp-customer-email"] ?? sentryCtxRef.current.customerEmail;
2095
- }
2096
- }, [
2097
- config.workflowName,
2098
- config.sessionParams?.id,
2099
- initialSessionId,
2100
- apiHeaders
2101
- ]);
2344
+ setIsLoaded(false);
2345
+ setHasError(false);
2346
+ setRetryCount(0);
2347
+ setIsVisible(false);
2348
+ }, [src]);
2102
2349
  useEffect(() => {
2103
- const endpoint = config.api.streamEndpoint || "/api/workflows/ask/stream";
2104
- return subscribeToCfRay(endpoint, (cfRay) => {
2105
- sentryCtxRef.current.cfRay = cfRay;
2106
- });
2107
- }, [config.api.streamEndpoint]);
2108
- const sentryCallbacks = useMemo(
2109
- () => ({
2110
- onMessageSent: (msg) => callbacksRef.current.onMessageSent?.(msg),
2111
- onStreamStart: () => callbacksRef.current.onStreamStart?.(),
2112
- onStreamComplete: (message) => {
2113
- if (message.executionId)
2114
- sentryCtxRef.current.executionId = message.executionId;
2115
- if (message.sessionId)
2116
- sentryCtxRef.current.sessionId = message.sessionId;
2117
- const content = message.content ?? "";
2118
- const looksLikeRawErr = content.length >= 10 && (content.includes("errorType=") || /failed:\s*\{/.test(content));
2119
- const completedEmpty = !message.isStreaming && !message.isCancelled && content.length === 0 && (message.streamProgress === "completed" || message.streamProgress === "error");
2120
- const hasConflict = !!getConflictErrorMessage(message.errorDetails);
2121
- const hasFriendlyErr = isFriendlyWorkflowError(message.errorDetails);
2122
- const shouldCapture = message.isError || hasConflict || hasFriendlyErr || looksLikeRawErr || completedEmpty;
2123
- if (shouldCapture) {
2124
- sentryCtxRef.current.route = typeof window !== "undefined" ? window.location.pathname : void 0;
2125
- captureSentryError(
2126
- `Workflow error: ${message.errorDetails || content || "Unknown error"}`,
2127
- { ...sentryCtxRef.current }
2128
- );
2350
+ const el = sentinelRef.current;
2351
+ if (!el || !src) return;
2352
+ const observer = new IntersectionObserver(
2353
+ ([entry]) => {
2354
+ if (entry.isIntersecting) {
2355
+ setIsVisible(true);
2356
+ observer.disconnect();
2129
2357
  }
2130
- callbacksRef.current.onStreamComplete?.(message);
2131
2358
  },
2132
- onError: (error) => {
2133
- sentryCtxRef.current.route = typeof window !== "undefined" ? window.location.pathname : void 0;
2134
- captureSentryError(error, { ...sentryCtxRef.current });
2135
- callbacksRef.current.onError?.(error);
2359
+ { rootMargin: "200px" }
2360
+ );
2361
+ observer.observe(el);
2362
+ return () => observer.disconnect();
2363
+ }, [src]);
2364
+ if (!src) return null;
2365
+ if (isResolvingRag) {
2366
+ return /* @__PURE__ */ jsx(
2367
+ "span",
2368
+ {
2369
+ className: cn("payman-v2-md-image", "payman-v2-md-image-resolving"),
2370
+ children: /* @__PURE__ */ jsxs("span", { className: "payman-v2-md-image-resolving-inner", children: [
2371
+ /* @__PURE__ */ jsx(Loader2, { className: "payman-v2-md-image-loading", "aria-hidden": true }),
2372
+ /* @__PURE__ */ jsx("span", { children: "Loading image" }),
2373
+ /* @__PURE__ */ jsx("span", { children: "Reference image" })
2374
+ ] })
2375
+ }
2376
+ );
2377
+ }
2378
+ if (hasError) {
2379
+ return /* @__PURE__ */ jsxs("span", { className: cn("payman-v2-md-image", "payman-v2-md-image-error"), children: [
2380
+ /* @__PURE__ */ jsx(ImageOff, { "aria-hidden": true }),
2381
+ /* @__PURE__ */ jsx("span", { children: "Unable to load image" }),
2382
+ alt ? /* @__PURE__ */ jsx("span", { children: alt }) : null,
2383
+ retryCount < 3 ? /* @__PURE__ */ jsx(
2384
+ "button",
2385
+ {
2386
+ type: "button",
2387
+ className: "payman-v2-md-image-error-retry",
2388
+ onClick: () => {
2389
+ setHasError(false);
2390
+ setRetryCount((c) => c + 1);
2391
+ },
2392
+ children: "Retry"
2393
+ }
2394
+ ) : null
2395
+ ] });
2396
+ }
2397
+ const imgSrc = retryCount > 0 ? `${src}${src.includes("?") ? "&" : "?"}_r=${retryCount}` : src;
2398
+ return /* @__PURE__ */ jsx("span", { ref: sentinelRef, className: "payman-v2-md-image", children: isVisible ? /* @__PURE__ */ jsxs(
2399
+ "button",
2400
+ {
2401
+ type: "button",
2402
+ className: "payman-v2-md-image-button",
2403
+ onClick: () => {
2404
+ if (isLoaded && src) onImageClick?.(src, alt || "Image");
2136
2405
  },
2137
- onSessionIdChange: (sessionId) => {
2138
- sentryCtxRef.current.sessionId = sessionId;
2139
- callbacksRef.current.onSessionIdChange?.(sessionId);
2406
+ disabled: !isLoaded,
2407
+ "aria-busy": !isLoaded,
2408
+ style: {
2409
+ ...frameStyle,
2410
+ ...!isLoaded ? { minHeight: "10rem" } : {}
2140
2411
  },
2141
- onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
2142
- onResetSession: () => callbacksRef.current.onResetSession?.(),
2143
- onUserActionRequired: (req) => callbacksRef.current.onUserActionRequired?.(req),
2144
- onUserActionEvent: (evType, msg) => callbacksRef.current.onUserActionEvent?.(evType, msg)
2145
- }),
2146
- // eslint-disable-next-line react-hooks/exhaustive-deps
2147
- []
2148
- );
2149
- const chat = useChat(config, sentryCallbacks);
2150
- const {
2151
- messages,
2152
- sendMessage,
2153
- isWaitingForResponse,
2154
- resetSession,
2155
- clearMessages,
2156
- prependMessages,
2157
- cancelStream,
2158
- getSessionId,
2159
- getMessages
2160
- } = chat;
2161
- useEffect(() => {
2162
- if (messages.length > 0 && !hasEverSentMessage) {
2163
- setHasEverSentMessage(true);
2412
+ children: [
2413
+ !isLoaded && /* @__PURE__ */ jsxs("span", { className: "payman-v2-md-image-placeholder", children: [
2414
+ /* @__PURE__ */ jsx(
2415
+ Loader2,
2416
+ {
2417
+ className: "payman-v2-md-image-loading",
2418
+ "aria-hidden": true
2419
+ }
2420
+ ),
2421
+ /* @__PURE__ */ jsx("span", { children: "Loading image\u2026" })
2422
+ ] }),
2423
+ /* @__PURE__ */ jsx(
2424
+ "img",
2425
+ {
2426
+ src: imgSrc,
2427
+ alt: alt || "",
2428
+ className: "payman-v2-md-image-img",
2429
+ style: {
2430
+ ...imgStyle,
2431
+ opacity: isLoaded ? 1 : 0
2432
+ },
2433
+ onLoad: () => {
2434
+ setHasError(false);
2435
+ setIsLoaded(true);
2436
+ },
2437
+ onError: () => {
2438
+ setIsLoaded(false);
2439
+ setHasError(true);
2440
+ }
2441
+ }
2442
+ ),
2443
+ isLoaded ? /* @__PURE__ */ jsx("span", { className: "payman-v2-md-image-overlay", "aria-hidden": true, children: /* @__PURE__ */ jsx("span", { className: "payman-v2-md-image-overlay-icon", children: /* @__PURE__ */ jsx(Eye, {}) }) }) : null
2444
+ ]
2164
2445
  }
2165
- }, [messages.length, hasEverSentMessage]);
2166
- const userActionState = chat.userActionState ?? DEFAULT_USER_ACTION_STATE;
2167
- const approveUserAction = chat.approveUserAction ?? NOOP_ASYNC;
2168
- const rejectUserAction = chat.rejectUserAction ?? NOOP_ASYNC;
2169
- const resendOtp = chat.resendOtp ?? NOOP_ASYNC;
2170
- const isUserActionSupported = typeof chat.approveUserAction === "function" && typeof chat.rejectUserAction === "function" && typeof chat.resendOtp === "function";
2171
- const {
2172
- isAvailable: voiceAvailable,
2173
- isRecording,
2174
- startRecording,
2175
- stopRecording,
2176
- clearTranscript
2177
- } = useVoice(
2178
- {
2179
- lang: config.voiceLang || "en-US",
2180
- interimResults: config.voiceInterimResults !== false,
2181
- continuous: config.voiceContinuous !== false
2182
- },
2446
+ ) : /* @__PURE__ */ jsx(
2447
+ "span",
2183
2448
  {
2184
- onResult: (text) => {
2185
- setInputValue(text);
2186
- },
2187
- onEnd: () => {
2188
- },
2189
- onError: (error) => {
2449
+ className: "payman-v2-md-image-placeholder",
2450
+ style: { ...frameStyle, minHeight: "10rem" },
2451
+ children: /* @__PURE__ */ jsx("span", { children: "Image" })
2452
+ }
2453
+ ) });
2454
+ }
2455
+ function buildComponents(onImageClick, isResolvingImages) {
2456
+ return {
2457
+ p: ({ children }) => /* @__PURE__ */ jsx("p", { children }),
2458
+ code: ({ children }) => /* @__PURE__ */ jsx("code", { children }),
2459
+ pre: ({ children }) => /* @__PURE__ */ jsx("div", { className: "payman-v2-markdown-pre", children: /* @__PURE__ */ jsx("pre", { children }) }),
2460
+ ul: ({ children }) => /* @__PURE__ */ jsx("ul", { children }),
2461
+ ol: ({ children }) => /* @__PURE__ */ jsx("ol", { children }),
2462
+ li: ({ children }) => /* @__PURE__ */ jsx("li", { children }),
2463
+ h1: ({ children }) => /* @__PURE__ */ jsx("h1", { children }),
2464
+ h2: ({ children }) => /* @__PURE__ */ jsx("h2", { children }),
2465
+ h3: ({ children }) => /* @__PURE__ */ jsx("h3", { children }),
2466
+ strong: ({ children }) => /* @__PURE__ */ jsx("strong", { children }),
2467
+ em: ({ children }) => /* @__PURE__ */ jsx("em", { children }),
2468
+ blockquote: ({ children }) => /* @__PURE__ */ jsx("blockquote", { children }),
2469
+ hr: () => /* @__PURE__ */ jsx("hr", {}),
2470
+ a: ({ href, children }) => /* @__PURE__ */ jsx("a", { href, target: "_blank", rel: "noopener noreferrer", children }),
2471
+ img: ({ src, alt }) => /* @__PURE__ */ jsx(
2472
+ MarkdownImageV2,
2473
+ {
2474
+ src: typeof src === "string" ? src : void 0,
2475
+ alt: typeof alt === "string" ? alt : void 0,
2476
+ isResolving: isResolvingImages,
2477
+ onImageClick
2478
+ }
2479
+ ),
2480
+ table: ({ children }) => /* @__PURE__ */ jsx("div", { className: "payman-v2-markdown-table-wrapper", children: /* @__PURE__ */ jsx("table", { className: "payman-v2-markdown-table", children }) }),
2481
+ thead: ({ children }) => /* @__PURE__ */ jsx("thead", { className: "payman-v2-markdown-thead", children }),
2482
+ tbody: ({ children }) => /* @__PURE__ */ jsx("tbody", { className: "payman-v2-markdown-tbody", children }),
2483
+ th: ({ children }) => /* @__PURE__ */ jsx("th", { className: "payman-v2-markdown-th", children }),
2484
+ td: ({ children }) => /* @__PURE__ */ jsx("td", { className: "payman-v2-markdown-td", children })
2485
+ };
2486
+ }
2487
+ function MarkdownRendererV2({
2488
+ content,
2489
+ isStreaming,
2490
+ isResolvingImages,
2491
+ onImageClick
2492
+ }) {
2493
+ const components = useMemo(
2494
+ () => buildComponents(onImageClick, isResolvingImages),
2495
+ [onImageClick, isResolvingImages]
2496
+ );
2497
+ return /* @__PURE__ */ jsx(
2498
+ "div",
2499
+ {
2500
+ className: cn(
2501
+ "payman-v2-markdown",
2502
+ isStreaming && "payman-v2-streaming-cursor"
2503
+ ),
2504
+ children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components, children: content })
2505
+ }
2506
+ );
2507
+ }
2508
+ var PAYMAN_PATH = "M174.005 38.1616C159.62 18.4068 138.406 5.43014 114.263 1.62485C90.1187 -2.18045 65.9302 3.63155 46.1599 17.9906C21.9565 35.5752 6.06885 61.5137 1.39776 91.0344C-3.27333 120.555 3.85231 150.135 21.4358 174.305C43.0508 204.004 74.9451 223.506 111.243 229.244L122.415 231.013V171.273C121.968 171.273 121.522 171.302 121.076 171.302C116.955 171.302 112.82 170.975 108.684 170.321C106.795 170.024 104.92 169.638 103.076 169.207V207.839C76.5368 201.031 53.4045 185.364 37.0706 162.934C22.5218 142.941 16.6309 118.474 20.4838 94.037C24.3515 69.6148 37.502 48.1505 57.5103 33.5983C73.1004 22.2715 92.1865 17.6784 111.228 20.6811C130.269 23.6837 147.005 33.9253 158.355 49.5032C167.117 61.5583 170.673 76.2889 168.337 91.0047C166.016 105.72 158.087 118.653 146.038 127.408C136.815 134.112 125.524 136.832 114.248 135.048C102.972 133.264 93.079 127.214 86.355 117.984C81.2823 111.027 79.2443 102.51 80.5831 94.0073C81.922 85.5049 86.5038 78.0429 93.4658 72.9741C98.6129 69.2283 104.92 67.7121 111.213 68.7081C117.506 69.704 123.039 73.0782 126.788 78.2362C129.481 81.9374 130.567 86.4711 129.853 90.9898C129.139 95.5086 126.699 99.4774 122.995 102.183H146.648C147.719 99.5815 148.492 96.8464 148.939 94.0073C150.456 84.39 148.135 74.743 142.408 66.8797C135.625 57.5597 125.613 51.4207 114.218 49.637C102.823 47.8384 91.4129 50.5734 82.0707 57.3665C70.9285 65.4676 63.6095 77.4037 61.4525 91.0047C59.2955 104.606 62.5831 118.221 70.6905 129.355C80.4344 142.748 94.8195 151.548 111.198 154.134C127.577 156.72 143.97 152.781 157.373 143.03C173.603 131.228 184.269 113.822 187.408 94.0073C190.547 74.193 185.757 54.349 173.96 38.117L174.005 38.1616Z";
2509
+ var CIRCLE_PATH = "M95 36C139.183 36 175 71.817 175 116C175 160.183 139.183 196 95 196C50.817 196 15 160.183 15 116C15 71.817 50.817 36 95 36Z";
2510
+ function easeInOut(t) {
2511
+ return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
2512
+ }
2513
+ var TIMINGS = {
2514
+ // Total loop cycle = sum of all phases (ms)
2515
+ holdLogoMs: 900,
2516
+ morphToCircleMs: 550,
2517
+ holdCircleMs: 1100,
2518
+ morphToLogoMs: 550
2519
+ };
2520
+ var TOTAL_CYCLE = TIMINGS.holdLogoMs + TIMINGS.morphToCircleMs + TIMINGS.holdCircleMs + TIMINGS.morphToLogoMs;
2521
+ function phaseAtTime(elapsed) {
2522
+ let t = elapsed % TOTAL_CYCLE;
2523
+ if (t < TIMINGS.holdLogoMs) {
2524
+ return { kind: "hold-logo" };
2525
+ }
2526
+ t -= TIMINGS.holdLogoMs;
2527
+ if (t < TIMINGS.morphToCircleMs) {
2528
+ return {
2529
+ kind: "morph",
2530
+ direction: 1,
2531
+ progress: easeInOut(t / TIMINGS.morphToCircleMs)
2532
+ };
2533
+ }
2534
+ t -= TIMINGS.morphToCircleMs;
2535
+ if (t < TIMINGS.holdCircleMs) {
2536
+ return { kind: "hold-circle", progress: t / TIMINGS.holdCircleMs };
2537
+ }
2538
+ t -= TIMINGS.holdCircleMs;
2539
+ return {
2540
+ kind: "morph",
2541
+ direction: -1,
2542
+ progress: easeInOut(t / TIMINGS.morphToLogoMs)
2543
+ };
2544
+ }
2545
+ var RING_CX = 95;
2546
+ var RING_CY = 116;
2547
+ var RING_R = 65;
2548
+ var RING_STROKE_WIDTH = 22;
2549
+ var RING_CIRCUMFERENCE = 2 * Math.PI * RING_R;
2550
+ var RING_ARC_FRACTION = 0.3;
2551
+ var cachedInterpolators = null;
2552
+ var pendingInterpolators = null;
2553
+ function buildInterpolators() {
2554
+ const opts = { maxSegmentLength: 8 };
2555
+ return {
2556
+ forward: interpolate(PAYMAN_PATH, CIRCLE_PATH, opts),
2557
+ backward: interpolate(CIRCLE_PATH, PAYMAN_PATH, opts)
2558
+ };
2559
+ }
2560
+ function loadInterpolatorsAsync() {
2561
+ if (cachedInterpolators) return Promise.resolve(cachedInterpolators);
2562
+ if (pendingInterpolators) return pendingInterpolators;
2563
+ pendingInterpolators = new Promise((resolve) => {
2564
+ const run = () => {
2565
+ cachedInterpolators = buildInterpolators();
2566
+ resolve(cachedInterpolators);
2567
+ };
2568
+ const ric = globalThis.requestIdleCallback;
2569
+ if (typeof ric === "function") {
2570
+ ric(run, { timeout: 200 });
2571
+ } else {
2572
+ setTimeout(run, 0);
2573
+ }
2574
+ });
2575
+ return pendingInterpolators;
2576
+ }
2577
+ function PaymanMark() {
2578
+ const pathRef = useRef(null);
2579
+ const ringGroupRef = useRef(null);
2580
+ useEffect(() => {
2581
+ const reduced = window.matchMedia(
2582
+ "(prefers-reduced-motion: reduce)"
2583
+ ).matches;
2584
+ if (reduced) {
2585
+ pathRef.current?.setAttribute("d", PAYMAN_PATH);
2586
+ pathRef.current?.setAttribute("fill-opacity", "1");
2587
+ ringGroupRef.current?.setAttribute("opacity", "0");
2588
+ return;
2589
+ }
2590
+ let raf = 0;
2591
+ let cancelled = false;
2592
+ const start = performance.now();
2593
+ let interpolators = cachedInterpolators;
2594
+ const tick = (now) => {
2595
+ const elapsed = now - start;
2596
+ const phase = phaseAtTime(elapsed);
2597
+ let d;
2598
+ let fillOpacity = 1;
2599
+ let ringOpacity = 0;
2600
+ const spin = elapsed / 900 * 360;
2601
+ switch (phase.kind) {
2602
+ case "hold-logo":
2603
+ d = PAYMAN_PATH;
2604
+ fillOpacity = 1;
2605
+ ringOpacity = 0;
2606
+ break;
2607
+ case "morph": {
2608
+ if (!interpolators) {
2609
+ d = PAYMAN_PATH;
2610
+ fillOpacity = 1;
2611
+ ringOpacity = 0;
2612
+ break;
2613
+ }
2614
+ d = phase.direction === 1 ? interpolators.forward(phase.progress) : interpolators.backward(phase.progress);
2615
+ const p = phase.direction === 1 ? phase.progress : 1 - phase.progress;
2616
+ fillOpacity = p < 0.6 ? 1 : 1 - (p - 0.6) / 0.4;
2617
+ ringOpacity = p < 0.55 ? 0 : (p - 0.55) / 0.45;
2618
+ break;
2619
+ }
2620
+ case "hold-circle":
2621
+ d = CIRCLE_PATH;
2622
+ fillOpacity = 0;
2623
+ ringOpacity = 1;
2624
+ break;
2625
+ }
2626
+ if (pathRef.current) {
2627
+ pathRef.current.setAttribute("d", d);
2628
+ pathRef.current.setAttribute("fill-opacity", fillOpacity.toFixed(3));
2629
+ }
2630
+ if (ringGroupRef.current) {
2631
+ ringGroupRef.current.setAttribute("opacity", ringOpacity.toFixed(3));
2632
+ ringGroupRef.current.setAttribute(
2633
+ "transform",
2634
+ `rotate(${spin.toFixed(2)} ${RING_CX} ${RING_CY})`
2635
+ );
2636
+ }
2637
+ raf = requestAnimationFrame(tick);
2638
+ };
2639
+ raf = requestAnimationFrame(tick);
2640
+ if (!interpolators) {
2641
+ void loadInterpolatorsAsync().then((result) => {
2642
+ if (!cancelled) interpolators = result;
2643
+ });
2644
+ }
2645
+ return () => {
2646
+ cancelled = true;
2647
+ cancelAnimationFrame(raf);
2648
+ };
2649
+ }, []);
2650
+ return /* @__PURE__ */ jsxs(
2651
+ "svg",
2652
+ {
2653
+ className: "payman-v2-thinking-mark",
2654
+ viewBox: "0 0 190 232",
2655
+ "aria-hidden": true,
2656
+ focusable: "false",
2657
+ children: [
2658
+ /* @__PURE__ */ jsx("path", { ref: pathRef, d: PAYMAN_PATH, fill: "currentColor" }),
2659
+ /* @__PURE__ */ jsxs("g", { ref: ringGroupRef, opacity: 0, children: [
2660
+ /* @__PURE__ */ jsx(
2661
+ "circle",
2662
+ {
2663
+ cx: RING_CX,
2664
+ cy: RING_CY,
2665
+ r: RING_R,
2666
+ fill: "none",
2667
+ stroke: "currentColor",
2668
+ strokeWidth: RING_STROKE_WIDTH,
2669
+ strokeOpacity: 0.16
2670
+ }
2671
+ ),
2672
+ /* @__PURE__ */ jsx(
2673
+ "circle",
2674
+ {
2675
+ cx: RING_CX,
2676
+ cy: RING_CY,
2677
+ r: RING_R,
2678
+ fill: "none",
2679
+ stroke: "currentColor",
2680
+ strokeWidth: RING_STROKE_WIDTH,
2681
+ strokeLinecap: "round",
2682
+ strokeDasharray: `${RING_CIRCUMFERENCE * RING_ARC_FRACTION} ${RING_CIRCUMFERENCE}`
2683
+ }
2684
+ )
2685
+ ] })
2686
+ ]
2687
+ }
2688
+ );
2689
+ }
2690
+ var CURSOR_MESSAGES = [
2691
+ "Analyzing",
2692
+ "Processing",
2693
+ "Calculating",
2694
+ "Reviewing",
2695
+ "Verifying",
2696
+ "Assessing",
2697
+ "Evaluating",
2698
+ "Checking",
2699
+ "Planning",
2700
+ "Working",
2701
+ "Updating",
2702
+ "Validating",
2703
+ "Monitoring",
2704
+ "Optimizing",
2705
+ "Reconciling",
2706
+ "Forecasting",
2707
+ "Inspecting",
2708
+ "Organizing",
2709
+ "Sorting",
2710
+ "Scanning",
2711
+ "Balancing",
2712
+ "Summarizing",
2713
+ "Predicting",
2714
+ "Comparing",
2715
+ "Tracking",
2716
+ "Adjusting",
2717
+ "Examining",
2718
+ "Mapping",
2719
+ "Modeling",
2720
+ "Reporting",
2721
+ "Confirming"
2722
+ ];
2723
+ var FINAL_CURSOR_MESSAGE = "Finishing up";
2724
+ function getMaxDuration(...values) {
2725
+ const defined = values.filter(
2726
+ (value) => typeof value === "number" && Number.isFinite(value)
2727
+ );
2728
+ return defined.length > 0 ? Math.max(...defined) : void 0;
2729
+ }
2730
+ function parseThinkingContent(content) {
2731
+ const lines = content.split("\n");
2732
+ const out = [];
2733
+ for (const raw of lines) {
2734
+ const line = raw.trim();
2735
+ if (!line) continue;
2736
+ const stmt = line.match(/^\*\*(.+)\*\*$/);
2737
+ if (stmt) {
2738
+ out.push({ type: "statement", text: stmt[1].trim() });
2739
+ continue;
2740
+ }
2741
+ if (line.startsWith("\u2713 ")) {
2742
+ out.push({
2743
+ type: "status",
2744
+ variant: "success",
2745
+ text: line.slice(2).trim()
2746
+ });
2747
+ continue;
2748
+ }
2749
+ if (line.startsWith("\u2717 ")) {
2750
+ out.push({
2751
+ type: "status",
2752
+ variant: "error",
2753
+ text: line.slice(2).trim()
2754
+ });
2755
+ continue;
2756
+ }
2757
+ out.push({ type: "detail", text: line });
2758
+ }
2759
+ return out;
2760
+ }
2761
+ function AnimatedSeconds({
2762
+ value,
2763
+ className,
2764
+ ariaLabel
2765
+ }) {
2766
+ return /* @__PURE__ */ jsxs("span", { className: cn("payman-v2-thinking-seconds", className), "aria-label": ariaLabel, children: [
2767
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-thinking-seconds-track", "aria-hidden": "true", children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: /* @__PURE__ */ jsx(
2768
+ motion.span,
2769
+ {
2770
+ className: "payman-v2-thinking-seconds-value",
2771
+ initial: { opacity: 0, y: 6, filter: "blur(2px)" },
2772
+ animate: { opacity: 1, y: 0, filter: "blur(0px)" },
2773
+ exit: { opacity: 0, y: -6, filter: "blur(2px)" },
2774
+ transition: { duration: 0.2, ease: [0.22, 1, 0.36, 1] },
2775
+ children: value
2776
+ },
2777
+ value
2778
+ ) }) }),
2779
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-thinking-seconds-suffix", "aria-hidden": "true", children: "s" })
2780
+ ] });
2781
+ }
2782
+ function ThinkingBlockV2({
2783
+ content,
2784
+ isStreaming,
2785
+ durationSec,
2786
+ startedAt
2787
+ }) {
2788
+ const [open, setOpen] = useState(true);
2789
+ const [cursorIdx, setCursorIdx] = useState(0);
2790
+ const [elapsedSec, setElapsedSec] = useState(
2791
+ () => startedAt ? Math.max(0, Math.floor((Date.now() - startedAt) / 1e3)) : 0
2792
+ );
2793
+ const frozenSecRef = useRef(null);
2794
+ const prevStreaming = useRef(isStreaming);
2795
+ const parsed = useMemo(() => parseThinkingContent(content), [content]);
2796
+ const isFinalizingPhase = useMemo(() => {
2797
+ const statements = parsed.filter(
2798
+ (l) => l.type === "statement"
2799
+ );
2800
+ return statements.length > 0 && statements[statements.length - 1].text === "Finalizing";
2801
+ }, [parsed]);
2802
+ useEffect(() => {
2803
+ if (prevStreaming.current && !isStreaming) {
2804
+ setOpen(false);
2805
+ if (startedAt) {
2806
+ frozenSecRef.current = Math.max(
2807
+ 0,
2808
+ Math.floor((Date.now() - startedAt) / 1e3)
2809
+ );
2810
+ }
2811
+ }
2812
+ prevStreaming.current = isStreaming;
2813
+ }, [isStreaming, startedAt]);
2814
+ useEffect(() => {
2815
+ if (!isStreaming || !startedAt) return;
2816
+ const tick = () => {
2817
+ setElapsedSec(
2818
+ Math.max(0, Math.floor((Date.now() - startedAt) / 1e3))
2819
+ );
2820
+ };
2821
+ tick();
2822
+ const id = window.setInterval(tick, 1e3);
2823
+ return () => window.clearInterval(id);
2824
+ }, [isStreaming, startedAt]);
2825
+ useEffect(() => {
2826
+ if (!isStreaming || isFinalizingPhase) return;
2827
+ const id = window.setInterval(() => {
2828
+ setCursorIdx((i) => (i + 1) % CURSOR_MESSAGES.length);
2829
+ }, 4e3);
2830
+ return () => window.clearInterval(id);
2831
+ }, [isStreaming, isFinalizingPhase]);
2832
+ const justStoppedSec = !isStreaming && prevStreaming.current && startedAt ? Math.max(0, Math.floor((Date.now() - startedAt) / 1e3)) : void 0;
2833
+ const finalSec = getMaxDuration(
2834
+ durationSec,
2835
+ frozenSecRef.current,
2836
+ justStoppedSec,
2837
+ !isStreaming ? elapsedSec : void 0
2838
+ );
2839
+ const headerLabel = isStreaming ? /* @__PURE__ */ jsxs("span", { className: "payman-v2-thinking-header-label", children: [
2840
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-thinking-shimmer", children: "Working on it\u2026" }),
2841
+ startedAt !== void 0 && /* @__PURE__ */ jsx(
2842
+ AnimatedSeconds,
2843
+ {
2844
+ className: "payman-v2-thinking-timer",
2845
+ ariaLabel: `Elapsed ${elapsedSec} seconds`,
2846
+ value: elapsedSec
2847
+ }
2848
+ )
2849
+ ] }) : finalSec !== null && finalSec !== void 0 ? /* @__PURE__ */ jsxs("span", { className: "payman-v2-thinking-header-label", children: [
2850
+ /* @__PURE__ */ jsx("span", { children: "Thought for" }),
2851
+ /* @__PURE__ */ jsx(
2852
+ AnimatedSeconds,
2853
+ {
2854
+ className: "payman-v2-thinking-duration",
2855
+ ariaLabel: `Thought for ${finalSec} seconds`,
2856
+ value: finalSec
2857
+ }
2858
+ )
2859
+ ] }) : /* @__PURE__ */ jsx("span", { children: "Thought" });
2860
+ const cursorKey = isFinalizingPhase ? "finalizing" : String(cursorIdx);
2861
+ const cursorText = isFinalizingPhase ? FINAL_CURSOR_MESSAGE : CURSOR_MESSAGES[cursorIdx];
2862
+ return /* @__PURE__ */ jsxs("div", { className: "payman-v2-thinking", children: [
2863
+ /* @__PURE__ */ jsxs(
2864
+ "button",
2865
+ {
2866
+ type: "button",
2867
+ className: "payman-v2-thinking-toggle",
2868
+ onClick: () => setOpen((o) => !o),
2869
+ "aria-expanded": open,
2870
+ children: [
2871
+ /* @__PURE__ */ jsx(
2872
+ ChevronRight,
2873
+ {
2874
+ className: cn(
2875
+ "payman-v2-thinking-chevron",
2876
+ open && "payman-v2-thinking-chevron-open"
2877
+ ),
2878
+ "aria-hidden": true
2879
+ }
2880
+ ),
2881
+ headerLabel
2882
+ ]
2883
+ }
2884
+ ),
2885
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-thinking-border", children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: open && /* @__PURE__ */ jsx(
2886
+ motion.div,
2887
+ {
2888
+ className: "payman-v2-thinking-content",
2889
+ initial: { height: 0, opacity: 0 },
2890
+ animate: { height: "auto", opacity: 1 },
2891
+ exit: { height: 0, opacity: 0 },
2892
+ transition: { duration: 0.2, ease: "easeInOut" },
2893
+ style: { overflow: "hidden" },
2894
+ children: /* @__PURE__ */ jsxs("div", { children: [
2895
+ parsed.map((item, i) => {
2896
+ if (item.type === "statement") {
2897
+ return /* @__PURE__ */ jsx(
2898
+ "div",
2899
+ {
2900
+ className: "payman-v2-thinking-statement",
2901
+ children: item.text
2902
+ },
2903
+ i
2904
+ );
2905
+ }
2906
+ if (item.type === "detail") {
2907
+ return /* @__PURE__ */ jsx(
2908
+ "div",
2909
+ {
2910
+ className: "payman-v2-thinking-detail",
2911
+ children: item.text
2912
+ },
2913
+ i
2914
+ );
2915
+ }
2916
+ return /* @__PURE__ */ jsx(
2917
+ "span",
2918
+ {
2919
+ className: cn(
2920
+ "payman-v2-thinking-status",
2921
+ item.variant === "success" ? "payman-v2-thinking-status-success" : "payman-v2-thinking-status-error"
2922
+ ),
2923
+ children: item.text
2924
+ },
2925
+ i
2926
+ );
2927
+ }),
2928
+ isStreaming && /* @__PURE__ */ jsxs(
2929
+ "div",
2930
+ {
2931
+ className: "payman-v2-thinking-cursor",
2932
+ "aria-live": "polite",
2933
+ children: [
2934
+ /* @__PURE__ */ jsx(PaymanMark, {}),
2935
+ /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
2936
+ motion.span,
2937
+ {
2938
+ className: "payman-v2-thinking-cursor-label payman-v2-thinking-shimmer",
2939
+ initial: { opacity: 0, y: 2 },
2940
+ animate: { opacity: 1, y: 0 },
2941
+ exit: { opacity: 0, y: -2 },
2942
+ transition: { duration: 0.24, ease: [0.4, 0, 0.2, 1] },
2943
+ children: cursorText
2944
+ },
2945
+ cursorKey
2946
+ ) })
2947
+ ]
2948
+ }
2949
+ )
2950
+ ] })
2951
+ },
2952
+ "thinking-content"
2953
+ ) }) })
2954
+ ] });
2955
+ }
2956
+ var THINKING_SPEED = {
2957
+ normal: [6, 8],
2958
+ fast: 1,
2959
+ punctuation: [20, 30],
2960
+ newline: [12, 18],
2961
+ idle: 30
2962
+ };
2963
+ var RESPONSE_SPEED = {
2964
+ normal: [4, 8],
2965
+ fast: 1,
2966
+ punctuation: [20, 30],
2967
+ newline: [10, 15],
2968
+ idle: 30
2969
+ };
2970
+ function charDelay(char, speed) {
2971
+ if (char === "*") return speed.fast;
2972
+ if (char === "\n") return speed.newline[0] + Math.random() * speed.newline[1];
2973
+ if (".!?,;:".includes(char))
2974
+ return speed.punctuation[0] + Math.random() * speed.punctuation[1];
2975
+ return speed.normal[0] + Math.random() * speed.normal[1];
2976
+ }
2977
+ function useTypingEffect(targetText, enabled, speed = RESPONSE_SPEED, initialDisplayedText) {
2978
+ const [displayedText, setDisplayedText] = useState("");
2979
+ const displayedRef = useRef("");
2980
+ const targetRef = useRef(targetText);
2981
+ const enabledRef = useRef(enabled);
2982
+ const initialDisplayedRef = useRef(initialDisplayedText);
2983
+ const timerRef = useRef(null);
2984
+ const runningRef = useRef(false);
2985
+ targetRef.current = targetText;
2986
+ enabledRef.current = enabled;
2987
+ initialDisplayedRef.current = initialDisplayedText;
2988
+ useEffect(() => {
2989
+ if (!enabled) {
2990
+ if (timerRef.current) {
2991
+ clearTimeout(timerRef.current);
2992
+ timerRef.current = null;
2993
+ }
2994
+ runningRef.current = false;
2995
+ displayedRef.current = targetText;
2996
+ setDisplayedText(targetText);
2997
+ return;
2998
+ }
2999
+ if (displayedRef.current.length === 0 && initialDisplayedRef.current && targetRef.current.startsWith(initialDisplayedRef.current)) {
3000
+ displayedRef.current = initialDisplayedRef.current;
3001
+ setDisplayedText(initialDisplayedRef.current);
3002
+ }
3003
+ if (runningRef.current) return;
3004
+ runningRef.current = true;
3005
+ const tick = () => {
3006
+ if (!enabledRef.current) {
3007
+ runningRef.current = false;
3008
+ return;
3009
+ }
3010
+ if (displayedRef.current.length < targetRef.current.length) {
3011
+ const nextChar = targetRef.current[displayedRef.current.length];
3012
+ displayedRef.current += nextChar;
3013
+ setDisplayedText(displayedRef.current);
3014
+ const delay = charDelay(nextChar, speed);
3015
+ timerRef.current = setTimeout(tick, delay);
3016
+ } else {
3017
+ timerRef.current = setTimeout(tick, speed.idle);
3018
+ }
3019
+ };
3020
+ tick();
3021
+ return () => {
3022
+ if (timerRef.current) {
3023
+ clearTimeout(timerRef.current);
3024
+ timerRef.current = null;
3025
+ }
3026
+ runningRef.current = false;
3027
+ };
3028
+ }, [enabled]);
3029
+ const isTyping = enabled && displayedRef.current.length < targetRef.current.length;
3030
+ return {
3031
+ displayedText: enabled ? displayedText : targetText,
3032
+ isTyping
3033
+ };
3034
+ }
3035
+ var INITIAL_THINKING_PLACEHOLDER = [
3036
+ "**Getting things ready**",
3037
+ "Putting things together"
3038
+ ].join("\n");
3039
+ function getFormattedThinking(message, includeInitialPlaceholder = false) {
3040
+ const plainThinkingText = message.allThinkingText || message.activeThinkingText || "";
3041
+ const baseText = message.formattedThinkingText || buildFormattedThinking(message.steps, plainThinkingText);
3042
+ if (includeInitialPlaceholder && baseText) {
3043
+ return INITIAL_THINKING_PLACEHOLDER + "\n" + baseText;
3044
+ }
3045
+ if (includeInitialPlaceholder) {
3046
+ return INITIAL_THINKING_PLACEHOLDER;
3047
+ }
3048
+ return baseText;
3049
+ }
3050
+ function AssistantMessageV2({
3051
+ message,
3052
+ onImageClick,
3053
+ onExecutionTraceClick,
3054
+ actions
3055
+ }) {
3056
+ const [copied, setCopied] = useState(false);
3057
+ const [toast, setToast] = useState(null);
3058
+ const copyResetTimerRef = useRef(null);
3059
+ const toastTimerRef = useRef(null);
3060
+ const showCopyAction = actions?.copy ?? true;
3061
+ const showTraceAction = (actions?.trace ?? true) && !!onExecutionTraceClick;
3062
+ const hasEverStreamed = useRef(!!message.isStreaming);
3063
+ const hasShownInitialThinking = useRef(
3064
+ message.streamProgress === "processing"
3065
+ );
3066
+ if (message.isStreaming) hasEverStreamed.current = true;
3067
+ useEffect(() => {
3068
+ return () => {
3069
+ if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
3070
+ if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
3071
+ };
3072
+ }, []);
3073
+ const rawResponseContent = (() => {
3074
+ const raw = message.isStreaming ? message.streamingContent || message.content : message.content;
3075
+ if (!raw) return "";
3076
+ return raw.replace(/\\n/g, "\n");
3077
+ })();
3078
+ const hasReadyStreamPhase = message.streamProgress === "processing" || Boolean(message.steps?.length) || Boolean(message.allThinkingText) || Boolean(message.activeThinkingText) || Boolean(rawResponseContent);
3079
+ if (hasReadyStreamPhase && !message.isError) {
3080
+ hasShownInitialThinking.current = true;
3081
+ }
3082
+ const includeInitialPlaceholder = hasShownInitialThinking.current && !message.isError;
3083
+ const rawThinkingContent = useMemo(
3084
+ () => getFormattedThinking(message, includeInitialPlaceholder),
3085
+ [message, includeInitialPlaceholder]
3086
+ );
3087
+ const isThinkingStreaming = !!message.isStreaming && !rawResponseContent && !message.isError;
3088
+ const { displayedText: thinkingContent } = useTypingEffect(
3089
+ rawThinkingContent,
3090
+ hasEverStreamed.current && isThinkingStreaming,
3091
+ THINKING_SPEED,
3092
+ includeInitialPlaceholder ? INITIAL_THINKING_PLACEHOLDER : void 0
3093
+ );
3094
+ const hasThinkingContent = Boolean(thinkingContent);
3095
+ const showThinkingBlock = hasThinkingContent || isThinkingStreaming;
3096
+ const showLegacyThinkingPhase = !!message.isStreaming && !message.isError && !rawResponseContent && message.streamProgress === "started";
3097
+ const responseTypingEnabled = hasEverStreamed.current && Boolean(rawResponseContent) && !message.isError;
3098
+ const { displayedText: displayContent, isTyping: isResponseTyping } = useTypingEffect(rawResponseContent, responseTypingEnabled, RESPONSE_SPEED);
3099
+ const resolvedErrorText = (() => {
3100
+ const conflictErrorMessage2 = getConflictErrorMessage(message.errorDetails);
3101
+ if (conflictErrorMessage2) {
3102
+ return conflictErrorMessage2;
3103
+ }
3104
+ if (isFriendlyWorkflowError(message.errorDetails) && !message.errorDetails) {
3105
+ return "Oops, something went wrong. Please try again.";
3106
+ }
3107
+ return message.errorDetails;
3108
+ })();
3109
+ const requestStartedAt = useMemo(() => {
3110
+ if (!message.timestamp) return void 0;
3111
+ const t = Date.parse(message.timestamp);
3112
+ return Number.isFinite(t) ? t : void 0;
3113
+ }, [message.timestamp]);
3114
+ const thinkingDuration = (() => {
3115
+ const steps = message.steps;
3116
+ if (!steps || steps.length === 0) return void 0;
3117
+ const last = steps[steps.length - 1];
3118
+ if (requestStartedAt && last.timestamp) {
3119
+ return Math.max(
3120
+ 0,
3121
+ Math.round((last.timestamp - requestStartedAt) / 1e3)
3122
+ );
3123
+ }
3124
+ const first = steps[0];
3125
+ if (first.timestamp && last.timestamp) {
3126
+ return Math.round((last.timestamp - first.timestamp) / 1e3);
3127
+ }
3128
+ const total = steps.reduce((sum, s) => sum + (s.elapsedMs || 0), 0);
3129
+ return total > 0 ? Math.round(total / 1e3) : void 0;
3130
+ })();
3131
+ const conflictErrorMessage = getConflictErrorMessage(message.errorDetails);
3132
+ const isConflictError = Boolean(conflictErrorMessage);
3133
+ if (isConflictError) {
3134
+ return /* @__PURE__ */ jsx("div", { className: "payman-v2-assistant-msg payman-v2-fade-in", children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-error", children: [
3135
+ /* @__PURE__ */ jsx(
3136
+ AlertCircle,
3137
+ {
3138
+ className: "payman-v2-assistant-msg-error-icon",
3139
+ style: { width: 16, height: 16 }
3140
+ }
3141
+ ),
3142
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-error-text", children: conflictErrorMessage }) })
3143
+ ] }) });
3144
+ }
3145
+ if (message.isError && !displayContent && !hasThinkingContent) {
3146
+ return /* @__PURE__ */ jsx("div", { className: "payman-v2-assistant-msg payman-v2-fade-in", children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-error", children: [
3147
+ /* @__PURE__ */ jsx(
3148
+ AlertCircle,
3149
+ {
3150
+ className: "payman-v2-assistant-msg-error-icon",
3151
+ style: { width: 16, height: 16 }
3152
+ }
3153
+ ),
3154
+ /* @__PURE__ */ jsx("div", { children: resolvedErrorText ? /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-error-text", children: resolvedErrorText }) : null })
3155
+ ] }) });
3156
+ }
3157
+ if (showLegacyThinkingPhase) {
3158
+ return /* @__PURE__ */ jsx("div", { className: "payman-v2-assistant-msg payman-v2-fade-in", children: /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-thinking-only payman-v2-thinking-shimmer", children: "Working on it\u2026" }) });
3159
+ }
3160
+ const showToast = (label, tone) => {
3161
+ if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
3162
+ setToast({ label, tone });
3163
+ toastTimerRef.current = setTimeout(() => setToast(null), 1800);
3164
+ };
3165
+ const handleCopy = async () => {
3166
+ try {
3167
+ if (!navigator.clipboard?.writeText) {
3168
+ throw new Error("Clipboard unavailable");
3169
+ }
3170
+ await navigator.clipboard.writeText(displayContent);
3171
+ if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
3172
+ setCopied(true);
3173
+ copyResetTimerRef.current = setTimeout(() => setCopied(false), 1800);
3174
+ showToast("Copied to clipboard", "success");
3175
+ } catch {
3176
+ setCopied(false);
3177
+ showToast("Could not copy", "error");
3178
+ }
3179
+ };
3180
+ const handleTrace = () => {
3181
+ onExecutionTraceClick?.({
3182
+ message,
3183
+ tracingData: message.tracingData,
3184
+ executionId: message.executionId
3185
+ });
3186
+ };
3187
+ const hasPartialError = message.isError && displayContent && !isConflictError;
3188
+ const isDone = !message.isStreaming && displayContent && !hasPartialError && !isResponseTyping;
3189
+ const hasVisibleDoneActions = showCopyAction || showTraceAction;
3190
+ const isCancelled = message.isCancelled;
3191
+ const toastPortal = typeof document !== "undefined" ? createPortal(
3192
+ /* @__PURE__ */ jsx(AnimatePresence, { children: toast && /* @__PURE__ */ jsx(
3193
+ motion.div,
3194
+ {
3195
+ initial: { opacity: 0, y: -18, scale: 0.96 },
3196
+ animate: { opacity: 1, y: 0, scale: 1 },
3197
+ exit: { opacity: 0, y: -12, scale: 0.96 },
3198
+ transition: {
3199
+ type: "spring",
3200
+ stiffness: 360,
3201
+ damping: 26,
3202
+ mass: 0.7
3203
+ },
3204
+ className: "payman-v2-toast",
3205
+ role: "status",
3206
+ "aria-live": "polite",
3207
+ children: /* @__PURE__ */ jsxs(
3208
+ "div",
3209
+ {
3210
+ className: cn(
3211
+ "payman-v2-toast-inner",
3212
+ toast.tone === "success" ? "payman-v2-toast-success" : "payman-v2-toast-error"
3213
+ ),
3214
+ children: [
3215
+ toast.tone === "success" ? /* @__PURE__ */ jsx(
3216
+ Check,
3217
+ {
3218
+ className: "h-4 w-4",
3219
+ style: { color: "#059669" }
3220
+ }
3221
+ ) : /* @__PURE__ */ jsx(
3222
+ AlertCircle,
3223
+ {
3224
+ className: "h-4 w-4",
3225
+ style: { color: "#ef4444" }
3226
+ }
3227
+ ),
3228
+ /* @__PURE__ */ jsx("span", { children: toast.label })
3229
+ ]
3230
+ }
3231
+ )
3232
+ }
3233
+ ) }),
3234
+ document.body
3235
+ ) : null;
3236
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3237
+ toastPortal,
3238
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg payman-v2-fade-in", children: [
3239
+ showThinkingBlock && /* @__PURE__ */ jsx(
3240
+ ThinkingBlockV2,
3241
+ {
3242
+ content: thinkingContent,
3243
+ isStreaming: isThinkingStreaming,
3244
+ durationSec: thinkingDuration,
3245
+ startedAt: requestStartedAt
3246
+ }
3247
+ ),
3248
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-assistant-msg-content-area", children: displayContent ? /* @__PURE__ */ jsx(
3249
+ MarkdownRendererV2,
3250
+ {
3251
+ content: displayContent,
3252
+ isStreaming: message.isStreaming && !isCancelled || isResponseTyping,
3253
+ isResolvingImages: message.isResolvingImages,
3254
+ onImageClick
3255
+ }
3256
+ ) : !isThinkingStreaming && !hasThinkingContent ? /* @__PURE__ */ jsx("span", { className: "payman-v2-assistant-msg-placeholder", children: "..." }) : null }),
3257
+ isCancelled && message.isStreaming && /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-paused", children: [
3258
+ /* @__PURE__ */ jsx(
3259
+ WifiOff,
3260
+ {
3261
+ style: { width: 14, height: 14, color: "rgba(217, 119, 6, 0.7)", flexShrink: 0 }
3262
+ }
3263
+ ),
3264
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-paused-text", children: "Connection slow - resuming\u2026" })
3265
+ ] }),
3266
+ hasPartialError && /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-partial-error", children: [
3267
+ /* @__PURE__ */ jsx(
3268
+ AlertCircle,
3269
+ {
3270
+ className: "payman-v2-assistant-msg-error-icon",
3271
+ style: { width: 16, height: 16 }
3272
+ }
3273
+ ),
3274
+ /* @__PURE__ */ jsx("div", { children: resolvedErrorText ? /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-error-text", children: resolvedErrorText }) : null })
3275
+ ] }),
3276
+ isDone && hasVisibleDoneActions && /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-actions", children: [
3277
+ showCopyAction && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Copy", children: /* @__PURE__ */ jsx(
3278
+ "button",
3279
+ {
3280
+ onClick: () => void handleCopy(),
3281
+ className: cn(
3282
+ "payman-v2-assistant-msg-action-btn",
3283
+ copied && "payman-v2-assistant-msg-action-btn-active"
3284
+ ),
3285
+ "aria-label": "Copy",
3286
+ children: copied ? /* @__PURE__ */ jsx(Check, { style: { width: 16, height: 16 } }) : /* @__PURE__ */ jsx(Copy, { style: { width: 16, height: 16 } })
3287
+ }
3288
+ ) }),
3289
+ showTraceAction && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Trace", children: /* @__PURE__ */ jsx(
3290
+ "button",
3291
+ {
3292
+ onClick: handleTrace,
3293
+ className: "payman-v2-assistant-msg-action-btn",
3294
+ "aria-label": "Trace response",
3295
+ children: /* @__PURE__ */ jsx(SearchCode, { style: { width: 16, height: 16 } })
3296
+ }
3297
+ ) })
3298
+ ] })
3299
+ ] })
3300
+ ] });
3301
+ }
3302
+ var DEFAULT_MAX_LENGTH2 = 6;
3303
+ var MAX_SUPPORTED_LENGTH2 = 12;
3304
+ var AUTO_FOCUS_DELAY_MS2 = 250;
3305
+ function OtpInputV2({
3306
+ value,
3307
+ onChange,
3308
+ maxLength,
3309
+ disabled = false,
3310
+ error = false
3311
+ }) {
3312
+ const inputRefs = useRef([]);
3313
+ const safeMaxLength = Number.isInteger(maxLength) && maxLength > 0 ? Math.min(maxLength, MAX_SUPPORTED_LENGTH2) : DEFAULT_MAX_LENGTH2;
3314
+ const digits = value.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
3315
+ useEffect(() => {
3316
+ if (disabled) return;
3317
+ const timer = window.setTimeout(() => {
3318
+ inputRefs.current[0]?.focus();
3319
+ }, AUTO_FOCUS_DELAY_MS2);
3320
+ return () => window.clearTimeout(timer);
3321
+ }, [disabled]);
3322
+ const focusInput = (index) => {
3323
+ if (index >= 0 && index < safeMaxLength) {
3324
+ inputRefs.current[index]?.focus();
3325
+ }
3326
+ };
3327
+ const updateValue = (newDigits) => {
3328
+ onChange(newDigits.join("").slice(0, safeMaxLength));
3329
+ };
3330
+ const handleChange = (index, char) => {
3331
+ if (char && !/^\d$/.test(char)) return;
3332
+ const newDigits = [...digits];
3333
+ newDigits[index] = char;
3334
+ updateValue(newDigits);
3335
+ if (char && index < safeMaxLength - 1) focusInput(index + 1);
3336
+ };
3337
+ const handleKeyDown = (index, e) => {
3338
+ if (e.key === "Enter") {
3339
+ e.preventDefault();
3340
+ return;
3341
+ }
3342
+ if (e.key === "Backspace") {
3343
+ e.preventDefault();
3344
+ if (digits[index]) {
3345
+ const newDigits = [...digits];
3346
+ newDigits[index] = "";
3347
+ updateValue(newDigits);
3348
+ } else if (index > 0) {
3349
+ const newDigits = [...digits];
3350
+ newDigits[index - 1] = "";
3351
+ updateValue(newDigits);
3352
+ focusInput(index - 1);
3353
+ }
3354
+ return;
3355
+ }
3356
+ if (e.key === "ArrowLeft") {
3357
+ e.preventDefault();
3358
+ focusInput(index - 1);
3359
+ } else if (e.key === "ArrowRight") {
3360
+ e.preventDefault();
3361
+ focusInput(index + 1);
3362
+ }
3363
+ };
3364
+ const handlePaste = (e) => {
3365
+ e.preventDefault();
3366
+ const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, safeMaxLength);
3367
+ if (!pasted) return;
3368
+ const newDigits = pasted.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
3369
+ updateValue(newDigits);
3370
+ focusInput(Math.min(pasted.length, safeMaxLength - 1));
3371
+ };
3372
+ return /* @__PURE__ */ jsx("div", { className: cn("payman-v2-otp", error && "payman-v2-shake"), children: digits.map((digit, i) => /* @__PURE__ */ jsx(
3373
+ "input",
3374
+ {
3375
+ ref: (el) => {
3376
+ inputRefs.current[i] = el;
3377
+ },
3378
+ type: "text",
3379
+ inputMode: "numeric",
3380
+ maxLength: 1,
3381
+ value: digit,
3382
+ disabled,
3383
+ onChange: (e) => handleChange(i, e.target.value.slice(-1)),
3384
+ onKeyDown: (e) => handleKeyDown(i, e),
3385
+ onPaste: handlePaste,
3386
+ onFocus: (e) => e.target.select(),
3387
+ "aria-label": `Digit ${i + 1}`,
3388
+ className: cn(
3389
+ "payman-v2-otp-digit",
3390
+ digit && "payman-v2-otp-digit-filled",
3391
+ error && "payman-v2-otp-digit-error"
3392
+ )
3393
+ },
3394
+ i
3395
+ )) });
3396
+ }
3397
+ var RESEND_COOLDOWN_S = 30;
3398
+ var OTP_LEN = 6;
3399
+ function VerificationCardV2({
3400
+ messageId,
3401
+ action,
3402
+ status,
3403
+ onApprove,
3404
+ onReject,
3405
+ onResend
3406
+ }) {
3407
+ const [otp, setOtp] = useState("");
3408
+ const [otpErrored, setOtpErrored] = useState(false);
3409
+ const [resendSec, setResendSec] = useState(0);
3410
+ const lastSubmittedRef = useRef(null);
3411
+ const resendTimerRef = useRef(void 0);
3412
+ useEffect(() => {
3413
+ if (status !== "error") {
3414
+ setOtpErrored(false);
3415
+ return;
3416
+ }
3417
+ setOtpErrored(true);
3418
+ const t = window.setTimeout(() => {
3419
+ setOtp("");
3420
+ setOtpErrored(false);
3421
+ lastSubmittedRef.current = null;
3422
+ }, 600);
3423
+ return () => window.clearTimeout(t);
3424
+ }, [status]);
3425
+ useEffect(() => {
3426
+ if (otp.length < OTP_LEN) {
3427
+ lastSubmittedRef.current = null;
3428
+ }
3429
+ }, [otp]);
3430
+ useEffect(() => {
3431
+ if (otp.length !== OTP_LEN || !/^\d+$/.test(otp) || status !== "pending") {
3432
+ return;
3433
+ }
3434
+ if (lastSubmittedRef.current === otp) return;
3435
+ lastSubmittedRef.current = otp;
3436
+ void onApprove(messageId, otp);
3437
+ }, [messageId, onApprove, otp, status]);
3438
+ useEffect(() => {
3439
+ return () => {
3440
+ if (typeof resendTimerRef.current === "number") {
3441
+ window.clearInterval(resendTimerRef.current);
3442
+ }
3443
+ };
3444
+ }, []);
3445
+ const startResendCooldown = useCallback(() => {
3446
+ setResendSec(RESEND_COOLDOWN_S);
3447
+ if (typeof resendTimerRef.current === "number") {
3448
+ window.clearInterval(resendTimerRef.current);
3449
+ }
3450
+ resendTimerRef.current = window.setInterval(() => {
3451
+ setResendSec((s) => {
3452
+ if (s <= 1) {
3453
+ if (typeof resendTimerRef.current === "number") {
3454
+ window.clearInterval(resendTimerRef.current);
3455
+ resendTimerRef.current = void 0;
3456
+ }
3457
+ return 0;
3458
+ }
3459
+ return s - 1;
3460
+ });
3461
+ }, 1e3);
3462
+ }, []);
3463
+ const handleResend = useCallback(async () => {
3464
+ if (resendSec > 0 || status === "verifying") return;
3465
+ await onResend(messageId);
3466
+ startResendCooldown();
3467
+ }, [messageId, onResend, resendSec, startResendCooldown, status]);
3468
+ const handleCancel = useCallback(async () => {
3469
+ await onReject(messageId);
3470
+ }, [messageId, onReject]);
3471
+ useCallback(async () => {
3472
+ if (otp.length !== OTP_LEN || !/^\d+$/.test(otp) || status !== "pending") {
3473
+ return;
3474
+ }
3475
+ if (lastSubmittedRef.current === otp) return;
3476
+ lastSubmittedRef.current = otp;
3477
+ await onApprove(messageId, otp);
3478
+ }, [messageId, onApprove, otp, status]);
3479
+ const busy = status === "verifying";
3480
+ status === "pending" && otp.length === OTP_LEN && /^\d+$/.test(otp);
3481
+ if (status === "approved" || status === "rejected") {
3482
+ return null;
3483
+ }
3484
+ return /* @__PURE__ */ jsxs(
3485
+ motion.div,
3486
+ {
3487
+ className: "payman-v2-verification",
3488
+ initial: { opacity: 0, y: 10 },
3489
+ animate: { opacity: 1, y: 0 },
3490
+ transition: { type: "spring", stiffness: 320, damping: 28 },
3491
+ children: [
3492
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-card", children: [
3493
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-header", children: [
3494
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-header-row", children: [
3495
+ /* @__PURE__ */ jsx(
3496
+ ShieldCheck,
3497
+ {
3498
+ className: "payman-v2-verification-icon",
3499
+ size: 18,
3500
+ strokeWidth: 1.75,
3501
+ "aria-hidden": true
3502
+ }
3503
+ ),
3504
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-verification-title", children: "Verify" }),
3505
+ action.amount != null ? /* @__PURE__ */ jsx("span", { className: "payman-v2-verification-amount", children: action.amount }) : action.payeeName ? /* @__PURE__ */ jsx("span", { className: "payman-v2-verification-payee", children: action.payeeName }) : null
3506
+ ] }),
3507
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-verification-description", children: "Enter the 6-digit code sent to your phone" }),
3508
+ /* @__PURE__ */ jsx(
3509
+ OtpInputV2,
3510
+ {
3511
+ value: otp,
3512
+ onChange: setOtp,
3513
+ maxLength: OTP_LEN,
3514
+ disabled: busy,
3515
+ error: otpErrored
3516
+ }
3517
+ ),
3518
+ busy ? /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-submitting", children: [
3519
+ /* @__PURE__ */ jsx(
3520
+ motion.span,
3521
+ {
3522
+ "aria-hidden": true,
3523
+ style: { display: "inline-flex" },
3524
+ animate: { rotate: 360 },
3525
+ transition: {
3526
+ repeat: Infinity,
3527
+ duration: 0.7,
3528
+ ease: "linear"
3529
+ },
3530
+ children: /* @__PURE__ */ jsx(Loader2, { size: 14, strokeWidth: 2 })
3531
+ }
3532
+ ),
3533
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-verification-submitting-text", children: "Verifying..." })
3534
+ ] }) : null
3535
+ ] }),
3536
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-verification-actions", children: /* @__PURE__ */ jsx(
3537
+ "button",
3538
+ {
3539
+ type: "button",
3540
+ className: "payman-v2-verification-cancel-btn",
3541
+ disabled: busy,
3542
+ onClick: () => void handleCancel(),
3543
+ children: "Cancel"
3544
+ }
3545
+ ) })
3546
+ ] }),
3547
+ /* @__PURE__ */ jsx(
3548
+ "button",
3549
+ {
3550
+ type: "button",
3551
+ className: "payman-v2-verification-resend-link",
3552
+ disabled: busy || resendSec > 0,
3553
+ onClick: () => void handleResend(),
3554
+ children: resendSec > 0 ? `Resend (${resendSec}s)` : "Resend"
3555
+ }
3556
+ )
3557
+ ]
3558
+ }
3559
+ );
3560
+ }
3561
+ var SCROLL_THRESHOLD2 = 100;
3562
+ var MessageListV2 = forwardRef(
3563
+ function MessageListV22({
3564
+ messages,
3565
+ isStreaming: _isStreaming = false,
3566
+ onEditUserMessage,
3567
+ onRetryUserMessage,
3568
+ onImageClick,
3569
+ onExecutionTraceClick,
3570
+ messageActions,
3571
+ retryDisabled = false,
3572
+ userAction,
3573
+ onApproveAction,
3574
+ onRejectAction,
3575
+ onResendAction
3576
+ }, ref) {
3577
+ const scrollRef = useRef(null);
3578
+ const scrollInnerRef = useRef(null);
3579
+ const isNearBottomRef = useRef(true);
3580
+ const [showScrollBtn, setShowScrollBtn] = useState(false);
3581
+ const prevCountRef = useRef(messages.length);
3582
+ const pauseStickUntilUserMessageRef = useRef(false);
3583
+ const followingBottomRef = useRef(true);
3584
+ const isProgrammaticScrollRef = useRef(false);
3585
+ const getDistanceFromBottom = useCallback(() => {
3586
+ const el = scrollRef.current;
3587
+ if (!el) return 0;
3588
+ return el.scrollHeight - el.scrollTop - el.clientHeight;
3589
+ }, []);
3590
+ const scrollToBottom = useCallback(
3591
+ (behavior = "smooth") => {
3592
+ const el = scrollRef.current;
3593
+ if (!el) return;
3594
+ isProgrammaticScrollRef.current = true;
3595
+ pauseStickUntilUserMessageRef.current = false;
3596
+ followingBottomRef.current = true;
3597
+ el.scrollTo({ top: el.scrollHeight, behavior });
3598
+ const clear = () => {
3599
+ isProgrammaticScrollRef.current = false;
3600
+ };
3601
+ if (behavior === "instant") {
3602
+ requestAnimationFrame(clear);
3603
+ } else {
3604
+ setTimeout(clear, 400);
3605
+ }
3606
+ },
3607
+ []
3608
+ );
3609
+ useImperativeHandle(
3610
+ ref,
3611
+ () => ({
3612
+ scrollToBottom: (behavior = "smooth") => {
3613
+ isNearBottomRef.current = true;
3614
+ pauseStickUntilUserMessageRef.current = false;
3615
+ followingBottomRef.current = true;
3616
+ setShowScrollBtn(false);
3617
+ scrollToBottom(behavior);
3618
+ }
3619
+ }),
3620
+ [scrollToBottom]
3621
+ );
3622
+ const handleScroll = useCallback(() => {
3623
+ const distance = getDistanceFromBottom();
3624
+ const nearBottom = distance <= SCROLL_THRESHOLD2;
3625
+ isNearBottomRef.current = nearBottom;
3626
+ setShowScrollBtn(!nearBottom);
3627
+ if (isProgrammaticScrollRef.current) return;
3628
+ if (!nearBottom) {
3629
+ followingBottomRef.current = false;
3630
+ pauseStickUntilUserMessageRef.current = true;
3631
+ }
3632
+ }, [getDistanceFromBottom]);
3633
+ useEffect(() => {
3634
+ const prevCount = prevCountRef.current;
3635
+ prevCountRef.current = messages.length;
3636
+ if (messages.length > prevCount) {
3637
+ const last = messages[messages.length - 1];
3638
+ if (last?.role === "user") {
3639
+ pauseStickUntilUserMessageRef.current = false;
3640
+ followingBottomRef.current = true;
3641
+ requestAnimationFrame(() => scrollToBottom());
3642
+ } else if (!pauseStickUntilUserMessageRef.current && followingBottomRef.current) {
3643
+ requestAnimationFrame(() => scrollToBottom("instant"));
3644
+ }
3645
+ }
3646
+ }, [messages.length, scrollToBottom]);
3647
+ useEffect(() => {
3648
+ const lastMsg = messages[messages.length - 1];
3649
+ if (!lastMsg?.isStreaming) return;
3650
+ if (pauseStickUntilUserMessageRef.current) return;
3651
+ if (!followingBottomRef.current) return;
3652
+ const el = scrollRef.current;
3653
+ if (!el) return;
3654
+ isProgrammaticScrollRef.current = true;
3655
+ el.scrollTop = el.scrollHeight;
3656
+ requestAnimationFrame(() => {
3657
+ isProgrammaticScrollRef.current = false;
3658
+ });
3659
+ });
3660
+ useEffect(() => {
3661
+ const inner = scrollInnerRef.current;
3662
+ if (!inner) return;
3663
+ const pinIfFollowing = () => {
3664
+ if (pauseStickUntilUserMessageRef.current) return;
3665
+ if (!followingBottomRef.current) return;
3666
+ const el = scrollRef.current;
3667
+ if (!el) return;
3668
+ isProgrammaticScrollRef.current = true;
3669
+ el.scrollTop = el.scrollHeight;
3670
+ requestAnimationFrame(() => {
3671
+ isProgrammaticScrollRef.current = false;
3672
+ });
3673
+ };
3674
+ const ro = new ResizeObserver(() => {
3675
+ pinIfFollowing();
3676
+ });
3677
+ ro.observe(inner);
3678
+ return () => ro.disconnect();
3679
+ }, []);
3680
+ useEffect(() => {
3681
+ if (messages.length > 0) {
3682
+ setTimeout(() => scrollToBottom("instant"), 50);
3683
+ }
3684
+ }, []);
3685
+ return /* @__PURE__ */ jsxs("div", { className: "payman-v2-message-list", children: [
3686
+ /* @__PURE__ */ jsx(
3687
+ "div",
3688
+ {
3689
+ ref: scrollRef,
3690
+ onScroll: handleScroll,
3691
+ className: "payman-v2-message-scroll payman-v2-scrollbar",
3692
+ children: /* @__PURE__ */ jsxs(
3693
+ "div",
3694
+ {
3695
+ ref: scrollInnerRef,
3696
+ className: "payman-v2-message-scroll-inner",
3697
+ children: [
3698
+ messages.map((message) => /* @__PURE__ */ jsx("div", { children: message.role === "user" ? /* @__PURE__ */ jsx(
3699
+ UserMessageV2,
3700
+ {
3701
+ message,
3702
+ onEdit: onEditUserMessage,
3703
+ onRetry: onRetryUserMessage,
3704
+ retryDisabled,
3705
+ actions: messageActions?.userMessageActions
3706
+ }
3707
+ ) : /* @__PURE__ */ jsx(
3708
+ AssistantMessageV2,
3709
+ {
3710
+ message,
3711
+ onImageClick,
3712
+ onExecutionTraceClick,
3713
+ actions: messageActions?.assistantMessageActions
3714
+ }
3715
+ ) }, message.id)),
3716
+ userAction && userAction.status !== "approved" && userAction.status !== "rejected" && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
3717
+ VerificationCardV2,
3718
+ {
3719
+ messageId: userAction.messageId,
3720
+ action: userAction.action,
3721
+ status: userAction.status,
3722
+ onApprove: onApproveAction ?? (async () => {
3723
+ }),
3724
+ onReject: onRejectAction ?? (async () => {
3725
+ }),
3726
+ onResend: onResendAction ?? (async () => {
3727
+ })
3728
+ }
3729
+ ) })
3730
+ ]
3731
+ }
3732
+ )
3733
+ }
3734
+ ),
3735
+ /* @__PURE__ */ jsx(AnimatePresence, { children: showScrollBtn && /* @__PURE__ */ jsx(
3736
+ motion.div,
3737
+ {
3738
+ initial: { opacity: 0, y: 6 },
3739
+ animate: { opacity: 1, y: 0 },
3740
+ exit: { opacity: 0, y: 6 },
3741
+ transition: { duration: 0.12 },
3742
+ className: "payman-v2-scroll-to-bottom",
3743
+ children: /* @__PURE__ */ jsx(
3744
+ "button",
3745
+ {
3746
+ onClick: () => {
3747
+ scrollToBottom();
3748
+ },
3749
+ className: "payman-v2-scroll-to-bottom-btn",
3750
+ "aria-label": "Scroll to bottom",
3751
+ children: /* @__PURE__ */ jsx(ArrowDown, { style: { width: 16, height: 16 } })
3752
+ }
3753
+ )
3754
+ }
3755
+ ) })
3756
+ ] });
3757
+ }
3758
+ );
3759
+ var ChatInputV2 = forwardRef(
3760
+ function ChatInputV22({
3761
+ onSend,
3762
+ onCancel,
3763
+ disabled = false,
3764
+ isStreaming = false,
3765
+ placeholder = "Reply...",
3766
+ enableVoice = false,
3767
+ voiceAvailable = false,
3768
+ isRecording = false,
3769
+ onVoicePress,
3770
+ transcribedText = "",
3771
+ showResetSession = false,
3772
+ onResetSession,
3773
+ showAttachmentButton = true,
3774
+ showUploadImageButton = true,
3775
+ showAttachFileButton = true,
3776
+ onUploadImageClick,
3777
+ onAttachFileClick,
3778
+ editingMessageId = null,
3779
+ onClearEditing,
3780
+ hideSendButton = false
3781
+ }, ref) {
3782
+ const [value, setValue] = useState("");
3783
+ const [isFocused, setIsFocused] = useState(false);
3784
+ const [showActions, setShowActions] = useState(false);
3785
+ const [showVoiceTooltip, setShowVoiceTooltip] = useState(false);
3786
+ const textareaRef = useRef(null);
3787
+ const actionsRef = useRef(null);
3788
+ const preRecordTextRef = useRef("");
3789
+ const voiceTooltipTimerRef = useRef(
3790
+ null
3791
+ );
3792
+ const voiceDraftSyncActiveRef = useRef(false);
3793
+ const isInputLocked = disabled || isRecording;
3794
+ const hasAttachmentOptions = showUploadImageButton || showAttachFileButton;
3795
+ const showAttachmentMenuButton = showAttachmentButton && hasAttachmentOptions;
3796
+ const showVoiceButton = enableVoice && onVoicePress != null;
3797
+ const isVoiceButtonDisabled = disabled || !voiceAvailable;
3798
+ useEffect(() => {
3799
+ if (textareaRef.current) {
3800
+ textareaRef.current.style.height = "auto";
3801
+ const scrollHeight = textareaRef.current.scrollHeight;
3802
+ textareaRef.current.style.height = `${Math.min(scrollHeight, 200)}px`;
3803
+ }
3804
+ }, [value]);
3805
+ useEffect(() => {
3806
+ if (disabled) {
3807
+ setIsFocused(false);
3808
+ setShowActions(false);
3809
+ textareaRef.current?.blur();
3810
+ return;
3811
+ }
3812
+ const frameId = requestAnimationFrame(() => textareaRef.current?.focus());
3813
+ return () => cancelAnimationFrame(frameId);
3814
+ }, [disabled]);
3815
+ useImperativeHandle(
3816
+ ref,
3817
+ () => ({
3818
+ setDraft: (message) => {
3819
+ setShowActions(false);
3820
+ setValue(message);
3821
+ requestAnimationFrame(() => {
3822
+ const textarea = textareaRef.current;
3823
+ if (!textarea || disabled) return;
3824
+ textarea.focus();
3825
+ const end = message.length;
3826
+ textarea.setSelectionRange(end, end);
3827
+ });
3828
+ }
3829
+ }),
3830
+ [disabled]
3831
+ );
3832
+ useEffect(() => {
3833
+ if (!showActions) return;
3834
+ const handleClickOutside = (e) => {
3835
+ if (actionsRef.current && !actionsRef.current.contains(e.target)) {
3836
+ setShowActions(false);
3837
+ }
3838
+ };
3839
+ document.addEventListener("mousedown", handleClickOutside);
3840
+ return () => document.removeEventListener("mousedown", handleClickOutside);
3841
+ }, [showActions]);
3842
+ useEffect(() => {
3843
+ if (!showAttachmentMenuButton) {
3844
+ setShowActions(false);
3845
+ }
3846
+ }, [showAttachmentMenuButton]);
3847
+ useEffect(() => {
3848
+ return () => {
3849
+ if (voiceTooltipTimerRef.current) {
3850
+ clearTimeout(voiceTooltipTimerRef.current);
3851
+ }
3852
+ };
3853
+ }, []);
3854
+ useEffect(() => {
3855
+ if (!voiceDraftSyncActiveRef.current) return;
3856
+ const base = preRecordTextRef.current;
3857
+ const separator = base && !base.endsWith(" ") && transcribedText ? " " : "";
3858
+ setValue(`${base}${separator}${transcribedText}`);
3859
+ }, [isRecording, transcribedText]);
3860
+ const handleSend = useCallback(() => {
3861
+ if (!value.trim() || disabled) return;
3862
+ voiceDraftSyncActiveRef.current = false;
3863
+ preRecordTextRef.current = "";
3864
+ onClearEditing?.();
3865
+ onSend(value.trim());
3866
+ setValue("");
3867
+ requestAnimationFrame(() => {
3868
+ if (textareaRef.current) {
3869
+ textareaRef.current.style.height = "auto";
3870
+ textareaRef.current.focus();
3871
+ }
3872
+ });
3873
+ }, [value, disabled, onClearEditing, onSend]);
3874
+ const handleKeyDown = (e) => {
3875
+ if (e.key === "Enter" && !e.shiftKey) {
3876
+ e.preventDefault();
3877
+ if (isStreaming || hideSendButton) return;
3878
+ handleSend();
3879
+ }
3880
+ };
3881
+ const handleUploadImageClick = () => {
3882
+ onUploadImageClick?.();
3883
+ setShowActions(false);
3884
+ };
3885
+ const handleAttachFileClick = () => {
3886
+ onAttachFileClick?.();
3887
+ setShowActions(false);
3888
+ };
3889
+ const hideVoiceTooltip = useCallback(() => {
3890
+ if (voiceTooltipTimerRef.current) {
3891
+ clearTimeout(voiceTooltipTimerRef.current);
3892
+ voiceTooltipTimerRef.current = null;
3893
+ }
3894
+ setShowVoiceTooltip(false);
3895
+ }, []);
3896
+ const startVoiceTooltipTimer = useCallback(() => {
3897
+ if (isVoiceButtonDisabled || isRecording) return;
3898
+ if (voiceTooltipTimerRef.current) {
3899
+ clearTimeout(voiceTooltipTimerRef.current);
3900
+ }
3901
+ voiceTooltipTimerRef.current = setTimeout(() => {
3902
+ setShowVoiceTooltip(true);
3903
+ voiceTooltipTimerRef.current = null;
3904
+ }, 2e3);
3905
+ }, [isRecording, isVoiceButtonDisabled]);
3906
+ const handleVoiceToggle = () => {
3907
+ hideVoiceTooltip();
3908
+ setShowActions(false);
3909
+ if (!onVoicePress || isVoiceButtonDisabled) return;
3910
+ if (!isRecording) {
3911
+ preRecordTextRef.current = value;
3912
+ voiceDraftSyncActiveRef.current = true;
3913
+ }
3914
+ onVoicePress();
3915
+ };
3916
+ const canSend = value.trim().length > 0 && !disabled;
3917
+ const sendDisabled = !canSend || isStreaming;
3918
+ return /* @__PURE__ */ jsxs("div", { className: "payman-v2-input-container", children: [
3919
+ /* @__PURE__ */ jsxs(
3920
+ "div",
3921
+ {
3922
+ className: cn(
3923
+ "payman-v2-input-wrapper",
3924
+ (isFocused || isRecording) && "payman-v2-input-wrapper-focused"
3925
+ ),
3926
+ children: [
3927
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-input-body", children: [
3928
+ /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: editingMessageId && /* @__PURE__ */ jsxs(
3929
+ motion.div,
3930
+ {
3931
+ initial: { opacity: 0, y: -4 },
3932
+ animate: { opacity: 1, y: 0 },
3933
+ exit: { opacity: 0, y: -4 },
3934
+ transition: { duration: 0.14, ease: "easeOut" },
3935
+ className: "payman-v2-input-editing-banner",
3936
+ children: [
3937
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-input-editing-banner-info", children: [
3938
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-input-editing-icon-wrap", children: /* @__PURE__ */ jsx(Pencil, { style: { width: 12, height: 12 } }) }),
3939
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-input-editing-label", children: "Editing message" })
3940
+ ] }),
3941
+ onClearEditing && /* @__PURE__ */ jsx(
3942
+ "button",
3943
+ {
3944
+ type: "button",
3945
+ onClick: onClearEditing,
3946
+ className: "payman-v2-input-editing-close",
3947
+ "aria-label": "Stop editing message",
3948
+ children: /* @__PURE__ */ jsx(X, { style: { width: 14, height: 14 } })
3949
+ }
3950
+ )
3951
+ ]
3952
+ }
3953
+ ) }),
3954
+ /* @__PURE__ */ jsx(
3955
+ "textarea",
3956
+ {
3957
+ ref: textareaRef,
3958
+ value,
3959
+ onChange: (e) => {
3960
+ if (isRecording) return;
3961
+ const nextValue = e.target.value;
3962
+ voiceDraftSyncActiveRef.current = false;
3963
+ setValue(nextValue);
3964
+ if (editingMessageId && nextValue.length === 0) {
3965
+ onClearEditing?.();
3966
+ }
3967
+ },
3968
+ onKeyDown: handleKeyDown,
3969
+ onFocus: () => {
3970
+ if (!disabled) setIsFocused(true);
3971
+ },
3972
+ onBlur: () => setIsFocused(false),
3973
+ onMouseDown: (e) => {
3974
+ if (disabled) e.preventDefault();
3975
+ },
3976
+ "aria-disabled": disabled,
3977
+ readOnly: isInputLocked,
3978
+ tabIndex: disabled ? -1 : 0,
3979
+ placeholder: isRecording ? "Listening\u2026" : placeholder,
3980
+ className: "payman-v2-input-textarea",
3981
+ "data-disabled": disabled ? "true" : "false",
3982
+ rows: 1
3983
+ }
3984
+ )
3985
+ ] }),
3986
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-input-controls", children: [
3987
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-input-controls-left", children: [
3988
+ showResetSession && onResetSession && /* @__PURE__ */ jsxs(
3989
+ "button",
3990
+ {
3991
+ type: "button",
3992
+ onClick: onResetSession,
3993
+ disabled: isStreaming || isRecording,
3994
+ className: "payman-v2-input-new-session-btn",
3995
+ "aria-label": "New Session",
3996
+ title: "New Session",
3997
+ children: [
3998
+ /* @__PURE__ */ jsx(
3999
+ RotateCcw,
4000
+ {
4001
+ style: { width: 16, height: 16, strokeWidth: 2.25 }
4002
+ }
4003
+ ),
4004
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-input-new-session-tooltip", children: "New Session" })
4005
+ ]
4006
+ }
4007
+ ),
4008
+ showAttachmentMenuButton && /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, ref: actionsRef, children: [
4009
+ /* @__PURE__ */ jsx(
4010
+ "button",
4011
+ {
4012
+ type: "button",
4013
+ onClick: () => setShowActions((current) => !current),
4014
+ disabled: disabled || isRecording,
4015
+ className: cn(
4016
+ "payman-v2-input-attach-btn",
4017
+ showActions && "payman-v2-input-attach-btn-active"
4018
+ ),
4019
+ "aria-label": "Attach",
4020
+ children: /* @__PURE__ */ jsx(
4021
+ Plus,
4022
+ {
4023
+ style: { width: 20, height: 20, strokeWidth: 2 }
4024
+ }
4025
+ )
4026
+ }
4027
+ ),
4028
+ /* @__PURE__ */ jsx(AnimatePresence, { children: showActions && /* @__PURE__ */ jsxs(
4029
+ motion.div,
4030
+ {
4031
+ initial: { opacity: 0, y: 4, scale: 0.95 },
4032
+ animate: { opacity: 1, y: 0, scale: 1 },
4033
+ exit: { opacity: 0, y: 4, scale: 0.95 },
4034
+ transition: { duration: 0.12 },
4035
+ className: "payman-v2-input-attach-menu",
4036
+ children: [
4037
+ showUploadImageButton && /* @__PURE__ */ jsxs(
4038
+ "button",
4039
+ {
4040
+ type: "button",
4041
+ className: "payman-v2-input-attach-option",
4042
+ onClick: handleUploadImageClick,
4043
+ children: [
4044
+ /* @__PURE__ */ jsx(
4045
+ ImagePlus,
4046
+ {
4047
+ style: { width: 16, height: 16 },
4048
+ className: "payman-v2-input-attach-option-icon"
4049
+ }
4050
+ ),
4051
+ "Upload image"
4052
+ ]
4053
+ }
4054
+ ),
4055
+ showAttachFileButton && /* @__PURE__ */ jsxs(
4056
+ "button",
4057
+ {
4058
+ type: "button",
4059
+ className: "payman-v2-input-attach-option",
4060
+ onClick: handleAttachFileClick,
4061
+ children: [
4062
+ /* @__PURE__ */ jsx(
4063
+ Paperclip,
4064
+ {
4065
+ style: { width: 16, height: 16 },
4066
+ className: "payman-v2-input-attach-option-icon"
4067
+ }
4068
+ ),
4069
+ "Attach file"
4070
+ ]
4071
+ }
4072
+ )
4073
+ ]
4074
+ }
4075
+ ) })
4076
+ ] }),
4077
+ showVoiceButton && /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
4078
+ /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: showVoiceTooltip && /* @__PURE__ */ jsx(
4079
+ motion.div,
4080
+ {
4081
+ initial: { opacity: 0, y: 4, scale: 0.98 },
4082
+ animate: { opacity: 1, y: 0, scale: 1 },
4083
+ exit: { opacity: 0, y: 4, scale: 0.98 },
4084
+ transition: { duration: 0.14, ease: "easeOut" },
4085
+ className: "payman-v2-input-voice-tooltip",
4086
+ children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-input-voice-tooltip-content", children: [
4087
+ "Chat with your voice",
4088
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-input-voice-tooltip-arrow" })
4089
+ ] })
4090
+ }
4091
+ ) }),
4092
+ /* @__PURE__ */ jsxs(
4093
+ "button",
4094
+ {
4095
+ type: "button",
4096
+ onClick: handleVoiceToggle,
4097
+ onMouseEnter: startVoiceTooltipTimer,
4098
+ onMouseLeave: hideVoiceTooltip,
4099
+ onFocus: startVoiceTooltipTimer,
4100
+ onBlur: hideVoiceTooltip,
4101
+ disabled: isVoiceButtonDisabled,
4102
+ className: cn(
4103
+ "payman-v2-input-mic-btn",
4104
+ isRecording && "payman-v2-input-mic-recording"
4105
+ ),
4106
+ "aria-label": isRecording ? "Stop recording" : "Voice input",
4107
+ children: [
4108
+ /* @__PURE__ */ jsx(Mic, { style: { width: 18, height: 18 } }),
4109
+ isRecording && /* @__PURE__ */ jsx("span", { className: "payman-v2-input-mic-indicator" })
4110
+ ]
4111
+ }
4112
+ )
4113
+ ] })
4114
+ ] }),
4115
+ !hideSendButton && /* @__PURE__ */ jsx("div", { className: "payman-v2-input-controls-right", children: /* @__PURE__ */ jsx(
4116
+ "button",
4117
+ {
4118
+ type: "button",
4119
+ onClick: handleSend,
4120
+ disabled: sendDisabled,
4121
+ className: cn(
4122
+ "payman-v2-input-send-btn",
4123
+ sendDisabled && "payman-v2-input-send-btn-disabled"
4124
+ ),
4125
+ "aria-label": "Send message",
4126
+ children: /* @__PURE__ */ jsx(
4127
+ ArrowUp,
4128
+ {
4129
+ style: { width: 16, height: 16, strokeWidth: 2.5 },
4130
+ className: "payman-v2-input-send-icon"
4131
+ }
4132
+ )
4133
+ }
4134
+ ) })
4135
+ ] })
4136
+ ]
4137
+ }
4138
+ ),
4139
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-input-disclaimer", children: "AI can make mistakes. Please double-check responses." })
4140
+ ] });
4141
+ }
4142
+ );
4143
+ function ImageLightboxV2({ src, alt, onClose }) {
4144
+ const [isMounted, setIsMounted] = useState(false);
4145
+ const [isImageLoaded, setIsImageLoaded] = useState(false);
4146
+ useEffect(() => {
4147
+ setIsMounted(true);
4148
+ return () => setIsMounted(false);
4149
+ }, []);
4150
+ useEffect(() => {
4151
+ setIsImageLoaded(false);
4152
+ }, [src]);
4153
+ const handleKeyDown = useCallback(
4154
+ (e) => {
4155
+ if (e.key === "Escape") onClose();
4156
+ },
4157
+ [onClose]
4158
+ );
4159
+ useEffect(() => {
4160
+ if (!src || typeof document === "undefined") return;
4161
+ document.addEventListener("keydown", handleKeyDown);
4162
+ const previousOverflow = document.body.style.overflow;
4163
+ document.body.style.overflow = "hidden";
4164
+ return () => {
4165
+ document.removeEventListener("keydown", handleKeyDown);
4166
+ document.body.style.overflow = previousOverflow;
4167
+ };
4168
+ }, [src, handleKeyDown]);
4169
+ const handleDownload = () => {
4170
+ if (!src || typeof document === "undefined") return;
4171
+ const a = document.createElement("a");
4172
+ a.href = src;
4173
+ a.download = alt.trim() ? alt : "image";
4174
+ document.body.appendChild(a);
4175
+ a.click();
4176
+ a.remove();
4177
+ };
4178
+ if (!isMounted || typeof document === "undefined") {
4179
+ return null;
4180
+ }
4181
+ return createPortal(
4182
+ /* @__PURE__ */ jsx(AnimatePresence, { children: src ? /* @__PURE__ */ jsxs(
4183
+ motion.div,
4184
+ {
4185
+ className: "payman-v2-lightbox",
4186
+ initial: { opacity: 0 },
4187
+ animate: { opacity: 1 },
4188
+ exit: { opacity: 0 },
4189
+ transition: { duration: 0.18 },
4190
+ onClick: onClose,
4191
+ role: "presentation",
4192
+ children: [
4193
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-lightbox-controls", children: [
4194
+ /* @__PURE__ */ jsx(
4195
+ "button",
4196
+ {
4197
+ type: "button",
4198
+ className: "payman-v2-lightbox-btn",
4199
+ "aria-label": "Download",
4200
+ onClick: (e) => {
4201
+ e.stopPropagation();
4202
+ handleDownload();
4203
+ },
4204
+ children: /* @__PURE__ */ jsx(Download, { size: 20, strokeWidth: 2 })
4205
+ }
4206
+ ),
4207
+ /* @__PURE__ */ jsx(
4208
+ "button",
4209
+ {
4210
+ type: "button",
4211
+ className: "payman-v2-lightbox-btn",
4212
+ "aria-label": "Close",
4213
+ onClick: (e) => {
4214
+ e.stopPropagation();
4215
+ onClose();
4216
+ },
4217
+ children: /* @__PURE__ */ jsx(X, { size: 20, strokeWidth: 2 })
4218
+ }
4219
+ )
4220
+ ] }),
4221
+ /* @__PURE__ */ jsxs(
4222
+ "div",
4223
+ {
4224
+ className: "payman-v2-lightbox-content",
4225
+ onClick: (e) => e.stopPropagation(),
4226
+ role: "dialog",
4227
+ "aria-modal": "true",
4228
+ "aria-label": alt || "Image preview",
4229
+ children: [
4230
+ !isImageLoaded ? /* @__PURE__ */ jsxs("div", { className: "payman-v2-lightbox-loading", children: [
4231
+ /* @__PURE__ */ jsx(
4232
+ Loader2,
4233
+ {
4234
+ size: 24,
4235
+ strokeWidth: 2,
4236
+ "aria-hidden": true,
4237
+ style: {
4238
+ color: "rgba(255, 255, 255, 0.8)",
4239
+ animation: "payman-v2-spin 0.6s linear infinite"
4240
+ }
4241
+ }
4242
+ ),
4243
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-lightbox-loading-text", children: "Loading image" })
4244
+ ] }) : null,
4245
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-lightbox-img-wrapper", children: /* @__PURE__ */ jsx(
4246
+ motion.div,
4247
+ {
4248
+ initial: { scale: 0.92, opacity: 0 },
4249
+ animate: {
4250
+ scale: isImageLoaded ? 1 : 0.92,
4251
+ opacity: isImageLoaded ? 1 : 0
4252
+ },
4253
+ exit: { scale: 0.92, opacity: 0 },
4254
+ transition: { duration: 0.2 },
4255
+ style: {
4256
+ display: "flex",
4257
+ height: "100%",
4258
+ width: "100%",
4259
+ alignItems: "center",
4260
+ justifyContent: "center"
4261
+ },
4262
+ children: /* @__PURE__ */ jsx(
4263
+ "img",
4264
+ {
4265
+ className: "payman-v2-lightbox-img",
4266
+ src,
4267
+ alt,
4268
+ draggable: false,
4269
+ onLoad: () => setIsImageLoaded(true)
4270
+ }
4271
+ )
4272
+ }
4273
+ ) })
4274
+ ]
4275
+ }
4276
+ )
4277
+ ]
4278
+ },
4279
+ src
4280
+ ) : null }),
4281
+ document.body
4282
+ );
4283
+ }
4284
+ var DEFAULT_USER_ACTION_STATE = {
4285
+ request: null,
4286
+ result: null,
4287
+ clearOtpTrigger: 0
4288
+ };
4289
+ var NOOP_ASYNC = async () => {
4290
+ };
4291
+ function useSentryChatCallbacks(callbacks, config) {
4292
+ const sentryCtxRef = useRef({});
4293
+ const callbacksRef = useRef(callbacks);
4294
+ callbacksRef.current = callbacks;
4295
+ const initialSessionId = config.initialSessionId;
4296
+ const apiHeaders = config.api.headers;
4297
+ useEffect(() => {
4298
+ sentryCtxRef.current.workflowName = config.workflowName;
4299
+ sentryCtxRef.current.sessionOwnerId = config.sessionParams?.id;
4300
+ if (initialSessionId) {
4301
+ sentryCtxRef.current.sessionId = initialSessionId;
4302
+ }
4303
+ if (apiHeaders) {
4304
+ sentryCtxRef.current.customerId = apiHeaders["x-paygent-wf-mcp-customer-id"] ?? sentryCtxRef.current.customerId;
4305
+ sentryCtxRef.current.customerEmail = apiHeaders["x-paygent-wf-mcp-customer-email"] ?? sentryCtxRef.current.customerEmail;
4306
+ }
4307
+ }, [
4308
+ config.workflowName,
4309
+ config.sessionParams?.id,
4310
+ initialSessionId,
4311
+ apiHeaders
4312
+ ]);
4313
+ useEffect(() => {
4314
+ const endpoint = config.api.streamEndpoint || "/api/workflows/ask/stream";
4315
+ return subscribeToCfRay(endpoint, (cfRay) => {
4316
+ sentryCtxRef.current.cfRay = cfRay;
4317
+ });
4318
+ }, [config.api.streamEndpoint]);
4319
+ return useMemo(
4320
+ () => ({
4321
+ onMessageSent: (msg) => callbacksRef.current?.onMessageSent?.(msg),
4322
+ onStreamStart: () => callbacksRef.current?.onStreamStart?.(),
4323
+ onStreamComplete: (message) => {
4324
+ if (message.executionId) {
4325
+ sentryCtxRef.current.executionId = message.executionId;
4326
+ }
4327
+ if (message.sessionId) {
4328
+ sentryCtxRef.current.sessionId = message.sessionId;
4329
+ }
4330
+ const content = message.content ?? "";
4331
+ const looksLikeRawErr = content.length >= 10 && (content.includes("errorType=") || /failed:\s*\{/.test(content));
4332
+ const completedEmpty = !message.isStreaming && !message.isCancelled && content.length === 0 && (message.streamProgress === "completed" || message.streamProgress === "error");
4333
+ const hasConflict = !!getConflictErrorMessage(message.errorDetails);
4334
+ const hasFriendlyErr = isFriendlyWorkflowError(message.errorDetails);
4335
+ const shouldCapture = message.isError || hasConflict || hasFriendlyErr || looksLikeRawErr || completedEmpty;
4336
+ if (shouldCapture) {
4337
+ sentryCtxRef.current.route = typeof window !== "undefined" ? window.location.pathname : void 0;
4338
+ captureSentryError(
4339
+ `Workflow error: ${message.errorDetails || content || "Unknown error"}`,
4340
+ { ...sentryCtxRef.current }
4341
+ );
4342
+ }
4343
+ callbacksRef.current?.onStreamComplete?.(message);
4344
+ },
4345
+ onError: (error) => {
4346
+ sentryCtxRef.current.route = typeof window !== "undefined" ? window.location.pathname : void 0;
4347
+ captureSentryError(error, { ...sentryCtxRef.current });
4348
+ callbacksRef.current?.onError?.(error);
4349
+ },
4350
+ onSessionIdChange: (sessionId) => {
4351
+ sentryCtxRef.current.sessionId = sessionId;
4352
+ callbacksRef.current?.onSessionIdChange?.(sessionId);
4353
+ },
4354
+ onExecutionTraceClick: (data) => callbacksRef.current?.onExecutionTraceClick?.(data),
4355
+ onResetSession: () => callbacksRef.current?.onResetSession?.(),
4356
+ onUploadImageClick: () => callbacksRef.current?.onUploadImageClick?.(),
4357
+ onAttachFileClick: () => callbacksRef.current?.onAttachFileClick?.(),
4358
+ onUserActionRequired: (req) => callbacksRef.current?.onUserActionRequired?.(req),
4359
+ onUserActionEvent: (evType, msg) => callbacksRef.current?.onUserActionEvent?.(evType, msg)
4360
+ }),
4361
+ // eslint-disable-next-line react-hooks/exhaustive-deps
4362
+ []
4363
+ );
4364
+ }
4365
+ var PaymanChatInner = forwardRef(function PaymanChatInner2({
4366
+ config,
4367
+ callbacks = {},
4368
+ className,
4369
+ style,
4370
+ children,
4371
+ onLoadMoreMessages,
4372
+ isLoadingMoreMessages = false,
4373
+ hasMoreMessages = false,
4374
+ chat
4375
+ }, ref) {
4376
+ const [inputValue, setInputValue] = useState("");
4377
+ const prevInputValueRef = useRef(inputValue);
4378
+ const [hasEverSentMessage, setHasEverSentMessage] = useState(false);
4379
+ const [lightboxSrc, setLightboxSrc] = useState(null);
4380
+ const [lightboxAlt, setLightboxAlt] = useState("");
4381
+ const [editingMessageId, setEditingMessageId] = useState(null);
4382
+ const [isResetSessionConfirmOpen, setIsResetSessionConfirmOpen] = useState(false);
4383
+ const chatInputV2Ref = useRef(null);
4384
+ const messageListV2Ref = useRef(null);
4385
+ const resetToEmptyStateRef = useRef(false);
4386
+ const isV2 = config.uiVersion !== 1;
4387
+ useEffect(() => {
4388
+ if (config.sentryDsn) {
4389
+ initSentryIfNeeded(config.sentryDsn);
4390
+ }
4391
+ }, [config.sentryDsn]);
4392
+ const {
4393
+ messages,
4394
+ sendMessage,
4395
+ isWaitingForResponse,
4396
+ resetSession,
4397
+ clearMessages,
4398
+ prependMessages,
4399
+ cancelStream,
4400
+ getSessionId,
4401
+ getMessages
4402
+ } = chat;
4403
+ useEffect(() => {
4404
+ if (resetToEmptyStateRef.current) {
4405
+ if (messages.length === 0) {
4406
+ setHasEverSentMessage(false);
4407
+ resetToEmptyStateRef.current = false;
4408
+ }
4409
+ return;
4410
+ }
4411
+ if (messages.length > 0 && !hasEverSentMessage) {
4412
+ setHasEverSentMessage(true);
4413
+ }
4414
+ }, [messages.length, hasEverSentMessage]);
4415
+ useEffect(() => {
4416
+ if (!editingMessageId) return;
4417
+ const editingMessageStillExists = messages.some(
4418
+ (message) => message.id === editingMessageId && message.role === "user"
4419
+ );
4420
+ if (!editingMessageStillExists) {
4421
+ setEditingMessageId(null);
4422
+ }
4423
+ }, [editingMessageId, messages]);
4424
+ const userActionState = chat.userActionState ?? DEFAULT_USER_ACTION_STATE;
4425
+ const approveUserAction = chat.approveUserAction ?? NOOP_ASYNC;
4426
+ const rejectUserAction = chat.rejectUserAction ?? NOOP_ASYNC;
4427
+ const resendOtp = chat.resendOtp ?? NOOP_ASYNC;
4428
+ const isUserActionSupported = typeof chat.approveUserAction === "function" && typeof chat.rejectUserAction === "function" && typeof chat.resendOtp === "function";
4429
+ const {
4430
+ transcribedText,
4431
+ isAvailable: voiceAvailable,
4432
+ isRecording,
4433
+ startRecording,
4434
+ stopRecording,
4435
+ clearTranscript
4436
+ } = useVoice(
4437
+ {
4438
+ lang: config.voiceLang || "en-US",
4439
+ interimResults: config.voiceInterimResults !== false,
4440
+ continuous: config.voiceContinuous !== false
4441
+ },
4442
+ {
4443
+ onResult: (text) => {
4444
+ if (!isV2) {
4445
+ setInputValue(text);
4446
+ }
4447
+ },
4448
+ onEnd: () => {
4449
+ },
4450
+ onError: (error) => {
2190
4451
  console.error("Voice error:", error);
2191
4452
  }
2192
4453
  }
@@ -2211,17 +4472,46 @@ var PaymanChat = forwardRef(function PaymanChat2({
2211
4472
  isWaitingForResponse
2212
4473
  ]
2213
4474
  );
2214
- const { onExecutionTraceClick, onResetSession } = callbacks;
4475
+ const {
4476
+ onExecutionTraceClick,
4477
+ onResetSession,
4478
+ onUploadImageClick,
4479
+ onAttachFileClick
4480
+ } = callbacks;
4481
+ const performResetSession = useCallback(() => {
4482
+ resetToEmptyStateRef.current = true;
4483
+ setEditingMessageId(null);
4484
+ setIsResetSessionConfirmOpen(false);
4485
+ setInputValue("");
4486
+ setLightboxSrc(null);
4487
+ setLightboxAlt("");
4488
+ chatInputV2Ref.current?.setDraft("");
4489
+ clearTranscript();
4490
+ if (isRecording) {
4491
+ stopRecording();
4492
+ }
4493
+ resetSession();
4494
+ onResetSession?.();
4495
+ }, [
4496
+ clearTranscript,
4497
+ isRecording,
4498
+ onResetSession,
4499
+ resetSession,
4500
+ stopRecording
4501
+ ]);
4502
+ const requestResetSession = useCallback(() => {
4503
+ setIsResetSessionConfirmOpen(true);
4504
+ }, []);
4505
+ const closeResetSessionConfirm = useCallback(() => {
4506
+ setIsResetSessionConfirmOpen(false);
4507
+ }, []);
2215
4508
  useImperativeHandle(ref, () => ({
2216
- resetSession: () => {
2217
- resetSession();
2218
- onResetSession?.();
2219
- },
4509
+ resetSession: performResetSession,
2220
4510
  clearMessages,
2221
4511
  cancelStream,
2222
4512
  getSessionId,
2223
4513
  getMessages
2224
- }), [resetSession, clearMessages, cancelStream, getSessionId, getMessages, onResetSession]);
4514
+ }), [performResetSession, clearMessages, cancelStream, getSessionId, getMessages]);
2225
4515
  const {
2226
4516
  placeholder = "Type your message...",
2227
4517
  emptyStateText = "What can I help with?",
@@ -2245,8 +4535,26 @@ var PaymanChat = forwardRef(function PaymanChat2({
2245
4535
  disabledComponent,
2246
4536
  showEmptyStateIcon = true,
2247
4537
  emptyStateComponent,
2248
- showResetSession = false
4538
+ showResetSession = false,
4539
+ showAttachmentButton = true,
4540
+ showUploadImageButton = true,
4541
+ showAttachFileButton = true,
4542
+ messageActions: messageActionsConfig
2249
4543
  } = config;
4544
+ const messageActions = useMemo(
4545
+ () => ({
4546
+ userMessageActions: {
4547
+ copy: messageActionsConfig?.userMessageActions?.copy ?? true,
4548
+ edit: messageActionsConfig?.userMessageActions?.edit ?? false,
4549
+ retry: messageActionsConfig?.userMessageActions?.retry ?? false
4550
+ },
4551
+ assistantMessageActions: {
4552
+ copy: messageActionsConfig?.assistantMessageActions?.copy ?? true,
4553
+ trace: messageActionsConfig?.assistantMessageActions?.trace ?? true
4554
+ }
4555
+ }),
4556
+ [messageActionsConfig]
4557
+ );
2250
4558
  const isSessionParamsConfigured = useMemo(() => {
2251
4559
  if (!sessionParams) return false;
2252
4560
  return !!(sessionParams.id?.trim() && sessionParams.name?.trim());
@@ -2267,7 +4575,7 @@ var PaymanChat = forwardRef(function PaymanChat2({
2267
4575
  stopRecording();
2268
4576
  }
2269
4577
  if (inputValue.trim() && !disableInput && isSessionParamsConfigured) {
2270
- sendMessage(inputValue.trim());
4578
+ void sendMessage(inputValue.trim());
2271
4579
  setInputValue("");
2272
4580
  }
2273
4581
  };
@@ -2280,6 +4588,7 @@ var PaymanChat = forwardRef(function PaymanChat2({
2280
4588
  stopRecording();
2281
4589
  };
2282
4590
  const isInputDisabled = isWaitingForResponse || !isSessionParamsConfigured || disableInput;
4591
+ const isV2InputDisabled = !isSessionParamsConfigured || disableInput;
2283
4592
  const isEmpty = messages.length === 0;
2284
4593
  if (isChatDisabled) {
2285
4594
  if (disabledComponent) {
@@ -2313,54 +4622,88 @@ var PaymanChat = forwardRef(function PaymanChat2({
2313
4622
  }
2314
4623
  ) });
2315
4624
  }
2316
- const inputElement = hasAskPermission && /* @__PURE__ */ jsx(
2317
- ChatInput,
2318
- {
2319
- value: inputValue,
2320
- onChange: setInputValue,
2321
- onSend: handleSend,
2322
- onPause: cancelStream,
2323
- disabled: isInputDisabled,
2324
- placeholder: isRecording ? "Listening..." : placeholder,
2325
- isWaitingForResponse,
2326
- hasSelectedSession: true,
2327
- isSessionParamsConfigured,
2328
- enableVoice: config.enableVoice === true,
2329
- onVoicePress: isRecording ? stopRecording : startRecording,
2330
- voiceAvailable: config.enableVoice === true && voiceAvailable,
2331
- isRecording,
2332
- transcribedText: inputValue,
2333
- onCancelRecording: handleCancelRecording,
2334
- onConfirmRecording: handleConfirmRecording,
2335
- inputStyle,
2336
- layout,
2337
- showResetSession,
2338
- onResetSession: () => {
2339
- resetSession();
2340
- onResetSession?.();
2341
- }
4625
+ const handleImageClick = (src, alt) => {
4626
+ setLightboxSrc(src);
4627
+ setLightboxAlt(alt);
4628
+ };
4629
+ const v2UserAction = useMemo(() => {
4630
+ if (!isUserActionSupported || !userActionState.request) return null;
4631
+ const req = userActionState.request;
4632
+ let status = "pending";
4633
+ if (userActionState.result === "approved") status = "approved";
4634
+ else if (userActionState.result === "rejected") status = "rejected";
4635
+ return {
4636
+ messageId: `ua-${req.userActionId || Date.now()}`,
4637
+ action: {
4638
+ type: req.userActionType || "generic",
4639
+ message: req.message || "Verify this action",
4640
+ amount: req.metadata?.amount,
4641
+ payeeName: req.metadata?.payeeName
4642
+ },
4643
+ status
4644
+ };
4645
+ }, [isUserActionSupported, userActionState.request, userActionState.result]);
4646
+ const hideV2SendDuringVerification = v2UserAction != null && v2UserAction.status !== "approved" && v2UserAction.status !== "rejected";
4647
+ const handleV2Send = (text) => {
4648
+ if (isRecording) stopRecording();
4649
+ if (text.trim() && !disableInput && isSessionParamsConfigured) {
4650
+ setEditingMessageId(null);
4651
+ void sendMessage(text.trim());
2342
4652
  }
2343
- );
2344
- return /* @__PURE__ */ jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
2345
- "div",
2346
- {
2347
- className: cn(
2348
- "bg-background overflow-hidden flex flex-col flex-[4]",
2349
- className
2350
- ),
2351
- style,
2352
- children: [
2353
- children,
2354
- /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: isEmpty && !hasEverSentMessage ? (
2355
- /* ---- Centered empty state with input ---- */
2356
- /* @__PURE__ */ jsx(
4653
+ };
4654
+ const handleVoicePress = useCallback(async () => {
4655
+ if (!voiceAvailable) return;
4656
+ if (isRecording) {
4657
+ stopRecording();
4658
+ return;
4659
+ }
4660
+ clearTranscript();
4661
+ await startRecording();
4662
+ }, [clearTranscript, isRecording, startRecording, stopRecording, voiceAvailable]);
4663
+ const handleEditMessageDraft = useCallback((messageId) => {
4664
+ const targetMessage = messages.find((message) => message.id === messageId);
4665
+ if (!targetMessage?.content.trim()) return;
4666
+ setEditingMessageId(messageId);
4667
+ chatInputV2Ref.current?.setDraft(targetMessage.content);
4668
+ requestAnimationFrame(() => {
4669
+ messageListV2Ref.current?.scrollToBottom("smooth");
4670
+ });
4671
+ }, [messages]);
4672
+ const handleRetryUserMessage = useCallback((messageId) => {
4673
+ if (isWaitingForResponse) return;
4674
+ const targetMessage = messages.find(
4675
+ (message) => message.id === messageId && message.role === "user"
4676
+ );
4677
+ if (!targetMessage?.content.trim()) return;
4678
+ void sendMessage(targetMessage.content.trim());
4679
+ const bump = () => messageListV2Ref.current?.scrollToBottom("instant");
4680
+ requestAnimationFrame(() => {
4681
+ bump();
4682
+ queueMicrotask(() => {
4683
+ window.setTimeout(bump, 120);
4684
+ });
4685
+ });
4686
+ }, [isWaitingForResponse, messages, sendMessage]);
4687
+ const handleClearEditing = useCallback(() => {
4688
+ setEditingMessageId(null);
4689
+ }, []);
4690
+ if (isV2) {
4691
+ return /* @__PURE__ */ jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
4692
+ "div",
4693
+ {
4694
+ className: cn("payman-v2-root", className),
4695
+ style,
4696
+ children: [
4697
+ children,
4698
+ isChatDisabled ? disabledComponent || /* @__PURE__ */ jsx("div", { style: { flex: 1, display: "flex", alignItems: "center", justifyContent: "center", padding: "1rem" }, children: /* @__PURE__ */ jsx("div", { style: { textAlign: "center", color: "var(--payman-v2-text-3)", fontSize: "0.875rem" }, children: "Chat is currently disabled" }) }) : /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: isEmpty && !hasEverSentMessage ? /* @__PURE__ */ jsx(
2357
4699
  motion.div,
2358
4700
  {
2359
4701
  initial: { opacity: 1 },
2360
4702
  exit: { opacity: 0 },
2361
4703
  transition: { duration: 0.3 },
2362
- className: "payman-empty-centered-layout",
2363
- children: /* @__PURE__ */ jsxs("div", { className: "payman-empty-centered-inner", children: [
4704
+ className: "payman-v2-chat-layout",
4705
+ style: { justifyContent: "center", alignItems: "center" },
4706
+ children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", flex: 1, width: "100%" }, children: [
2364
4707
  /* @__PURE__ */ jsx(
2365
4708
  MessageList,
2366
4709
  {
@@ -2394,56 +4737,246 @@ var PaymanChat = forwardRef(function PaymanChat2({
2394
4737
  initial: { opacity: 0, y: 12 },
2395
4738
  animate: { opacity: 1, y: 0 },
2396
4739
  transition: { delay: 0.2, duration: 0.4, ease: [0.25, 0.46, 0.45, 0.94] },
2397
- className: "payman-empty-centered-input",
2398
- children: inputElement
4740
+ style: { width: "100%" },
4741
+ children: hasAskPermission && /* @__PURE__ */ jsx(
4742
+ ChatInputV2,
4743
+ {
4744
+ ref: chatInputV2Ref,
4745
+ onSend: handleV2Send,
4746
+ onCancel: cancelStream,
4747
+ disabled: isV2InputDisabled,
4748
+ isStreaming: isWaitingForResponse,
4749
+ placeholder: isRecording ? "Listening..." : placeholder,
4750
+ enableVoice: config.enableVoice === true,
4751
+ transcribedText: config.enableVoice === true ? transcribedText : "",
4752
+ voiceAvailable: config.enableVoice === true && voiceAvailable,
4753
+ isRecording,
4754
+ onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
4755
+ onCancelRecording: handleCancelRecording,
4756
+ onConfirmRecording: handleConfirmRecording,
4757
+ showResetSession,
4758
+ onResetSession: requestResetSession,
4759
+ showAttachmentButton,
4760
+ showUploadImageButton,
4761
+ showAttachFileButton,
4762
+ onUploadImageClick,
4763
+ onAttachFileClick,
4764
+ editingMessageId,
4765
+ onClearEditing: handleClearEditing,
4766
+ hideSendButton: hideV2SendDuringVerification
4767
+ }
4768
+ )
2399
4769
  }
2400
4770
  )
2401
4771
  ] })
2402
4772
  },
2403
- "empty-centered"
2404
- )
2405
- ) : (
2406
- /* ---- Normal chat layout ---- */
2407
- /* @__PURE__ */ jsxs(
4773
+ "v2-empty"
4774
+ ) : /* @__PURE__ */ jsxs(
2408
4775
  motion.div,
2409
4776
  {
2410
4777
  initial: hasEverSentMessage ? { opacity: 0 } : false,
2411
4778
  animate: { opacity: 1 },
2412
4779
  transition: { duration: 0.3 },
2413
- className: "flex flex-col flex-1 min-h-0",
4780
+ className: "payman-v2-chat-layout",
2414
4781
  children: [
2415
4782
  /* @__PURE__ */ jsx(
2416
- MessageList,
4783
+ MessageListV2,
2417
4784
  {
4785
+ ref: messageListV2Ref,
2418
4786
  messages,
2419
- isLoading: false,
2420
- emptyStateText,
2421
- showEmptyStateIcon,
2422
- emptyStateComponent,
2423
- layout,
2424
- showTimestamps,
2425
- stage: config.stage || "DEV",
2426
- animated,
2427
- showAgentName,
2428
- agentName,
2429
- showAvatars,
2430
- showUserAvatar,
2431
- showAssistantAvatar,
2432
- showExecutionSteps,
2433
- showStreamingDot,
2434
- streamingStepsText,
2435
- completedStepsText,
4787
+ isStreaming: isWaitingForResponse,
4788
+ onEditUserMessage: handleEditMessageDraft,
4789
+ onRetryUserMessage: handleRetryUserMessage,
4790
+ onImageClick: handleImageClick,
2436
4791
  onExecutionTraceClick,
2437
- onLoadMoreMessages,
2438
- isLoadingMoreMessages,
2439
- hasMoreMessages
4792
+ messageActions,
4793
+ retryDisabled: isWaitingForResponse,
4794
+ userAction: v2UserAction,
4795
+ onApproveAction: isUserActionSupported ? async (_msgId, otp) => {
4796
+ await approveUserAction(otp);
4797
+ } : void 0,
4798
+ onRejectAction: isUserActionSupported ? async () => {
4799
+ await rejectUserAction();
4800
+ } : void 0,
4801
+ onResendAction: isUserActionSupported ? async () => {
4802
+ await resendOtp();
4803
+ } : void 0
2440
4804
  }
2441
4805
  ),
2442
- inputElement
4806
+ hasAskPermission && /* @__PURE__ */ jsx(
4807
+ ChatInputV2,
4808
+ {
4809
+ ref: chatInputV2Ref,
4810
+ onSend: handleV2Send,
4811
+ onCancel: cancelStream,
4812
+ disabled: isV2InputDisabled,
4813
+ isStreaming: isWaitingForResponse,
4814
+ placeholder: isRecording ? "Listening..." : placeholder,
4815
+ enableVoice: config.enableVoice === true,
4816
+ transcribedText: config.enableVoice === true ? transcribedText : "",
4817
+ voiceAvailable: config.enableVoice === true && voiceAvailable,
4818
+ isRecording,
4819
+ onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
4820
+ onCancelRecording: handleCancelRecording,
4821
+ onConfirmRecording: handleConfirmRecording,
4822
+ showResetSession,
4823
+ onResetSession: requestResetSession,
4824
+ showAttachmentButton,
4825
+ showUploadImageButton,
4826
+ showAttachFileButton,
4827
+ onUploadImageClick,
4828
+ onAttachFileClick,
4829
+ editingMessageId,
4830
+ onClearEditing: handleClearEditing,
4831
+ hideSendButton: hideV2SendDuringVerification
4832
+ }
4833
+ )
2443
4834
  ]
2444
4835
  },
2445
- "chat-layout"
4836
+ "v2-chat"
4837
+ ) }),
4838
+ /* @__PURE__ */ jsx(
4839
+ ImageLightboxV2,
4840
+ {
4841
+ src: lightboxSrc,
4842
+ alt: lightboxAlt,
4843
+ onClose: () => setLightboxSrc(null)
4844
+ }
4845
+ ),
4846
+ /* @__PURE__ */ jsx(
4847
+ ResetSessionConfirmModal,
4848
+ {
4849
+ isOpen: isResetSessionConfirmOpen,
4850
+ onClose: closeResetSessionConfirm,
4851
+ onConfirm: performResetSession
4852
+ }
2446
4853
  )
4854
+ ]
4855
+ }
4856
+ ) });
4857
+ }
4858
+ const inputElement = hasAskPermission && /* @__PURE__ */ jsx(
4859
+ ChatInput,
4860
+ {
4861
+ value: inputValue,
4862
+ onChange: setInputValue,
4863
+ onSend: handleSend,
4864
+ onPause: cancelStream,
4865
+ disabled: isInputDisabled,
4866
+ placeholder: isRecording ? "Listening..." : placeholder,
4867
+ isWaitingForResponse,
4868
+ hasSelectedSession: true,
4869
+ isSessionParamsConfigured,
4870
+ enableVoice: config.enableVoice === true,
4871
+ onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
4872
+ voiceAvailable: config.enableVoice === true && voiceAvailable,
4873
+ isRecording,
4874
+ transcribedText: inputValue,
4875
+ onCancelRecording: handleCancelRecording,
4876
+ onConfirmRecording: handleConfirmRecording,
4877
+ inputStyle,
4878
+ layout,
4879
+ showResetSession,
4880
+ onResetSession: requestResetSession
4881
+ }
4882
+ );
4883
+ return /* @__PURE__ */ jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
4884
+ "div",
4885
+ {
4886
+ className: cn(
4887
+ "bg-background overflow-hidden flex flex-col flex-[4]",
4888
+ className
4889
+ ),
4890
+ style,
4891
+ children: [
4892
+ children,
4893
+ /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: isEmpty && !hasEverSentMessage ? /* @__PURE__ */ jsx(
4894
+ motion.div,
4895
+ {
4896
+ initial: { opacity: 1 },
4897
+ exit: { opacity: 0 },
4898
+ transition: { duration: 0.3 },
4899
+ className: "payman-empty-centered-layout",
4900
+ children: /* @__PURE__ */ jsxs("div", { className: "payman-empty-centered-inner", children: [
4901
+ /* @__PURE__ */ jsx(
4902
+ MessageList,
4903
+ {
4904
+ messages,
4905
+ isLoading: false,
4906
+ emptyStateText,
4907
+ showEmptyStateIcon,
4908
+ emptyStateComponent,
4909
+ layout,
4910
+ showTimestamps,
4911
+ stage: config.stage || "DEV",
4912
+ animated,
4913
+ showAgentName,
4914
+ agentName,
4915
+ showAvatars,
4916
+ showUserAvatar,
4917
+ showAssistantAvatar,
4918
+ showExecutionSteps,
4919
+ showStreamingDot,
4920
+ streamingStepsText,
4921
+ completedStepsText,
4922
+ onExecutionTraceClick,
4923
+ onLoadMoreMessages,
4924
+ isLoadingMoreMessages,
4925
+ hasMoreMessages
4926
+ }
4927
+ ),
4928
+ /* @__PURE__ */ jsx(
4929
+ motion.div,
4930
+ {
4931
+ initial: { opacity: 0, y: 12 },
4932
+ animate: { opacity: 1, y: 0 },
4933
+ transition: { delay: 0.2, duration: 0.4, ease: [0.25, 0.46, 0.45, 0.94] },
4934
+ className: "payman-empty-centered-input",
4935
+ children: inputElement
4936
+ }
4937
+ )
4938
+ ] })
4939
+ },
4940
+ "empty-centered"
4941
+ ) : /* @__PURE__ */ jsxs(
4942
+ motion.div,
4943
+ {
4944
+ initial: hasEverSentMessage ? { opacity: 0 } : false,
4945
+ animate: { opacity: 1 },
4946
+ transition: { duration: 0.3 },
4947
+ className: "flex flex-col flex-1 min-h-0",
4948
+ children: [
4949
+ /* @__PURE__ */ jsx(
4950
+ MessageList,
4951
+ {
4952
+ messages,
4953
+ isLoading: false,
4954
+ emptyStateText,
4955
+ showEmptyStateIcon,
4956
+ emptyStateComponent,
4957
+ layout,
4958
+ showTimestamps,
4959
+ stage: config.stage || "DEV",
4960
+ animated,
4961
+ showAgentName,
4962
+ agentName,
4963
+ showAvatars,
4964
+ showUserAvatar,
4965
+ showAssistantAvatar,
4966
+ showExecutionSteps,
4967
+ showStreamingDot,
4968
+ streamingStepsText,
4969
+ completedStepsText,
4970
+ onExecutionTraceClick,
4971
+ onLoadMoreMessages,
4972
+ isLoadingMoreMessages,
4973
+ hasMoreMessages
4974
+ }
4975
+ ),
4976
+ inputElement
4977
+ ]
4978
+ },
4979
+ "chat-layout"
2447
4980
  ) }),
2448
4981
  /* @__PURE__ */ jsx(
2449
4982
  UserActionModal,
@@ -2455,11 +4988,41 @@ var PaymanChat = forwardRef(function PaymanChat2({
2455
4988
  onResend: resendOtp,
2456
4989
  clearOtpTrigger: userActionState.clearOtpTrigger
2457
4990
  }
4991
+ ),
4992
+ /* @__PURE__ */ jsx(
4993
+ ResetSessionConfirmModal,
4994
+ {
4995
+ isOpen: isResetSessionConfirmOpen,
4996
+ onClose: closeResetSessionConfirm,
4997
+ onConfirm: performResetSession
4998
+ }
2458
4999
  )
2459
5000
  ]
2460
5001
  }
2461
5002
  ) });
2462
5003
  });
5004
+ var PaymanChatV1Shell = forwardRef(
5005
+ function PaymanChatV1Shell2(props, ref) {
5006
+ const mergedCallbacks = useSentryChatCallbacks(props.callbacks, props.config);
5007
+ const chat = useChat(props.config, mergedCallbacks);
5008
+ return /* @__PURE__ */ jsx(PaymanChatInner, { ...props, chat, ref });
5009
+ }
5010
+ );
5011
+ var PaymanChatV2Shell = forwardRef(
5012
+ function PaymanChatV2Shell2(props, ref) {
5013
+ const mergedCallbacks = useSentryChatCallbacks(props.callbacks, props.config);
5014
+ const chat = useChatV2(props.config, mergedCallbacks);
5015
+ return /* @__PURE__ */ jsx(PaymanChatInner, { ...props, chat, ref });
5016
+ }
5017
+ );
5018
+ var PaymanChat = forwardRef(
5019
+ function PaymanChat2(props, ref) {
5020
+ if (props.config.uiVersion !== 1) {
5021
+ return /* @__PURE__ */ jsx(PaymanChatV2Shell, { ...props, ref });
5022
+ }
5023
+ return /* @__PURE__ */ jsx(PaymanChatV1Shell, { ...props, ref });
5024
+ }
5025
+ );
2463
5026
 
2464
5027
  export { PaymanChat, PaymanChatContext, captureSentryError, cn, formatDate, usePaymanChat };
2465
5028
  //# sourceMappingURL=index.mjs.map