@paymanai/payman-ask-sdk 1.2.23 → 1.2.24

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,12 +1,12 @@
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';
@@ -54,114 +54,6 @@ function formatElapsedTime(ms) {
54
54
  if (ms < 1e3) return `${ms}ms`;
55
55
  return `${(ms / 1e3).toFixed(1)}s`;
56
56
  }
57
- function captureSentryError(error, context) {
58
- if (!Sentry.getClient()) return;
59
- const tags = {};
60
- if (context.executionId) tags.executionId = context.executionId;
61
- if (context.sessionId) tags.sessionId = context.sessionId;
62
- if (context.route) tags.route = context.route;
63
- if (context.cfRay) tags.cfRay = context.cfRay;
64
- if (context.customerId) tags.customerId = context.customerId;
65
- if (context.customerEmail) tags.customerEmail = context.customerEmail;
66
- const contexts = {
67
- chat_session: {
68
- sessionId: context.sessionId ?? null,
69
- sessionOwnerId: context.sessionOwnerId ?? null,
70
- executionId: context.executionId ?? null,
71
- workflowName: context.workflowName ?? null,
72
- cfRay: context.cfRay ?? null,
73
- customerId: context.customerId ?? null,
74
- customerEmail: context.customerEmail ?? null
75
- }
76
- };
77
- if (typeof error === "string") {
78
- Sentry.captureMessage(error, { level: "error", tags, contexts });
79
- } else {
80
- Sentry.captureException(error, { tags, contexts });
81
- }
82
- }
83
- var interceptors = /* @__PURE__ */ new Set();
84
- var originalFetch = null;
85
- function patchFetch() {
86
- if (originalFetch !== null) return;
87
- if (typeof globalThis === "undefined" || typeof globalThis.fetch !== "function")
88
- return;
89
- originalFetch = globalThis.fetch;
90
- globalThis.fetch = async function(input, init2) {
91
- const response = await originalFetch.call(this, input, init2);
92
- if (interceptors.size > 0) {
93
- const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
94
- try {
95
- const cfRay = response.headers.get("cf-ray");
96
- if (cfRay) {
97
- for (const entry of interceptors) {
98
- if (url.includes(entry.urlPattern)) {
99
- entry.listener(cfRay);
100
- }
101
- }
102
- }
103
- } catch {
104
- }
105
- }
106
- return response;
107
- };
108
- }
109
- function maybeUnpatchFetch() {
110
- if (interceptors.size > 0 || originalFetch === null) return;
111
- globalThis.fetch = originalFetch;
112
- originalFetch = null;
113
- }
114
- function subscribeToCfRay(urlPattern, listener) {
115
- const entry = { urlPattern, listener };
116
- patchFetch();
117
- interceptors.add(entry);
118
- return () => {
119
- interceptors.delete(entry);
120
- maybeUnpatchFetch();
121
- };
122
- }
123
-
124
- // src/utils/errorMessages.ts
125
- var WORKFLOW_FAILED = "WORKFLOW_FAILED";
126
- var STREAM_NOT_STARTED = "STREAM_NOT_STARTED";
127
- var HTTP_ERROR_PREFIX = /^HTTP\s+(\d+)\s*:\s*([\s\S]+)$/;
128
- function isFriendlyWorkflowError(errorDetails) {
129
- if (!errorDetails) return false;
130
- return errorDetails === WORKFLOW_FAILED || errorDetails === STREAM_NOT_STARTED || errorDetails.includes(WORKFLOW_FAILED);
131
- }
132
- function parseErrorPayload(payload) {
133
- try {
134
- const parsed = JSON.parse(payload);
135
- if (typeof parsed === "string") {
136
- return { message: parsed.trim() || void 0 };
137
- }
138
- if (typeof parsed === "object" && parsed !== null) {
139
- const record = parsed;
140
- return {
141
- status: typeof record.status === "number" ? record.status : void 0,
142
- message: typeof record.message === "string" && record.message.trim() ? record.message.trim() : void 0
143
- };
144
- }
145
- } catch {
146
- }
147
- return {};
148
- }
149
- function getConflictErrorMessage(errorDetails) {
150
- if (!errorDetails) return void 0;
151
- const trimmedError = errorDetails.trim();
152
- const httpMatch = trimmedError.match(HTTP_ERROR_PREFIX);
153
- const httpStatus = httpMatch ? Number(httpMatch[1]) : void 0;
154
- const rawPayload = (httpMatch ? httpMatch[2] : trimmedError).trim();
155
- const payload = parseErrorPayload(rawPayload);
156
- const status = payload.status ?? httpStatus;
157
- if (status !== 409) {
158
- return void 0;
159
- }
160
- if (payload.message) {
161
- return payload.message;
162
- }
163
- return rawPayload || void 0;
164
- }
165
57
  function initSentryIfNeeded(dsn) {
166
58
  if (!dsn) return;
167
59
  if (Sentry.getClient()) return;
@@ -454,7 +346,7 @@ function ImageLightbox({
454
346
  background: "rgba(2, 6, 23, 0.92)",
455
347
  isolation: "isolate"
456
348
  };
457
- const frameStyle = {
349
+ const frameStyle2 = {
458
350
  position: "relative",
459
351
  width: "min(92vw, 1280px)",
460
352
  height: "min(88vh, 920px)",
@@ -514,7 +406,7 @@ function ImageLightbox({
514
406
  children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
515
407
  }
516
408
  ),
517
- /* @__PURE__ */ jsxs("div", { style: frameStyle, onClick: (event) => event.stopPropagation(), children: [
409
+ /* @__PURE__ */ jsxs("div", { style: frameStyle2, onClick: (event) => event.stopPropagation(), children: [
518
410
  !isImageLoaded ? /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 flex flex-col items-center justify-center gap-2", children: [
519
411
  /* @__PURE__ */ jsx(Loader2, { className: "h-5 w-5 animate-spin text-white/80" }),
520
412
  /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-white/90", children: "Loading image" }),
@@ -686,6 +578,48 @@ function createMarkdownComponents(options = {}) {
686
578
  td: ({ children }) => /* @__PURE__ */ jsx("td", { className: "p-3 align-middle text-sm whitespace-nowrap", children })
687
579
  };
688
580
  }
581
+
582
+ // src/utils/errorMessages.ts
583
+ var WORKFLOW_FAILED = "WORKFLOW_FAILED";
584
+ var STREAM_NOT_STARTED = "STREAM_NOT_STARTED";
585
+ var HTTP_ERROR_PREFIX = /^HTTP\s+(\d+)\s*:\s*([\s\S]+)$/;
586
+ function isFriendlyWorkflowError(errorDetails) {
587
+ if (!errorDetails) return false;
588
+ return errorDetails === WORKFLOW_FAILED || errorDetails === STREAM_NOT_STARTED || errorDetails.includes(WORKFLOW_FAILED);
589
+ }
590
+ function parseErrorPayload(payload) {
591
+ try {
592
+ const parsed = JSON.parse(payload);
593
+ if (typeof parsed === "string") {
594
+ return { message: parsed.trim() || void 0 };
595
+ }
596
+ if (typeof parsed === "object" && parsed !== null) {
597
+ const record = parsed;
598
+ return {
599
+ status: typeof record.status === "number" ? record.status : void 0,
600
+ message: typeof record.message === "string" && record.message.trim() ? record.message.trim() : void 0
601
+ };
602
+ }
603
+ } catch {
604
+ }
605
+ return {};
606
+ }
607
+ function getConflictErrorMessage(errorDetails) {
608
+ if (!errorDetails) return void 0;
609
+ const trimmedError = errorDetails.trim();
610
+ const httpMatch = trimmedError.match(HTTP_ERROR_PREFIX);
611
+ const httpStatus = httpMatch ? Number(httpMatch[1]) : void 0;
612
+ const rawPayload = (httpMatch ? httpMatch[2] : trimmedError).trim();
613
+ const payload = parseErrorPayload(rawPayload);
614
+ const status = payload.status ?? httpStatus;
615
+ if (status !== 409) {
616
+ return void 0;
617
+ }
618
+ if (payload.message) {
619
+ return payload.message;
620
+ }
621
+ return rawPayload || void 0;
622
+ }
689
623
  function ThinkingBlock({ text }) {
690
624
  const [isOpen, setIsOpen] = useState(false);
691
625
  const hasContent = typeof text === "string" && text.trim().length > 0;
@@ -1398,6 +1332,101 @@ function MessageList({
1398
1332
  }
1399
1333
  ) });
1400
1334
  }
1335
+ function ResetSessionConfirmModal({
1336
+ isOpen,
1337
+ onClose,
1338
+ onConfirm
1339
+ }) {
1340
+ const handleKeyDown = useCallback(
1341
+ (event) => {
1342
+ if (event.key === "Escape") {
1343
+ onClose();
1344
+ }
1345
+ },
1346
+ [onClose]
1347
+ );
1348
+ useEffect(() => {
1349
+ if (!isOpen || typeof document === "undefined") return;
1350
+ document.addEventListener("keydown", handleKeyDown);
1351
+ const previousOverflow = document.body.style.overflow;
1352
+ document.body.style.overflow = "hidden";
1353
+ return () => {
1354
+ document.removeEventListener("keydown", handleKeyDown);
1355
+ document.body.style.overflow = previousOverflow;
1356
+ };
1357
+ }, [handleKeyDown, isOpen]);
1358
+ return /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen ? /* @__PURE__ */ jsxs(
1359
+ motion.div,
1360
+ {
1361
+ className: "payman-reset-session-modal-backdrop",
1362
+ initial: { opacity: 0 },
1363
+ animate: { opacity: 1 },
1364
+ exit: { opacity: 0 },
1365
+ transition: { duration: 0.18 },
1366
+ onClick: onClose,
1367
+ role: "presentation",
1368
+ children: [
1369
+ /* @__PURE__ */ jsx("div", { className: "payman-reset-session-modal-overlay" }),
1370
+ /* @__PURE__ */ jsxs(
1371
+ motion.div,
1372
+ {
1373
+ initial: { opacity: 0, y: 12, scale: 0.98 },
1374
+ animate: { opacity: 1, y: 0, scale: 1 },
1375
+ exit: { opacity: 0, y: 8, scale: 0.98 },
1376
+ transition: { duration: 0.2, ease: [0.16, 1, 0.3, 1] },
1377
+ className: "payman-reset-session-modal-dialog",
1378
+ onClick: (event) => event.stopPropagation(),
1379
+ role: "dialog",
1380
+ "aria-modal": "true",
1381
+ "aria-labelledby": "payman-reset-session-title",
1382
+ "aria-describedby": "payman-reset-session-description",
1383
+ children: [
1384
+ /* @__PURE__ */ jsxs("div", { className: "payman-reset-session-modal-copy", children: [
1385
+ /* @__PURE__ */ jsx("p", { className: "payman-reset-session-modal-eyebrow", children: "New Session" }),
1386
+ /* @__PURE__ */ jsx(
1387
+ "h2",
1388
+ {
1389
+ id: "payman-reset-session-title",
1390
+ className: "payman-reset-session-modal-title",
1391
+ children: "Start a new session?"
1392
+ }
1393
+ ),
1394
+ /* @__PURE__ */ jsx(
1395
+ "p",
1396
+ {
1397
+ id: "payman-reset-session-description",
1398
+ className: "payman-reset-session-modal-description",
1399
+ children: "This will clear the current conversation and start fresh."
1400
+ }
1401
+ )
1402
+ ] }),
1403
+ /* @__PURE__ */ jsxs("div", { className: "payman-reset-session-modal-actions", children: [
1404
+ /* @__PURE__ */ jsx(
1405
+ "button",
1406
+ {
1407
+ type: "button",
1408
+ onClick: onClose,
1409
+ className: "payman-reset-session-modal-btn payman-reset-session-modal-btn-secondary",
1410
+ children: "Cancel"
1411
+ }
1412
+ ),
1413
+ /* @__PURE__ */ jsx(
1414
+ "button",
1415
+ {
1416
+ type: "button",
1417
+ onClick: onConfirm,
1418
+ className: "payman-reset-session-modal-btn payman-reset-session-modal-btn-primary",
1419
+ children: "New Session"
1420
+ }
1421
+ )
1422
+ ] })
1423
+ ]
1424
+ }
1425
+ )
1426
+ ]
1427
+ }
1428
+ ) : null });
1429
+ }
1401
1430
 
1402
1431
  // src/assets/payman-mono-crop-blue.png
1403
1432
  var payman_mono_crop_blue_default = "data:image/png;base64,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";
@@ -2054,99 +2083,1868 @@ function UserActionModal({
2054
2083
  }
2055
2084
  );
2056
2085
  }
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);
2086
+ function ActionTooltipV2({ label, children }) {
2087
+ return /* @__PURE__ */ jsxs("div", { className: "payman-v2-tooltip", children: [
2088
+ children,
2089
+ /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "payman-v2-tooltip-content", children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-tooltip-text", children: [
2090
+ label,
2091
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-tooltip-arrow" })
2092
+ ] }) })
2093
+ ] });
2094
+ }
2095
+ function formatMessageTime(timestamp) {
2096
+ const value = new Date(timestamp);
2097
+ if (Number.isNaN(value.getTime())) return "";
2098
+ return new Intl.DateTimeFormat(void 0, {
2099
+ hour: "numeric",
2100
+ minute: "2-digit"
2101
+ }).format(value);
2102
+ }
2103
+ function UserMessageV2({
2104
+ message,
2105
+ onEdit,
2106
+ onRetry,
2107
+ retryDisabled = false,
2108
+ actions
2109
+ }) {
2110
+ const [copied, setCopied] = useState(false);
2111
+ const [toast, setToast] = useState(null);
2112
+ const copyResetTimerRef = useRef(null);
2113
+ const toastTimerRef = useRef(null);
2114
+ const showCopyAction = actions?.copy ?? true;
2115
+ const showEditAction = actions?.edit ?? false;
2116
+ const showRetryAction = actions?.retry ?? false;
2076
2117
  useEffect(() => {
2077
- if (config.sentryDsn) {
2078
- initSentryIfNeeded(config.sentryDsn);
2118
+ return () => {
2119
+ if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
2120
+ if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
2121
+ };
2122
+ }, []);
2123
+ const showToast = (label, tone) => {
2124
+ if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
2125
+ setToast({ label, tone });
2126
+ toastTimerRef.current = setTimeout(() => setToast(null), 1800);
2127
+ };
2128
+ const handleCopy = async () => {
2129
+ try {
2130
+ if (!navigator.clipboard?.writeText) {
2131
+ throw new Error("Clipboard unavailable");
2132
+ }
2133
+ await navigator.clipboard.writeText(message.content);
2134
+ if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
2135
+ setCopied(true);
2136
+ copyResetTimerRef.current = setTimeout(() => setCopied(false), 1800);
2137
+ showToast("Copied to clipboard", "success");
2138
+ } catch {
2139
+ setCopied(false);
2140
+ showToast("Could not copy", "error");
2079
2141
  }
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;
2142
+ };
2143
+ const timestamp = formatMessageTime(message.timestamp);
2144
+ const hasVisibleActions = showCopyAction || showEditAction && !!onEdit || showRetryAction && !!onRetry;
2145
+ const toastPortal = typeof document !== "undefined" ? createPortal(
2146
+ /* @__PURE__ */ jsx(AnimatePresence, { children: toast && /* @__PURE__ */ jsx(
2147
+ motion.div,
2148
+ {
2149
+ initial: { opacity: 0, y: -18, scale: 0.96 },
2150
+ animate: { opacity: 1, y: 0, scale: 1 },
2151
+ exit: { opacity: 0, y: -12, scale: 0.96 },
2152
+ transition: {
2153
+ type: "spring",
2154
+ stiffness: 360,
2155
+ damping: 26,
2156
+ mass: 0.7
2157
+ },
2158
+ className: "payman-v2-toast",
2159
+ role: "status",
2160
+ "aria-live": "polite",
2161
+ children: /* @__PURE__ */ jsxs(
2162
+ "div",
2163
+ {
2164
+ className: cn(
2165
+ "payman-v2-toast-inner",
2166
+ toast.tone === "success" ? "payman-v2-toast-success" : "payman-v2-toast-error"
2167
+ ),
2168
+ children: [
2169
+ toast.tone === "success" ? /* @__PURE__ */ jsx(Check, { className: "h-4 w-4", style: { color: "#059669" } }) : /* @__PURE__ */ jsx(
2170
+ AlertCircle,
2171
+ {
2172
+ className: "h-4 w-4",
2173
+ style: { color: "#ef4444" }
2174
+ }
2175
+ ),
2176
+ /* @__PURE__ */ jsx("span", { children: toast.label })
2177
+ ]
2178
+ }
2179
+ )
2180
+ }
2181
+ ) }),
2182
+ document.body
2183
+ ) : null;
2184
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2185
+ toastPortal,
2186
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-user-msg payman-v2-fade-in", children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-user-msg-group", children: [
2187
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-user-msg-bubble", children: /* @__PURE__ */ jsx("p", { className: "payman-v2-user-msg-text", children: message.content }) }),
2188
+ message.isError && message.errorDetails && /* @__PURE__ */ jsxs("div", { className: "payman-v2-user-msg-error", children: [
2189
+ /* @__PURE__ */ jsx(
2190
+ AlertCircle,
2191
+ {
2192
+ className: "h-3.5 w-3.5 shrink-0",
2193
+ style: { color: "rgba(239, 68, 68, 0.7)", marginTop: "2px" }
2194
+ }
2195
+ ),
2196
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-user-msg-error-text", children: message.errorDetails })
2197
+ ] }),
2198
+ (timestamp || hasVisibleActions) && /* @__PURE__ */ jsxs("div", { className: "payman-v2-user-msg-actions", children: [
2199
+ timestamp ? /* @__PURE__ */ jsx("span", { className: "payman-v2-user-msg-timestamp", children: timestamp }) : null,
2200
+ showCopyAction && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Copy", children: /* @__PURE__ */ jsx(
2201
+ "button",
2202
+ {
2203
+ type: "button",
2204
+ onClick: () => void handleCopy(),
2205
+ className: "payman-v2-user-msg-action-btn",
2206
+ "aria-label": "Copy message",
2207
+ children: copied ? /* @__PURE__ */ jsx(
2208
+ Check,
2209
+ {
2210
+ className: "h-3.5 w-3.5",
2211
+ style: { color: "#059669" }
2212
+ }
2213
+ ) : /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" })
2214
+ }
2215
+ ) }),
2216
+ showEditAction && onEdit && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Edit", children: /* @__PURE__ */ jsx(
2217
+ "button",
2218
+ {
2219
+ type: "button",
2220
+ onClick: () => onEdit(message.id),
2221
+ className: "payman-v2-user-msg-action-btn",
2222
+ "aria-label": "Edit message",
2223
+ children: /* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" })
2224
+ }
2225
+ ) }),
2226
+ showRetryAction && onRetry && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Retry", children: /* @__PURE__ */ jsx(
2227
+ "button",
2228
+ {
2229
+ type: "button",
2230
+ onClick: () => onRetry(message.id),
2231
+ disabled: retryDisabled,
2232
+ className: "payman-v2-user-msg-action-btn",
2233
+ "aria-label": "Retry message",
2234
+ children: /* @__PURE__ */ jsx(RotateCcw, { className: "h-3.5 w-3.5" })
2235
+ }
2236
+ ) })
2237
+ ] })
2238
+ ] }) })
2239
+ ] });
2240
+ }
2241
+ var RAG_IMAGE_PATH_REGEX2 = /^(?:https?:\/\/[^/\s]+)?\/api\/rag\/chunks\/[^"'\s]+\/image(?:[?#][^"'\s]*)?$/;
2242
+ function isUnresolvedRagImageSource2(src) {
2243
+ return RAG_IMAGE_PATH_REGEX2.test(src);
2244
+ }
2245
+ var frameStyle = {
2246
+ width: "min(100%, 32rem)",
2247
+ maxWidth: "100%"
2248
+ };
2249
+ var imgStyle = {
2250
+ display: "block",
2251
+ width: "100%",
2252
+ height: "auto",
2253
+ maxWidth: "100%",
2254
+ maxHeight: "22rem",
2255
+ objectFit: "contain"
2256
+ };
2257
+ function MarkdownImageV2({
2258
+ src,
2259
+ alt,
2260
+ isResolving = false,
2261
+ onImageClick
2262
+ }) {
2263
+ const [isVisible, setIsVisible] = useState(false);
2264
+ const [isLoaded, setIsLoaded] = useState(false);
2265
+ const [hasError, setHasError] = useState(false);
2266
+ const [retryCount, setRetryCount] = useState(0);
2267
+ const sentinelRef = useRef(null);
2268
+ const isUnresolvedRag = useMemo(
2269
+ () => src ? isUnresolvedRagImageSource2(src) : false,
2270
+ [src]
2271
+ );
2272
+ const isResolvingRag = Boolean(isResolving && isUnresolvedRag);
2086
2273
  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
- ]);
2274
+ setIsLoaded(false);
2275
+ setHasError(false);
2276
+ setRetryCount(0);
2277
+ setIsVisible(false);
2278
+ }, [src]);
2102
2279
  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
- );
2280
+ const el = sentinelRef.current;
2281
+ if (!el || !src) return;
2282
+ const observer = new IntersectionObserver(
2283
+ ([entry]) => {
2284
+ if (entry.isIntersecting) {
2285
+ setIsVisible(true);
2286
+ observer.disconnect();
2129
2287
  }
2130
- callbacksRef.current.onStreamComplete?.(message);
2131
2288
  },
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);
2289
+ { rootMargin: "200px" }
2290
+ );
2291
+ observer.observe(el);
2292
+ return () => observer.disconnect();
2293
+ }, [src]);
2294
+ if (!src) return null;
2295
+ if (isResolvingRag) {
2296
+ return /* @__PURE__ */ jsx(
2297
+ "span",
2298
+ {
2299
+ className: cn("payman-v2-md-image", "payman-v2-md-image-resolving"),
2300
+ children: /* @__PURE__ */ jsxs("span", { className: "payman-v2-md-image-resolving-inner", children: [
2301
+ /* @__PURE__ */ jsx(Loader2, { className: "payman-v2-md-image-loading", "aria-hidden": true }),
2302
+ /* @__PURE__ */ jsx("span", { children: "Loading image" }),
2303
+ /* @__PURE__ */ jsx("span", { children: "Reference image" })
2304
+ ] })
2305
+ }
2306
+ );
2307
+ }
2308
+ if (hasError) {
2309
+ return /* @__PURE__ */ jsxs("span", { className: cn("payman-v2-md-image", "payman-v2-md-image-error"), children: [
2310
+ /* @__PURE__ */ jsx(ImageOff, { "aria-hidden": true }),
2311
+ /* @__PURE__ */ jsx("span", { children: "Unable to load image" }),
2312
+ alt ? /* @__PURE__ */ jsx("span", { children: alt }) : null,
2313
+ retryCount < 3 ? /* @__PURE__ */ jsx(
2314
+ "button",
2315
+ {
2316
+ type: "button",
2317
+ className: "payman-v2-md-image-error-retry",
2318
+ onClick: () => {
2319
+ setHasError(false);
2320
+ setRetryCount((c) => c + 1);
2321
+ },
2322
+ children: "Retry"
2323
+ }
2324
+ ) : null
2325
+ ] });
2326
+ }
2327
+ const imgSrc = retryCount > 0 ? `${src}${src.includes("?") ? "&" : "?"}_r=${retryCount}` : src;
2328
+ return /* @__PURE__ */ jsx("span", { ref: sentinelRef, className: "payman-v2-md-image", children: isVisible ? /* @__PURE__ */ jsxs(
2329
+ "button",
2330
+ {
2331
+ type: "button",
2332
+ className: "payman-v2-md-image-button",
2333
+ onClick: () => {
2334
+ if (isLoaded && src) onImageClick?.(src, alt || "Image");
2136
2335
  },
2137
- onSessionIdChange: (sessionId) => {
2138
- sentryCtxRef.current.sessionId = sessionId;
2139
- callbacksRef.current.onSessionIdChange?.(sessionId);
2336
+ disabled: !isLoaded,
2337
+ "aria-busy": !isLoaded,
2338
+ style: {
2339
+ ...frameStyle,
2340
+ ...!isLoaded ? { minHeight: "10rem" } : {}
2140
2341
  },
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);
2342
+ children: [
2343
+ !isLoaded && /* @__PURE__ */ jsxs("span", { className: "payman-v2-md-image-placeholder", children: [
2344
+ /* @__PURE__ */ jsx(
2345
+ Loader2,
2346
+ {
2347
+ className: "payman-v2-md-image-loading",
2348
+ "aria-hidden": true
2349
+ }
2350
+ ),
2351
+ /* @__PURE__ */ jsx("span", { children: "Loading image\u2026" })
2352
+ ] }),
2353
+ /* @__PURE__ */ jsx(
2354
+ "img",
2355
+ {
2356
+ src: imgSrc,
2357
+ alt: alt || "",
2358
+ className: "payman-v2-md-image-img",
2359
+ style: {
2360
+ ...imgStyle,
2361
+ opacity: isLoaded ? 1 : 0
2362
+ },
2363
+ onLoad: () => {
2364
+ setHasError(false);
2365
+ setIsLoaded(true);
2366
+ },
2367
+ onError: () => {
2368
+ setIsLoaded(false);
2369
+ setHasError(true);
2370
+ }
2371
+ }
2372
+ ),
2373
+ 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
2374
+ ]
2375
+ }
2376
+ ) : /* @__PURE__ */ jsx(
2377
+ "span",
2378
+ {
2379
+ className: "payman-v2-md-image-placeholder",
2380
+ style: { ...frameStyle, minHeight: "10rem" },
2381
+ children: /* @__PURE__ */ jsx("span", { children: "Image" })
2382
+ }
2383
+ ) });
2384
+ }
2385
+ function buildComponents(onImageClick, isResolvingImages) {
2386
+ return {
2387
+ p: ({ children }) => /* @__PURE__ */ jsx("p", { children }),
2388
+ code: ({ children }) => /* @__PURE__ */ jsx("code", { children }),
2389
+ pre: ({ children }) => /* @__PURE__ */ jsx("div", { className: "payman-v2-markdown-pre", children: /* @__PURE__ */ jsx("pre", { children }) }),
2390
+ ul: ({ children }) => /* @__PURE__ */ jsx("ul", { children }),
2391
+ ol: ({ children }) => /* @__PURE__ */ jsx("ol", { children }),
2392
+ li: ({ children }) => /* @__PURE__ */ jsx("li", { children }),
2393
+ h1: ({ children }) => /* @__PURE__ */ jsx("h1", { children }),
2394
+ h2: ({ children }) => /* @__PURE__ */ jsx("h2", { children }),
2395
+ h3: ({ children }) => /* @__PURE__ */ jsx("h3", { children }),
2396
+ strong: ({ children }) => /* @__PURE__ */ jsx("strong", { children }),
2397
+ em: ({ children }) => /* @__PURE__ */ jsx("em", { children }),
2398
+ blockquote: ({ children }) => /* @__PURE__ */ jsx("blockquote", { children }),
2399
+ hr: () => /* @__PURE__ */ jsx("hr", {}),
2400
+ a: ({ href, children }) => /* @__PURE__ */ jsx("a", { href, target: "_blank", rel: "noopener noreferrer", children }),
2401
+ img: ({ src, alt }) => /* @__PURE__ */ jsx(
2402
+ MarkdownImageV2,
2403
+ {
2404
+ src: typeof src === "string" ? src : void 0,
2405
+ alt: typeof alt === "string" ? alt : void 0,
2406
+ isResolving: isResolvingImages,
2407
+ onImageClick
2408
+ }
2409
+ ),
2410
+ table: ({ children }) => /* @__PURE__ */ jsx("div", { className: "payman-v2-markdown-table-wrapper", children: /* @__PURE__ */ jsx("table", { className: "payman-v2-markdown-table", children }) }),
2411
+ thead: ({ children }) => /* @__PURE__ */ jsx("thead", { className: "payman-v2-markdown-thead", children }),
2412
+ tbody: ({ children }) => /* @__PURE__ */ jsx("tbody", { className: "payman-v2-markdown-tbody", children }),
2413
+ th: ({ children }) => /* @__PURE__ */ jsx("th", { className: "payman-v2-markdown-th", children }),
2414
+ td: ({ children }) => /* @__PURE__ */ jsx("td", { className: "payman-v2-markdown-td", children })
2415
+ };
2416
+ }
2417
+ function MarkdownRendererV2({
2418
+ content,
2419
+ isStreaming,
2420
+ isResolvingImages,
2421
+ onImageClick
2422
+ }) {
2423
+ const components = useMemo(
2424
+ () => buildComponents(onImageClick, isResolvingImages),
2425
+ [onImageClick, isResolvingImages]
2426
+ );
2427
+ return /* @__PURE__ */ jsx(
2428
+ "div",
2429
+ {
2430
+ className: cn(
2431
+ "payman-v2-markdown",
2432
+ isStreaming && "payman-v2-streaming-cursor"
2433
+ ),
2434
+ children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components, children: content })
2435
+ }
2436
+ );
2437
+ }
2438
+ var CURSOR_MESSAGES = [
2439
+ "Analyzing",
2440
+ "Processing",
2441
+ "Calculating",
2442
+ "Reviewing",
2443
+ "Verifying",
2444
+ "Assessing",
2445
+ "Evaluating",
2446
+ "Checking",
2447
+ "Planning",
2448
+ "Updating",
2449
+ "Validating",
2450
+ "Monitoring",
2451
+ "Optimizing",
2452
+ "Reconciling",
2453
+ "Forecasting",
2454
+ "Inspecting",
2455
+ "Organizing",
2456
+ "Sorting",
2457
+ "Scanning",
2458
+ "Balancing",
2459
+ "Summarizing",
2460
+ "Predicting",
2461
+ "Comparing",
2462
+ "Tracking",
2463
+ "Adjusting",
2464
+ "Examining",
2465
+ "Mapping",
2466
+ "Modeling",
2467
+ "Reporting",
2468
+ "Confirming"
2469
+ ];
2470
+ var FINAL_CURSOR_MESSAGE = "Finishing up";
2471
+ function parseThinkingContent(content) {
2472
+ const lines = content.split("\n");
2473
+ const out = [];
2474
+ for (const raw of lines) {
2475
+ const line = raw.trim();
2476
+ if (!line) continue;
2477
+ const stmt = line.match(/^\*\*(.+)\*\*$/);
2478
+ if (stmt) {
2479
+ out.push({ type: "statement", text: stmt[1].trim() });
2480
+ continue;
2481
+ }
2482
+ if (line.startsWith("\u2713 ")) {
2483
+ out.push({
2484
+ type: "status",
2485
+ variant: "success",
2486
+ text: line.slice(2).trim()
2487
+ });
2488
+ continue;
2489
+ }
2490
+ if (line.startsWith("\u2717 ")) {
2491
+ out.push({
2492
+ type: "status",
2493
+ variant: "error",
2494
+ text: line.slice(2).trim()
2495
+ });
2496
+ continue;
2497
+ }
2498
+ out.push({ type: "detail", text: line });
2499
+ }
2500
+ return out;
2501
+ }
2502
+ function ThinkingBlockV2({
2503
+ content,
2504
+ isStreaming,
2505
+ durationSec
2506
+ }) {
2507
+ const [open, setOpen] = useState(true);
2508
+ const [cursorIdx, setCursorIdx] = useState(0);
2509
+ const prevStreaming = useRef(isStreaming);
2510
+ const parsed = useMemo(() => parseThinkingContent(content), [content]);
2511
+ const isFinalizingPhase = useMemo(() => {
2512
+ const statements = parsed.filter(
2513
+ (l) => l.type === "statement"
2514
+ );
2515
+ return statements.length > 0 && statements[statements.length - 1].text === "Finalizing";
2516
+ }, [parsed]);
2517
+ useEffect(() => {
2518
+ if (prevStreaming.current && !isStreaming) {
2519
+ setOpen(false);
2520
+ }
2521
+ prevStreaming.current = isStreaming;
2522
+ }, [isStreaming]);
2523
+ useEffect(() => {
2524
+ if (!isStreaming || isFinalizingPhase) return;
2525
+ const id = window.setInterval(() => {
2526
+ setCursorIdx((i) => (i + 1) % CURSOR_MESSAGES.length);
2527
+ }, 4e3);
2528
+ return () => window.clearInterval(id);
2529
+ }, [isStreaming, isFinalizingPhase]);
2530
+ const headerLabel = isStreaming ? /* @__PURE__ */ jsx("span", { className: "payman-v2-thinking-shimmer", children: "Working on it\u2026" }) : durationSec !== void 0 ? /* @__PURE__ */ jsxs("span", { children: [
2531
+ "Thought for ",
2532
+ durationSec,
2533
+ "s"
2534
+ ] }) : /* @__PURE__ */ jsx("span", { children: "Thought" });
2535
+ const cursorKey = isFinalizingPhase ? "finalizing" : String(cursorIdx);
2536
+ const cursorText = isFinalizingPhase ? FINAL_CURSOR_MESSAGE : CURSOR_MESSAGES[cursorIdx];
2537
+ return /* @__PURE__ */ jsxs("div", { className: "payman-v2-thinking", children: [
2538
+ /* @__PURE__ */ jsxs(
2539
+ "button",
2540
+ {
2541
+ type: "button",
2542
+ className: "payman-v2-thinking-toggle",
2543
+ onClick: () => setOpen((o) => !o),
2544
+ "aria-expanded": open,
2545
+ children: [
2546
+ /* @__PURE__ */ jsx(
2547
+ ChevronRight,
2548
+ {
2549
+ className: cn(
2550
+ "payman-v2-thinking-chevron",
2551
+ open && "payman-v2-thinking-chevron-open"
2552
+ ),
2553
+ "aria-hidden": true
2554
+ }
2555
+ ),
2556
+ headerLabel
2557
+ ]
2558
+ }
2559
+ ),
2560
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-thinking-border", children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: open && /* @__PURE__ */ jsx(
2561
+ motion.div,
2562
+ {
2563
+ className: "payman-v2-thinking-content",
2564
+ initial: { height: 0, opacity: 0 },
2565
+ animate: { height: "auto", opacity: 1 },
2566
+ exit: { height: 0, opacity: 0 },
2567
+ transition: { duration: 0.2, ease: "easeInOut" },
2568
+ style: { overflow: "hidden" },
2569
+ children: /* @__PURE__ */ jsxs("div", { children: [
2570
+ parsed.map((item, i) => {
2571
+ if (item.type === "statement") {
2572
+ return /* @__PURE__ */ jsx(
2573
+ "div",
2574
+ {
2575
+ className: "payman-v2-thinking-statement",
2576
+ children: item.text
2577
+ },
2578
+ i
2579
+ );
2580
+ }
2581
+ if (item.type === "detail") {
2582
+ return /* @__PURE__ */ jsx(
2583
+ "div",
2584
+ {
2585
+ className: "payman-v2-thinking-detail",
2586
+ children: item.text
2587
+ },
2588
+ i
2589
+ );
2590
+ }
2591
+ return /* @__PURE__ */ jsx(
2592
+ "span",
2593
+ {
2594
+ className: cn(
2595
+ "payman-v2-thinking-status",
2596
+ item.variant === "success" ? "payman-v2-thinking-status-success" : "payman-v2-thinking-status-error"
2597
+ ),
2598
+ children: item.text
2599
+ },
2600
+ i
2601
+ );
2602
+ }),
2603
+ isStreaming && /* @__PURE__ */ jsxs("div", { className: "payman-v2-thinking-cursor", children: [
2604
+ /* @__PURE__ */ jsx(
2605
+ "span",
2606
+ {
2607
+ className: "payman-v2-thinking-cursor-bar",
2608
+ "aria-hidden": true
2609
+ }
2610
+ ),
2611
+ /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
2612
+ motion.span,
2613
+ {
2614
+ className: "payman-v2-thinking-cursor-label",
2615
+ initial: { opacity: 0, y: 4 },
2616
+ animate: { opacity: 1, y: 0 },
2617
+ exit: { opacity: 0, y: -4 },
2618
+ transition: { duration: 0.2 },
2619
+ children: cursorText
2620
+ },
2621
+ cursorKey
2622
+ ) })
2623
+ ] })
2624
+ ] })
2625
+ },
2626
+ "thinking-content"
2627
+ ) }) })
2628
+ ] });
2629
+ }
2630
+ var THINKING_SPEED = {
2631
+ normal: [6, 8],
2632
+ fast: 1,
2633
+ punctuation: [20, 30],
2634
+ newline: [12, 18],
2635
+ idle: 30
2636
+ };
2637
+ var RESPONSE_SPEED = {
2638
+ normal: [4, 8],
2639
+ fast: 1,
2640
+ punctuation: [20, 30],
2641
+ newline: [10, 15],
2642
+ idle: 30
2643
+ };
2644
+ function charDelay(char, speed) {
2645
+ if (char === "*") return speed.fast;
2646
+ if (char === "\n") return speed.newline[0] + Math.random() * speed.newline[1];
2647
+ if (".!?,;:".includes(char))
2648
+ return speed.punctuation[0] + Math.random() * speed.punctuation[1];
2649
+ return speed.normal[0] + Math.random() * speed.normal[1];
2650
+ }
2651
+ function useTypingEffect(targetText, enabled, speed = RESPONSE_SPEED, initialDisplayedText) {
2652
+ const [displayedText, setDisplayedText] = useState("");
2653
+ const displayedRef = useRef("");
2654
+ const targetRef = useRef(targetText);
2655
+ const enabledRef = useRef(enabled);
2656
+ const initialDisplayedRef = useRef(initialDisplayedText);
2657
+ const timerRef = useRef(null);
2658
+ const runningRef = useRef(false);
2659
+ targetRef.current = targetText;
2660
+ enabledRef.current = enabled;
2661
+ initialDisplayedRef.current = initialDisplayedText;
2662
+ useEffect(() => {
2663
+ if (!enabled) {
2664
+ if (timerRef.current) {
2665
+ clearTimeout(timerRef.current);
2666
+ timerRef.current = null;
2667
+ }
2668
+ runningRef.current = false;
2669
+ displayedRef.current = targetText;
2670
+ setDisplayedText(targetText);
2671
+ return;
2672
+ }
2673
+ if (displayedRef.current.length === 0 && initialDisplayedRef.current && targetRef.current.startsWith(initialDisplayedRef.current)) {
2674
+ displayedRef.current = initialDisplayedRef.current;
2675
+ setDisplayedText(initialDisplayedRef.current);
2676
+ }
2677
+ if (runningRef.current) return;
2678
+ runningRef.current = true;
2679
+ const tick = () => {
2680
+ if (!enabledRef.current) {
2681
+ runningRef.current = false;
2682
+ return;
2683
+ }
2684
+ if (displayedRef.current.length < targetRef.current.length) {
2685
+ const nextChar = targetRef.current[displayedRef.current.length];
2686
+ displayedRef.current += nextChar;
2687
+ setDisplayedText(displayedRef.current);
2688
+ const delay = charDelay(nextChar, speed);
2689
+ timerRef.current = setTimeout(tick, delay);
2690
+ } else {
2691
+ timerRef.current = setTimeout(tick, speed.idle);
2692
+ }
2693
+ };
2694
+ tick();
2695
+ return () => {
2696
+ if (timerRef.current) {
2697
+ clearTimeout(timerRef.current);
2698
+ timerRef.current = null;
2699
+ }
2700
+ runningRef.current = false;
2701
+ };
2702
+ }, [enabled]);
2703
+ const isTyping = enabled && displayedRef.current.length < targetRef.current.length;
2704
+ return {
2705
+ displayedText: enabled ? displayedText : targetText,
2706
+ isTyping
2707
+ };
2708
+ }
2709
+ var INITIAL_THINKING_PLACEHOLDER = [
2710
+ "**Getting things ready**",
2711
+ "Putting things together"
2712
+ ].join("\n");
2713
+ function getFormattedThinking(message, includeInitialPlaceholder = false) {
2714
+ const plainThinkingText = message.allThinkingText || message.activeThinkingText || "";
2715
+ const baseText = message.formattedThinkingText || buildFormattedThinking(message.steps, plainThinkingText);
2716
+ if (includeInitialPlaceholder && baseText) {
2717
+ return INITIAL_THINKING_PLACEHOLDER + "\n" + baseText;
2718
+ }
2719
+ if (includeInitialPlaceholder) {
2720
+ return INITIAL_THINKING_PLACEHOLDER;
2721
+ }
2722
+ return baseText;
2723
+ }
2724
+ function AssistantMessageV2({
2725
+ message,
2726
+ onImageClick,
2727
+ onExecutionTraceClick,
2728
+ actions
2729
+ }) {
2730
+ const [copied, setCopied] = useState(false);
2731
+ const [toast, setToast] = useState(null);
2732
+ const copyResetTimerRef = useRef(null);
2733
+ const toastTimerRef = useRef(null);
2734
+ const showCopyAction = actions?.copy ?? true;
2735
+ const showTraceAction = (actions?.trace ?? true) && !!onExecutionTraceClick;
2736
+ const hasEverStreamed = useRef(!!message.isStreaming);
2737
+ const hasShownInitialThinking = useRef(
2738
+ message.streamProgress === "processing"
2739
+ );
2740
+ if (message.isStreaming) hasEverStreamed.current = true;
2741
+ useEffect(() => {
2742
+ return () => {
2743
+ if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
2744
+ if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
2745
+ };
2746
+ }, []);
2747
+ const rawResponseContent = (() => {
2748
+ const raw = message.isStreaming ? message.streamingContent || message.content : message.content;
2749
+ if (!raw) return "";
2750
+ return raw.replace(/\\n/g, "\n");
2751
+ })();
2752
+ const hasReadyStreamPhase = message.streamProgress === "processing" || Boolean(message.steps?.length) || Boolean(message.allThinkingText) || Boolean(message.activeThinkingText) || Boolean(rawResponseContent);
2753
+ if (hasReadyStreamPhase && !message.isError) {
2754
+ hasShownInitialThinking.current = true;
2755
+ }
2756
+ const includeInitialPlaceholder = hasShownInitialThinking.current && !message.isError;
2757
+ const rawThinkingContent = useMemo(
2758
+ () => getFormattedThinking(message, includeInitialPlaceholder),
2759
+ [message, includeInitialPlaceholder]
2760
+ );
2761
+ const isThinkingStreaming = !!message.isStreaming && !rawResponseContent && !message.isError;
2762
+ const { displayedText: thinkingContent } = useTypingEffect(
2763
+ rawThinkingContent,
2764
+ hasEverStreamed.current && isThinkingStreaming,
2765
+ THINKING_SPEED,
2766
+ includeInitialPlaceholder ? INITIAL_THINKING_PLACEHOLDER : void 0
2767
+ );
2768
+ const hasThinkingContent = Boolean(thinkingContent);
2769
+ const showThinkingBlock = hasThinkingContent || isThinkingStreaming;
2770
+ const showLegacyThinkingPhase = !!message.isStreaming && !message.isError && !rawResponseContent && message.streamProgress === "started";
2771
+ const responseTypingEnabled = hasEverStreamed.current && Boolean(rawResponseContent) && !message.isError;
2772
+ const { displayedText: displayContent, isTyping: isResponseTyping } = useTypingEffect(rawResponseContent, responseTypingEnabled, RESPONSE_SPEED);
2773
+ const thinkingDuration = (() => {
2774
+ if (!message.steps || message.steps.length === 0) return void 0;
2775
+ const first = message.steps[0];
2776
+ const last = message.steps[message.steps.length - 1];
2777
+ if (first.timestamp && last.timestamp) {
2778
+ return Math.round((last.timestamp - first.timestamp) / 1e3);
2779
+ }
2780
+ const total = message.steps.reduce((sum, s) => sum + (s.elapsedMs || 0), 0);
2781
+ return total > 0 ? Math.round(total / 1e3) : void 0;
2782
+ })();
2783
+ if (message.isError && !displayContent && !hasThinkingContent) {
2784
+ return /* @__PURE__ */ jsx("div", { className: "payman-v2-assistant-msg payman-v2-fade-in", children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-error", children: [
2785
+ /* @__PURE__ */ jsx(
2786
+ AlertCircle,
2787
+ {
2788
+ className: "payman-v2-assistant-msg-error-icon",
2789
+ style: { width: 16, height: 16 }
2790
+ }
2791
+ ),
2792
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-error-text", children: message.errorDetails || "Something went wrong. Please try again." }) })
2793
+ ] }) });
2794
+ }
2795
+ if (showLegacyThinkingPhase) {
2796
+ 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" }) });
2797
+ }
2798
+ const showToast = (label, tone) => {
2799
+ if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
2800
+ setToast({ label, tone });
2801
+ toastTimerRef.current = setTimeout(() => setToast(null), 1800);
2802
+ };
2803
+ const handleCopy = async () => {
2804
+ try {
2805
+ if (!navigator.clipboard?.writeText) {
2806
+ throw new Error("Clipboard unavailable");
2807
+ }
2808
+ await navigator.clipboard.writeText(displayContent);
2809
+ if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
2810
+ setCopied(true);
2811
+ copyResetTimerRef.current = setTimeout(() => setCopied(false), 1800);
2812
+ showToast("Copied to clipboard", "success");
2813
+ } catch {
2814
+ setCopied(false);
2815
+ showToast("Could not copy", "error");
2816
+ }
2817
+ };
2818
+ const handleTrace = () => {
2819
+ onExecutionTraceClick?.({
2820
+ message,
2821
+ tracingData: message.tracingData,
2822
+ executionId: message.executionId
2823
+ });
2824
+ };
2825
+ const hasPartialError = message.isError && displayContent;
2826
+ const isDone = !message.isStreaming && displayContent && !hasPartialError && !isResponseTyping;
2827
+ const hasVisibleDoneActions = showCopyAction || showTraceAction;
2828
+ const isCancelled = message.isCancelled;
2829
+ const toastPortal = typeof document !== "undefined" ? createPortal(
2830
+ /* @__PURE__ */ jsx(AnimatePresence, { children: toast && /* @__PURE__ */ jsx(
2831
+ motion.div,
2832
+ {
2833
+ initial: { opacity: 0, y: -18, scale: 0.96 },
2834
+ animate: { opacity: 1, y: 0, scale: 1 },
2835
+ exit: { opacity: 0, y: -12, scale: 0.96 },
2836
+ transition: {
2837
+ type: "spring",
2838
+ stiffness: 360,
2839
+ damping: 26,
2840
+ mass: 0.7
2841
+ },
2842
+ className: "payman-v2-toast",
2843
+ role: "status",
2844
+ "aria-live": "polite",
2845
+ children: /* @__PURE__ */ jsxs(
2846
+ "div",
2847
+ {
2848
+ className: cn(
2849
+ "payman-v2-toast-inner",
2850
+ toast.tone === "success" ? "payman-v2-toast-success" : "payman-v2-toast-error"
2851
+ ),
2852
+ children: [
2853
+ toast.tone === "success" ? /* @__PURE__ */ jsx(
2854
+ Check,
2855
+ {
2856
+ className: "h-4 w-4",
2857
+ style: { color: "#059669" }
2858
+ }
2859
+ ) : /* @__PURE__ */ jsx(
2860
+ AlertCircle,
2861
+ {
2862
+ className: "h-4 w-4",
2863
+ style: { color: "#ef4444" }
2864
+ }
2865
+ ),
2866
+ /* @__PURE__ */ jsx("span", { children: toast.label })
2867
+ ]
2868
+ }
2869
+ )
2870
+ }
2871
+ ) }),
2872
+ document.body
2873
+ ) : null;
2874
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2875
+ toastPortal,
2876
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg payman-v2-fade-in", children: [
2877
+ showThinkingBlock && /* @__PURE__ */ jsx(
2878
+ ThinkingBlockV2,
2879
+ {
2880
+ content: thinkingContent,
2881
+ isStreaming: isThinkingStreaming,
2882
+ durationSec: thinkingDuration
2883
+ }
2884
+ ),
2885
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-assistant-msg-content-area", children: displayContent ? /* @__PURE__ */ jsx(
2886
+ MarkdownRendererV2,
2887
+ {
2888
+ content: displayContent,
2889
+ isStreaming: message.isStreaming && !isCancelled || isResponseTyping,
2890
+ isResolvingImages: message.isResolvingImages,
2891
+ onImageClick
2892
+ }
2893
+ ) : !isThinkingStreaming && !hasThinkingContent ? /* @__PURE__ */ jsx("span", { className: "payman-v2-assistant-msg-placeholder", children: "..." }) : null }),
2894
+ isCancelled && message.isStreaming && /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-paused", children: [
2895
+ /* @__PURE__ */ jsx(
2896
+ WifiOff,
2897
+ {
2898
+ style: { width: 14, height: 14, color: "rgba(217, 119, 6, 0.7)", flexShrink: 0 }
2899
+ }
2900
+ ),
2901
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-paused-text", children: "Connection slow - resuming\u2026" })
2902
+ ] }),
2903
+ hasPartialError && /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-partial-error", children: [
2904
+ /* @__PURE__ */ jsx(
2905
+ AlertCircle,
2906
+ {
2907
+ className: "payman-v2-assistant-msg-error-icon",
2908
+ style: { width: 16, height: 16 }
2909
+ }
2910
+ ),
2911
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-error-text", children: message.errorDetails || "The response was interrupted." }) })
2912
+ ] }),
2913
+ isDone && hasVisibleDoneActions && /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-actions", children: [
2914
+ showCopyAction && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Copy", children: /* @__PURE__ */ jsx(
2915
+ "button",
2916
+ {
2917
+ onClick: () => void handleCopy(),
2918
+ className: cn(
2919
+ "payman-v2-assistant-msg-action-btn",
2920
+ copied && "payman-v2-assistant-msg-action-btn-active"
2921
+ ),
2922
+ "aria-label": "Copy",
2923
+ children: copied ? /* @__PURE__ */ jsx(Check, { style: { width: 16, height: 16 } }) : /* @__PURE__ */ jsx(Copy, { style: { width: 16, height: 16 } })
2924
+ }
2925
+ ) }),
2926
+ showTraceAction && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Trace", children: /* @__PURE__ */ jsx(
2927
+ "button",
2928
+ {
2929
+ onClick: handleTrace,
2930
+ className: "payman-v2-assistant-msg-action-btn",
2931
+ "aria-label": "Trace response",
2932
+ children: /* @__PURE__ */ jsx(SearchCode, { style: { width: 16, height: 16 } })
2933
+ }
2934
+ ) })
2935
+ ] })
2936
+ ] })
2937
+ ] });
2938
+ }
2939
+ var DEFAULT_MAX_LENGTH2 = 6;
2940
+ var MAX_SUPPORTED_LENGTH2 = 12;
2941
+ var AUTO_FOCUS_DELAY_MS2 = 250;
2942
+ function OtpInputV2({
2943
+ value,
2944
+ onChange,
2945
+ maxLength,
2946
+ disabled = false,
2947
+ error = false
2948
+ }) {
2949
+ const inputRefs = useRef([]);
2950
+ const safeMaxLength = Number.isInteger(maxLength) && maxLength > 0 ? Math.min(maxLength, MAX_SUPPORTED_LENGTH2) : DEFAULT_MAX_LENGTH2;
2951
+ const digits = value.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
2952
+ useEffect(() => {
2953
+ if (disabled) return;
2954
+ const timer = window.setTimeout(() => {
2955
+ inputRefs.current[0]?.focus();
2956
+ }, AUTO_FOCUS_DELAY_MS2);
2957
+ return () => window.clearTimeout(timer);
2958
+ }, [disabled]);
2959
+ const focusInput = (index) => {
2960
+ if (index >= 0 && index < safeMaxLength) {
2961
+ inputRefs.current[index]?.focus();
2962
+ }
2963
+ };
2964
+ const updateValue = (newDigits) => {
2965
+ onChange(newDigits.join("").slice(0, safeMaxLength));
2966
+ };
2967
+ const handleChange = (index, char) => {
2968
+ if (char && !/^\d$/.test(char)) return;
2969
+ const newDigits = [...digits];
2970
+ newDigits[index] = char;
2971
+ updateValue(newDigits);
2972
+ if (char && index < safeMaxLength - 1) focusInput(index + 1);
2973
+ };
2974
+ const handleKeyDown = (index, e) => {
2975
+ if (e.key === "Enter") {
2976
+ e.preventDefault();
2977
+ return;
2978
+ }
2979
+ if (e.key === "Backspace") {
2980
+ e.preventDefault();
2981
+ if (digits[index]) {
2982
+ const newDigits = [...digits];
2983
+ newDigits[index] = "";
2984
+ updateValue(newDigits);
2985
+ } else if (index > 0) {
2986
+ const newDigits = [...digits];
2987
+ newDigits[index - 1] = "";
2988
+ updateValue(newDigits);
2989
+ focusInput(index - 1);
2990
+ }
2991
+ return;
2992
+ }
2993
+ if (e.key === "ArrowLeft") {
2994
+ e.preventDefault();
2995
+ focusInput(index - 1);
2996
+ } else if (e.key === "ArrowRight") {
2997
+ e.preventDefault();
2998
+ focusInput(index + 1);
2999
+ }
3000
+ };
3001
+ const handlePaste = (e) => {
3002
+ e.preventDefault();
3003
+ const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, safeMaxLength);
3004
+ if (!pasted) return;
3005
+ const newDigits = pasted.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
3006
+ updateValue(newDigits);
3007
+ focusInput(Math.min(pasted.length, safeMaxLength - 1));
3008
+ };
3009
+ return /* @__PURE__ */ jsx("div", { className: cn("payman-v2-otp", error && "payman-v2-shake"), children: digits.map((digit, i) => /* @__PURE__ */ jsx(
3010
+ "input",
3011
+ {
3012
+ ref: (el) => {
3013
+ inputRefs.current[i] = el;
3014
+ },
3015
+ type: "text",
3016
+ inputMode: "numeric",
3017
+ maxLength: 1,
3018
+ value: digit,
3019
+ disabled,
3020
+ onChange: (e) => handleChange(i, e.target.value.slice(-1)),
3021
+ onKeyDown: (e) => handleKeyDown(i, e),
3022
+ onPaste: handlePaste,
3023
+ onFocus: (e) => e.target.select(),
3024
+ "aria-label": `Digit ${i + 1}`,
3025
+ className: cn(
3026
+ "payman-v2-otp-digit",
3027
+ digit && "payman-v2-otp-digit-filled",
3028
+ error && "payman-v2-otp-digit-error"
3029
+ )
3030
+ },
3031
+ i
3032
+ )) });
3033
+ }
3034
+ var RESEND_COOLDOWN_S = 30;
3035
+ var OTP_LEN = 6;
3036
+ function VerificationCardV2({
3037
+ messageId,
3038
+ action,
3039
+ status,
3040
+ onApprove,
3041
+ onReject,
3042
+ onResend
3043
+ }) {
3044
+ const [otp, setOtp] = useState("");
3045
+ const [otpErrored, setOtpErrored] = useState(false);
3046
+ const [resendSec, setResendSec] = useState(0);
3047
+ const lastSubmittedRef = useRef(null);
3048
+ const resendTimerRef = useRef(void 0);
3049
+ useEffect(() => {
3050
+ if (status !== "error") {
3051
+ setOtpErrored(false);
3052
+ return;
3053
+ }
3054
+ setOtpErrored(true);
3055
+ const t = window.setTimeout(() => {
3056
+ setOtp("");
3057
+ setOtpErrored(false);
3058
+ lastSubmittedRef.current = null;
3059
+ }, 600);
3060
+ return () => window.clearTimeout(t);
3061
+ }, [status]);
3062
+ useEffect(() => {
3063
+ if (otp.length < OTP_LEN) {
3064
+ lastSubmittedRef.current = null;
3065
+ }
3066
+ }, [otp]);
3067
+ useEffect(() => {
3068
+ if (otp.length !== OTP_LEN || !/^\d+$/.test(otp) || status !== "pending") {
3069
+ return;
3070
+ }
3071
+ if (lastSubmittedRef.current === otp) return;
3072
+ lastSubmittedRef.current = otp;
3073
+ void onApprove(messageId, otp);
3074
+ }, [messageId, onApprove, otp, status]);
3075
+ useEffect(() => {
3076
+ return () => {
3077
+ if (typeof resendTimerRef.current === "number") {
3078
+ window.clearInterval(resendTimerRef.current);
3079
+ }
3080
+ };
3081
+ }, []);
3082
+ const startResendCooldown = useCallback(() => {
3083
+ setResendSec(RESEND_COOLDOWN_S);
3084
+ if (typeof resendTimerRef.current === "number") {
3085
+ window.clearInterval(resendTimerRef.current);
3086
+ }
3087
+ resendTimerRef.current = window.setInterval(() => {
3088
+ setResendSec((s) => {
3089
+ if (s <= 1) {
3090
+ if (typeof resendTimerRef.current === "number") {
3091
+ window.clearInterval(resendTimerRef.current);
3092
+ resendTimerRef.current = void 0;
3093
+ }
3094
+ return 0;
3095
+ }
3096
+ return s - 1;
3097
+ });
3098
+ }, 1e3);
3099
+ }, []);
3100
+ const handleResend = useCallback(async () => {
3101
+ if (resendSec > 0 || status === "verifying") return;
3102
+ await onResend(messageId);
3103
+ startResendCooldown();
3104
+ }, [messageId, onResend, resendSec, startResendCooldown, status]);
3105
+ const handleCancel = useCallback(async () => {
3106
+ await onReject(messageId);
3107
+ }, [messageId, onReject]);
3108
+ const busy = status === "verifying";
3109
+ if (status === "approved" || status === "rejected") {
3110
+ return null;
3111
+ }
3112
+ return /* @__PURE__ */ jsx(
3113
+ motion.div,
3114
+ {
3115
+ className: "payman-v2-verification",
3116
+ initial: { opacity: 0, y: 10 },
3117
+ animate: { opacity: 1, y: 0 },
3118
+ transition: { type: "spring", stiffness: 320, damping: 28 },
3119
+ children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-card", children: [
3120
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-header", children: [
3121
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-header-row", children: [
3122
+ /* @__PURE__ */ jsx(
3123
+ ShieldCheck,
3124
+ {
3125
+ className: "payman-v2-verification-icon",
3126
+ size: 18,
3127
+ strokeWidth: 1.75,
3128
+ "aria-hidden": true
3129
+ }
3130
+ ),
3131
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-verification-title", children: "Verify" }),
3132
+ 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
3133
+ ] }),
3134
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-verification-description", children: "Enter the 6-digit code sent to your phone" }),
3135
+ /* @__PURE__ */ jsx(
3136
+ OtpInputV2,
3137
+ {
3138
+ value: otp,
3139
+ onChange: setOtp,
3140
+ maxLength: OTP_LEN,
3141
+ disabled: busy,
3142
+ error: otpErrored
3143
+ }
3144
+ ),
3145
+ busy ? /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-submitting", children: [
3146
+ /* @__PURE__ */ jsx(
3147
+ motion.span,
3148
+ {
3149
+ "aria-hidden": true,
3150
+ style: { display: "inline-flex" },
3151
+ animate: { rotate: 360 },
3152
+ transition: {
3153
+ repeat: Infinity,
3154
+ duration: 0.7,
3155
+ ease: "linear"
3156
+ },
3157
+ children: /* @__PURE__ */ jsx(Loader2, { size: 14, strokeWidth: 2 })
3158
+ }
3159
+ ),
3160
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-verification-submitting-text", children: "Verifying..." })
3161
+ ] }) : null
3162
+ ] }),
3163
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-actions", children: [
3164
+ /* @__PURE__ */ jsxs(
3165
+ "button",
3166
+ {
3167
+ type: "button",
3168
+ className: "payman-v2-verification-resend-btn",
3169
+ disabled: busy || resendSec > 0,
3170
+ onClick: () => void handleResend(),
3171
+ children: [
3172
+ /* @__PURE__ */ jsx(RotateCcw, { size: 12, strokeWidth: 2, "aria-hidden": true }),
3173
+ resendSec > 0 ? `Resend (${resendSec}s)` : "Resend"
3174
+ ]
3175
+ }
3176
+ ),
3177
+ /* @__PURE__ */ jsx(
3178
+ "button",
3179
+ {
3180
+ type: "button",
3181
+ className: "payman-v2-verification-cancel-btn",
3182
+ disabled: busy,
3183
+ onClick: () => void handleCancel(),
3184
+ children: "Cancel"
3185
+ }
3186
+ )
3187
+ ] })
3188
+ ] })
3189
+ }
3190
+ );
3191
+ }
3192
+ var SCROLL_THRESHOLD2 = 100;
3193
+ var MessageListV2 = forwardRef(
3194
+ function MessageListV22({
3195
+ messages,
3196
+ isStreaming: _isStreaming = false,
3197
+ onEditUserMessage,
3198
+ onRetryUserMessage,
3199
+ onImageClick,
3200
+ onExecutionTraceClick,
3201
+ messageActions,
3202
+ retryDisabled = false,
3203
+ userAction,
3204
+ onApproveAction,
3205
+ onRejectAction,
3206
+ onResendAction
3207
+ }, ref) {
3208
+ const scrollRef = useRef(null);
3209
+ const scrollInnerRef = useRef(null);
3210
+ const isNearBottomRef = useRef(true);
3211
+ const [showScrollBtn, setShowScrollBtn] = useState(false);
3212
+ const prevCountRef = useRef(messages.length);
3213
+ const pauseStickUntilUserMessageRef = useRef(false);
3214
+ const followingBottomRef = useRef(true);
3215
+ const isProgrammaticScrollRef = useRef(false);
3216
+ const getDistanceFromBottom = useCallback(() => {
3217
+ const el = scrollRef.current;
3218
+ if (!el) return 0;
3219
+ return el.scrollHeight - el.scrollTop - el.clientHeight;
3220
+ }, []);
3221
+ const scrollToBottom = useCallback(
3222
+ (behavior = "smooth") => {
3223
+ const el = scrollRef.current;
3224
+ if (!el) return;
3225
+ isProgrammaticScrollRef.current = true;
3226
+ pauseStickUntilUserMessageRef.current = false;
3227
+ followingBottomRef.current = true;
3228
+ el.scrollTo({ top: el.scrollHeight, behavior });
3229
+ const clear = () => {
3230
+ isProgrammaticScrollRef.current = false;
3231
+ };
3232
+ if (behavior === "instant") {
3233
+ requestAnimationFrame(clear);
3234
+ } else {
3235
+ setTimeout(clear, 400);
3236
+ }
3237
+ },
3238
+ []
3239
+ );
3240
+ useImperativeHandle(
3241
+ ref,
3242
+ () => ({
3243
+ scrollToBottom: (behavior = "smooth") => {
3244
+ isNearBottomRef.current = true;
3245
+ pauseStickUntilUserMessageRef.current = false;
3246
+ followingBottomRef.current = true;
3247
+ setShowScrollBtn(false);
3248
+ scrollToBottom(behavior);
3249
+ }
3250
+ }),
3251
+ [scrollToBottom]
3252
+ );
3253
+ const handleScroll = useCallback(() => {
3254
+ const distance = getDistanceFromBottom();
3255
+ const nearBottom = distance <= SCROLL_THRESHOLD2;
3256
+ isNearBottomRef.current = nearBottom;
3257
+ setShowScrollBtn(!nearBottom);
3258
+ if (isProgrammaticScrollRef.current) return;
3259
+ if (!nearBottom) {
3260
+ followingBottomRef.current = false;
3261
+ pauseStickUntilUserMessageRef.current = true;
3262
+ }
3263
+ }, [getDistanceFromBottom]);
3264
+ useEffect(() => {
3265
+ const prevCount = prevCountRef.current;
3266
+ prevCountRef.current = messages.length;
3267
+ if (messages.length > prevCount) {
3268
+ const last = messages[messages.length - 1];
3269
+ if (last?.role === "user") {
3270
+ pauseStickUntilUserMessageRef.current = false;
3271
+ followingBottomRef.current = true;
3272
+ requestAnimationFrame(() => scrollToBottom());
3273
+ } else if (!pauseStickUntilUserMessageRef.current && followingBottomRef.current) {
3274
+ requestAnimationFrame(() => scrollToBottom("instant"));
3275
+ }
3276
+ }
3277
+ }, [messages.length, scrollToBottom]);
3278
+ useEffect(() => {
3279
+ const lastMsg = messages[messages.length - 1];
3280
+ if (!lastMsg?.isStreaming) return;
3281
+ if (pauseStickUntilUserMessageRef.current) return;
3282
+ if (!followingBottomRef.current) return;
3283
+ const el = scrollRef.current;
3284
+ if (!el) return;
3285
+ isProgrammaticScrollRef.current = true;
3286
+ el.scrollTop = el.scrollHeight;
3287
+ requestAnimationFrame(() => {
3288
+ isProgrammaticScrollRef.current = false;
3289
+ });
3290
+ });
3291
+ useEffect(() => {
3292
+ const inner = scrollInnerRef.current;
3293
+ if (!inner) return;
3294
+ const pinIfFollowing = () => {
3295
+ if (pauseStickUntilUserMessageRef.current) return;
3296
+ if (!followingBottomRef.current) return;
3297
+ const el = scrollRef.current;
3298
+ if (!el) return;
3299
+ isProgrammaticScrollRef.current = true;
3300
+ el.scrollTop = el.scrollHeight;
3301
+ requestAnimationFrame(() => {
3302
+ isProgrammaticScrollRef.current = false;
3303
+ });
3304
+ };
3305
+ const ro = new ResizeObserver(() => {
3306
+ pinIfFollowing();
3307
+ });
3308
+ ro.observe(inner);
3309
+ return () => ro.disconnect();
3310
+ }, []);
3311
+ useEffect(() => {
3312
+ if (messages.length > 0) {
3313
+ setTimeout(() => scrollToBottom("instant"), 50);
3314
+ }
3315
+ }, []);
3316
+ return /* @__PURE__ */ jsxs("div", { className: "payman-v2-message-list", children: [
3317
+ /* @__PURE__ */ jsx(
3318
+ "div",
3319
+ {
3320
+ ref: scrollRef,
3321
+ onScroll: handleScroll,
3322
+ className: "payman-v2-message-scroll payman-v2-scrollbar",
3323
+ children: /* @__PURE__ */ jsxs(
3324
+ "div",
3325
+ {
3326
+ ref: scrollInnerRef,
3327
+ className: "payman-v2-message-scroll-inner",
3328
+ children: [
3329
+ messages.map((message) => /* @__PURE__ */ jsx("div", { children: message.role === "user" ? /* @__PURE__ */ jsx(
3330
+ UserMessageV2,
3331
+ {
3332
+ message,
3333
+ onEdit: onEditUserMessage,
3334
+ onRetry: onRetryUserMessage,
3335
+ retryDisabled,
3336
+ actions: messageActions?.userMessageActions
3337
+ }
3338
+ ) : /* @__PURE__ */ jsx(
3339
+ AssistantMessageV2,
3340
+ {
3341
+ message,
3342
+ onImageClick,
3343
+ onExecutionTraceClick,
3344
+ actions: messageActions?.assistantMessageActions
3345
+ }
3346
+ ) }, message.id)),
3347
+ userAction && userAction.status !== "approved" && userAction.status !== "rejected" && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
3348
+ VerificationCardV2,
3349
+ {
3350
+ messageId: userAction.messageId,
3351
+ action: userAction.action,
3352
+ status: userAction.status,
3353
+ onApprove: onApproveAction ?? (async () => {
3354
+ }),
3355
+ onReject: onRejectAction ?? (async () => {
3356
+ }),
3357
+ onResend: onResendAction ?? (async () => {
3358
+ })
3359
+ }
3360
+ ) })
3361
+ ]
3362
+ }
3363
+ )
3364
+ }
3365
+ ),
3366
+ /* @__PURE__ */ jsx(AnimatePresence, { children: showScrollBtn && /* @__PURE__ */ jsx(
3367
+ motion.div,
3368
+ {
3369
+ initial: { opacity: 0, y: 6 },
3370
+ animate: { opacity: 1, y: 0 },
3371
+ exit: { opacity: 0, y: 6 },
3372
+ transition: { duration: 0.12 },
3373
+ className: "payman-v2-scroll-to-bottom",
3374
+ children: /* @__PURE__ */ jsx(
3375
+ "button",
3376
+ {
3377
+ onClick: () => {
3378
+ scrollToBottom();
3379
+ },
3380
+ className: "payman-v2-scroll-to-bottom-btn",
3381
+ "aria-label": "Scroll to bottom",
3382
+ children: /* @__PURE__ */ jsx(ArrowDown, { style: { width: 16, height: 16 } })
3383
+ }
3384
+ )
3385
+ }
3386
+ ) })
3387
+ ] });
3388
+ }
3389
+ );
3390
+ var ChatInputV2 = forwardRef(
3391
+ function ChatInputV22({
3392
+ onSend,
3393
+ onCancel,
3394
+ disabled = false,
3395
+ isStreaming = false,
3396
+ placeholder = "Reply...",
3397
+ enableVoice = false,
3398
+ voiceAvailable = false,
3399
+ isRecording = false,
3400
+ onVoicePress,
3401
+ transcribedText = "",
3402
+ showResetSession = false,
3403
+ onResetSession,
3404
+ showAttachmentButton = true,
3405
+ showUploadImageButton = true,
3406
+ showAttachFileButton = true,
3407
+ onUploadImageClick,
3408
+ onAttachFileClick,
3409
+ editingMessageId = null,
3410
+ onClearEditing
3411
+ }, ref) {
3412
+ const [value, setValue] = useState("");
3413
+ const [isFocused, setIsFocused] = useState(false);
3414
+ const [showActions, setShowActions] = useState(false);
3415
+ const [showVoiceTooltip, setShowVoiceTooltip] = useState(false);
3416
+ const textareaRef = useRef(null);
3417
+ const actionsRef = useRef(null);
3418
+ const preRecordTextRef = useRef("");
3419
+ const voiceTooltipTimerRef = useRef(
3420
+ null
3421
+ );
3422
+ const voiceDraftSyncActiveRef = useRef(false);
3423
+ const isInputLocked = disabled || isRecording;
3424
+ const hasAttachmentOptions = showUploadImageButton || showAttachFileButton;
3425
+ const showAttachmentMenuButton = showAttachmentButton && hasAttachmentOptions;
3426
+ const showVoiceButton = enableVoice && onVoicePress != null;
3427
+ const isVoiceButtonDisabled = disabled || !voiceAvailable;
3428
+ useEffect(() => {
3429
+ if (textareaRef.current) {
3430
+ textareaRef.current.style.height = "auto";
3431
+ const scrollHeight = textareaRef.current.scrollHeight;
3432
+ textareaRef.current.style.height = `${Math.min(scrollHeight, 200)}px`;
3433
+ }
3434
+ }, [value]);
3435
+ useEffect(() => {
3436
+ if (disabled) {
3437
+ setIsFocused(false);
3438
+ setShowActions(false);
3439
+ textareaRef.current?.blur();
3440
+ return;
3441
+ }
3442
+ const frameId = requestAnimationFrame(() => textareaRef.current?.focus());
3443
+ return () => cancelAnimationFrame(frameId);
3444
+ }, [disabled]);
3445
+ useImperativeHandle(
3446
+ ref,
3447
+ () => ({
3448
+ setDraft: (message) => {
3449
+ setShowActions(false);
3450
+ setValue(message);
3451
+ requestAnimationFrame(() => {
3452
+ const textarea = textareaRef.current;
3453
+ if (!textarea || disabled) return;
3454
+ textarea.focus();
3455
+ const end = message.length;
3456
+ textarea.setSelectionRange(end, end);
3457
+ });
3458
+ }
3459
+ }),
3460
+ [disabled]
3461
+ );
3462
+ useEffect(() => {
3463
+ if (!showActions) return;
3464
+ const handleClickOutside = (e) => {
3465
+ if (actionsRef.current && !actionsRef.current.contains(e.target)) {
3466
+ setShowActions(false);
3467
+ }
3468
+ };
3469
+ document.addEventListener("mousedown", handleClickOutside);
3470
+ return () => document.removeEventListener("mousedown", handleClickOutside);
3471
+ }, [showActions]);
3472
+ useEffect(() => {
3473
+ if (!showAttachmentMenuButton) {
3474
+ setShowActions(false);
3475
+ }
3476
+ }, [showAttachmentMenuButton]);
3477
+ useEffect(() => {
3478
+ return () => {
3479
+ if (voiceTooltipTimerRef.current) {
3480
+ clearTimeout(voiceTooltipTimerRef.current);
3481
+ }
3482
+ };
3483
+ }, []);
3484
+ useEffect(() => {
3485
+ if (!voiceDraftSyncActiveRef.current) return;
3486
+ const base = preRecordTextRef.current;
3487
+ const separator = base && !base.endsWith(" ") && transcribedText ? " " : "";
3488
+ setValue(`${base}${separator}${transcribedText}`);
3489
+ }, [isRecording, transcribedText]);
3490
+ const handleSend = useCallback(() => {
3491
+ if (!value.trim() || disabled) return;
3492
+ voiceDraftSyncActiveRef.current = false;
3493
+ preRecordTextRef.current = "";
3494
+ onClearEditing?.();
3495
+ onSend(value.trim());
3496
+ setValue("");
3497
+ requestAnimationFrame(() => {
3498
+ if (textareaRef.current) {
3499
+ textareaRef.current.style.height = "auto";
3500
+ textareaRef.current.focus();
3501
+ }
3502
+ });
3503
+ }, [value, disabled, onClearEditing, onSend]);
3504
+ const handleKeyDown = (e) => {
3505
+ if (e.key === "Enter" && !e.shiftKey) {
3506
+ e.preventDefault();
3507
+ if (isStreaming) return;
3508
+ handleSend();
3509
+ }
3510
+ };
3511
+ const handleUploadImageClick = () => {
3512
+ onUploadImageClick?.();
3513
+ setShowActions(false);
3514
+ };
3515
+ const handleAttachFileClick = () => {
3516
+ onAttachFileClick?.();
3517
+ setShowActions(false);
3518
+ };
3519
+ const hideVoiceTooltip = useCallback(() => {
3520
+ if (voiceTooltipTimerRef.current) {
3521
+ clearTimeout(voiceTooltipTimerRef.current);
3522
+ voiceTooltipTimerRef.current = null;
3523
+ }
3524
+ setShowVoiceTooltip(false);
3525
+ }, []);
3526
+ const startVoiceTooltipTimer = useCallback(() => {
3527
+ if (isVoiceButtonDisabled || isRecording) return;
3528
+ if (voiceTooltipTimerRef.current) {
3529
+ clearTimeout(voiceTooltipTimerRef.current);
3530
+ }
3531
+ voiceTooltipTimerRef.current = setTimeout(() => {
3532
+ setShowVoiceTooltip(true);
3533
+ voiceTooltipTimerRef.current = null;
3534
+ }, 2e3);
3535
+ }, [isRecording, isVoiceButtonDisabled]);
3536
+ const handleVoiceToggle = () => {
3537
+ hideVoiceTooltip();
3538
+ setShowActions(false);
3539
+ if (!onVoicePress || isVoiceButtonDisabled) return;
3540
+ if (!isRecording) {
3541
+ preRecordTextRef.current = value;
3542
+ voiceDraftSyncActiveRef.current = true;
3543
+ }
3544
+ onVoicePress();
3545
+ };
3546
+ const canSend = value.trim().length > 0 && !disabled;
3547
+ const sendDisabled = !canSend || isStreaming;
3548
+ return /* @__PURE__ */ jsxs("div", { className: "payman-v2-input-container", children: [
3549
+ /* @__PURE__ */ jsxs(
3550
+ "div",
3551
+ {
3552
+ className: cn(
3553
+ "payman-v2-input-wrapper",
3554
+ (isFocused || isRecording) && "payman-v2-input-wrapper-focused"
3555
+ ),
3556
+ children: [
3557
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-input-body", children: [
3558
+ /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: editingMessageId && /* @__PURE__ */ jsxs(
3559
+ motion.div,
3560
+ {
3561
+ initial: { opacity: 0, y: -4 },
3562
+ animate: { opacity: 1, y: 0 },
3563
+ exit: { opacity: 0, y: -4 },
3564
+ transition: { duration: 0.14, ease: "easeOut" },
3565
+ className: "payman-v2-input-editing-banner",
3566
+ children: [
3567
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-input-editing-banner-info", children: [
3568
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-input-editing-icon-wrap", children: /* @__PURE__ */ jsx(Pencil, { style: { width: 12, height: 12 } }) }),
3569
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-input-editing-label", children: "Editing message" })
3570
+ ] }),
3571
+ onClearEditing && /* @__PURE__ */ jsx(
3572
+ "button",
3573
+ {
3574
+ type: "button",
3575
+ onClick: onClearEditing,
3576
+ className: "payman-v2-input-editing-close",
3577
+ "aria-label": "Stop editing message",
3578
+ children: /* @__PURE__ */ jsx(X, { style: { width: 14, height: 14 } })
3579
+ }
3580
+ )
3581
+ ]
3582
+ }
3583
+ ) }),
3584
+ /* @__PURE__ */ jsx(
3585
+ "textarea",
3586
+ {
3587
+ ref: textareaRef,
3588
+ value,
3589
+ onChange: (e) => {
3590
+ if (isRecording) return;
3591
+ const nextValue = e.target.value;
3592
+ voiceDraftSyncActiveRef.current = false;
3593
+ setValue(nextValue);
3594
+ if (editingMessageId && nextValue.length === 0) {
3595
+ onClearEditing?.();
3596
+ }
3597
+ },
3598
+ onKeyDown: handleKeyDown,
3599
+ onFocus: () => {
3600
+ if (!disabled) setIsFocused(true);
3601
+ },
3602
+ onBlur: () => setIsFocused(false),
3603
+ onMouseDown: (e) => {
3604
+ if (disabled) e.preventDefault();
3605
+ },
3606
+ "aria-disabled": disabled,
3607
+ readOnly: isInputLocked,
3608
+ tabIndex: disabled ? -1 : 0,
3609
+ placeholder: isRecording ? "Listening\u2026" : placeholder,
3610
+ className: "payman-v2-input-textarea",
3611
+ "data-disabled": disabled ? "true" : "false",
3612
+ rows: 1
3613
+ }
3614
+ )
3615
+ ] }),
3616
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-input-controls", children: [
3617
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-input-controls-left", children: [
3618
+ showResetSession && onResetSession && /* @__PURE__ */ jsxs(
3619
+ "button",
3620
+ {
3621
+ type: "button",
3622
+ onClick: onResetSession,
3623
+ disabled: isStreaming || isRecording,
3624
+ className: "payman-v2-input-new-session-btn",
3625
+ "aria-label": "New Session",
3626
+ title: "New Session",
3627
+ children: [
3628
+ /* @__PURE__ */ jsx(
3629
+ RotateCcw,
3630
+ {
3631
+ style: { width: 16, height: 16, strokeWidth: 2.25 }
3632
+ }
3633
+ ),
3634
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-input-new-session-tooltip", children: "New Session" })
3635
+ ]
3636
+ }
3637
+ ),
3638
+ showAttachmentMenuButton && /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, ref: actionsRef, children: [
3639
+ /* @__PURE__ */ jsx(
3640
+ "button",
3641
+ {
3642
+ type: "button",
3643
+ onClick: () => setShowActions((current) => !current),
3644
+ disabled: disabled || isRecording,
3645
+ className: cn(
3646
+ "payman-v2-input-attach-btn",
3647
+ showActions && "payman-v2-input-attach-btn-active"
3648
+ ),
3649
+ "aria-label": "Attach",
3650
+ children: /* @__PURE__ */ jsx(
3651
+ Plus,
3652
+ {
3653
+ style: { width: 20, height: 20, strokeWidth: 2 }
3654
+ }
3655
+ )
3656
+ }
3657
+ ),
3658
+ /* @__PURE__ */ jsx(AnimatePresence, { children: showActions && /* @__PURE__ */ jsxs(
3659
+ motion.div,
3660
+ {
3661
+ initial: { opacity: 0, y: 4, scale: 0.95 },
3662
+ animate: { opacity: 1, y: 0, scale: 1 },
3663
+ exit: { opacity: 0, y: 4, scale: 0.95 },
3664
+ transition: { duration: 0.12 },
3665
+ className: "payman-v2-input-attach-menu",
3666
+ children: [
3667
+ showUploadImageButton && /* @__PURE__ */ jsxs(
3668
+ "button",
3669
+ {
3670
+ type: "button",
3671
+ className: "payman-v2-input-attach-option",
3672
+ onClick: handleUploadImageClick,
3673
+ children: [
3674
+ /* @__PURE__ */ jsx(
3675
+ ImagePlus,
3676
+ {
3677
+ style: { width: 16, height: 16 },
3678
+ className: "payman-v2-input-attach-option-icon"
3679
+ }
3680
+ ),
3681
+ "Upload image"
3682
+ ]
3683
+ }
3684
+ ),
3685
+ showAttachFileButton && /* @__PURE__ */ jsxs(
3686
+ "button",
3687
+ {
3688
+ type: "button",
3689
+ className: "payman-v2-input-attach-option",
3690
+ onClick: handleAttachFileClick,
3691
+ children: [
3692
+ /* @__PURE__ */ jsx(
3693
+ Paperclip,
3694
+ {
3695
+ style: { width: 16, height: 16 },
3696
+ className: "payman-v2-input-attach-option-icon"
3697
+ }
3698
+ ),
3699
+ "Attach file"
3700
+ ]
3701
+ }
3702
+ )
3703
+ ]
3704
+ }
3705
+ ) })
3706
+ ] }),
3707
+ showVoiceButton && /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
3708
+ /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: showVoiceTooltip && /* @__PURE__ */ jsx(
3709
+ motion.div,
3710
+ {
3711
+ initial: { opacity: 0, y: 4, scale: 0.98 },
3712
+ animate: { opacity: 1, y: 0, scale: 1 },
3713
+ exit: { opacity: 0, y: 4, scale: 0.98 },
3714
+ transition: { duration: 0.14, ease: "easeOut" },
3715
+ className: "payman-v2-input-voice-tooltip",
3716
+ children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-input-voice-tooltip-content", children: [
3717
+ "Chat with your voice",
3718
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-input-voice-tooltip-arrow" })
3719
+ ] })
3720
+ }
3721
+ ) }),
3722
+ /* @__PURE__ */ jsxs(
3723
+ "button",
3724
+ {
3725
+ type: "button",
3726
+ onClick: handleVoiceToggle,
3727
+ onMouseEnter: startVoiceTooltipTimer,
3728
+ onMouseLeave: hideVoiceTooltip,
3729
+ onFocus: startVoiceTooltipTimer,
3730
+ onBlur: hideVoiceTooltip,
3731
+ disabled: isVoiceButtonDisabled,
3732
+ className: cn(
3733
+ "payman-v2-input-mic-btn",
3734
+ isRecording && "payman-v2-input-mic-recording"
3735
+ ),
3736
+ "aria-label": isRecording ? "Stop recording" : "Voice input",
3737
+ children: [
3738
+ /* @__PURE__ */ jsx(Mic, { style: { width: 18, height: 18 } }),
3739
+ isRecording && /* @__PURE__ */ jsx("span", { className: "payman-v2-input-mic-indicator" })
3740
+ ]
3741
+ }
3742
+ )
3743
+ ] })
3744
+ ] }),
3745
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-input-controls-right", children: /* @__PURE__ */ jsx(
3746
+ "button",
3747
+ {
3748
+ type: "button",
3749
+ onClick: handleSend,
3750
+ disabled: sendDisabled,
3751
+ className: cn(
3752
+ "payman-v2-input-send-btn",
3753
+ sendDisabled && "payman-v2-input-send-btn-disabled"
3754
+ ),
3755
+ "aria-label": "Send message",
3756
+ children: /* @__PURE__ */ jsx(
3757
+ ArrowUp,
3758
+ {
3759
+ style: { width: 16, height: 16, strokeWidth: 2.5 },
3760
+ className: "payman-v2-input-send-icon"
3761
+ }
3762
+ )
3763
+ }
3764
+ ) })
3765
+ ] })
3766
+ ]
3767
+ }
3768
+ ),
3769
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-input-disclaimer", children: "AI can make mistakes. Please double-check responses." })
3770
+ ] });
3771
+ }
3772
+ );
3773
+ function ImageLightboxV2({ src, alt, onClose }) {
3774
+ const [isMounted, setIsMounted] = useState(false);
3775
+ const [isImageLoaded, setIsImageLoaded] = useState(false);
3776
+ useEffect(() => {
3777
+ setIsMounted(true);
3778
+ return () => setIsMounted(false);
3779
+ }, []);
3780
+ useEffect(() => {
3781
+ setIsImageLoaded(false);
3782
+ }, [src]);
3783
+ const handleKeyDown = useCallback(
3784
+ (e) => {
3785
+ if (e.key === "Escape") onClose();
3786
+ },
3787
+ [onClose]
3788
+ );
3789
+ useEffect(() => {
3790
+ if (!src || typeof document === "undefined") return;
3791
+ document.addEventListener("keydown", handleKeyDown);
3792
+ const previousOverflow = document.body.style.overflow;
3793
+ document.body.style.overflow = "hidden";
3794
+ return () => {
3795
+ document.removeEventListener("keydown", handleKeyDown);
3796
+ document.body.style.overflow = previousOverflow;
3797
+ };
3798
+ }, [src, handleKeyDown]);
3799
+ const handleDownload = () => {
3800
+ if (!src || typeof document === "undefined") return;
3801
+ const a = document.createElement("a");
3802
+ a.href = src;
3803
+ a.download = alt.trim() ? alt : "image";
3804
+ document.body.appendChild(a);
3805
+ a.click();
3806
+ a.remove();
3807
+ };
3808
+ if (!isMounted || typeof document === "undefined") {
3809
+ return null;
3810
+ }
3811
+ return createPortal(
3812
+ /* @__PURE__ */ jsx(AnimatePresence, { children: src ? /* @__PURE__ */ jsxs(
3813
+ motion.div,
3814
+ {
3815
+ className: "payman-v2-lightbox",
3816
+ initial: { opacity: 0 },
3817
+ animate: { opacity: 1 },
3818
+ exit: { opacity: 0 },
3819
+ transition: { duration: 0.18 },
3820
+ onClick: onClose,
3821
+ role: "presentation",
3822
+ children: [
3823
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-lightbox-controls", children: [
3824
+ /* @__PURE__ */ jsx(
3825
+ "button",
3826
+ {
3827
+ type: "button",
3828
+ className: "payman-v2-lightbox-btn",
3829
+ "aria-label": "Download",
3830
+ onClick: (e) => {
3831
+ e.stopPropagation();
3832
+ handleDownload();
3833
+ },
3834
+ children: /* @__PURE__ */ jsx(Download, { size: 20, strokeWidth: 2 })
3835
+ }
3836
+ ),
3837
+ /* @__PURE__ */ jsx(
3838
+ "button",
3839
+ {
3840
+ type: "button",
3841
+ className: "payman-v2-lightbox-btn",
3842
+ "aria-label": "Close",
3843
+ onClick: (e) => {
3844
+ e.stopPropagation();
3845
+ onClose();
3846
+ },
3847
+ children: /* @__PURE__ */ jsx(X, { size: 20, strokeWidth: 2 })
3848
+ }
3849
+ )
3850
+ ] }),
3851
+ /* @__PURE__ */ jsxs(
3852
+ "div",
3853
+ {
3854
+ className: "payman-v2-lightbox-content",
3855
+ onClick: (e) => e.stopPropagation(),
3856
+ role: "dialog",
3857
+ "aria-modal": "true",
3858
+ "aria-label": alt || "Image preview",
3859
+ children: [
3860
+ !isImageLoaded ? /* @__PURE__ */ jsxs("div", { className: "payman-v2-lightbox-loading", children: [
3861
+ /* @__PURE__ */ jsx(
3862
+ Loader2,
3863
+ {
3864
+ size: 24,
3865
+ strokeWidth: 2,
3866
+ "aria-hidden": true,
3867
+ style: {
3868
+ color: "rgba(255, 255, 255, 0.8)",
3869
+ animation: "payman-v2-spin 0.6s linear infinite"
3870
+ }
3871
+ }
3872
+ ),
3873
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-lightbox-loading-text", children: "Loading image" })
3874
+ ] }) : null,
3875
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-lightbox-img-wrapper", children: /* @__PURE__ */ jsx(
3876
+ motion.div,
3877
+ {
3878
+ initial: { scale: 0.92, opacity: 0 },
3879
+ animate: {
3880
+ scale: isImageLoaded ? 1 : 0.92,
3881
+ opacity: isImageLoaded ? 1 : 0
3882
+ },
3883
+ exit: { scale: 0.92, opacity: 0 },
3884
+ transition: { duration: 0.2 },
3885
+ style: {
3886
+ display: "flex",
3887
+ height: "100%",
3888
+ width: "100%",
3889
+ alignItems: "center",
3890
+ justifyContent: "center"
3891
+ },
3892
+ children: /* @__PURE__ */ jsx(
3893
+ "img",
3894
+ {
3895
+ className: "payman-v2-lightbox-img",
3896
+ src,
3897
+ alt,
3898
+ draggable: false,
3899
+ onLoad: () => setIsImageLoaded(true)
3900
+ }
3901
+ )
3902
+ }
3903
+ ) })
3904
+ ]
3905
+ }
3906
+ )
3907
+ ]
3908
+ },
3909
+ src
3910
+ ) : null }),
3911
+ document.body
3912
+ );
3913
+ }
3914
+ var DEFAULT_USER_ACTION_STATE = {
3915
+ request: null,
3916
+ result: null,
3917
+ clearOtpTrigger: 0
3918
+ };
3919
+ var NOOP_ASYNC = async () => {
3920
+ };
3921
+ var PaymanChatInner = forwardRef(function PaymanChatInner2({
3922
+ config,
3923
+ callbacks = {},
3924
+ className,
3925
+ style,
3926
+ children,
3927
+ onLoadMoreMessages,
3928
+ isLoadingMoreMessages = false,
3929
+ hasMoreMessages = false,
3930
+ chat
3931
+ }, ref) {
3932
+ const [inputValue, setInputValue] = useState("");
3933
+ const prevInputValueRef = useRef(inputValue);
3934
+ const [hasEverSentMessage, setHasEverSentMessage] = useState(false);
3935
+ const [lightboxSrc, setLightboxSrc] = useState(null);
3936
+ const [lightboxAlt, setLightboxAlt] = useState("");
3937
+ const [editingMessageId, setEditingMessageId] = useState(null);
3938
+ const [isResetSessionConfirmOpen, setIsResetSessionConfirmOpen] = useState(false);
3939
+ const chatInputV2Ref = useRef(null);
3940
+ const messageListV2Ref = useRef(null);
3941
+ const resetToEmptyStateRef = useRef(false);
3942
+ const isV2 = config.uiVersion !== 1;
3943
+ useEffect(() => {
3944
+ if (config.sentryDsn) {
3945
+ initSentryIfNeeded(config.sentryDsn);
3946
+ }
3947
+ }, [config.sentryDsn]);
2150
3948
  const {
2151
3949
  messages,
2152
3950
  sendMessage,
@@ -2159,16 +3957,33 @@ var PaymanChat = forwardRef(function PaymanChat2({
2159
3957
  getMessages
2160
3958
  } = chat;
2161
3959
  useEffect(() => {
3960
+ if (resetToEmptyStateRef.current) {
3961
+ if (messages.length === 0) {
3962
+ setHasEverSentMessage(false);
3963
+ resetToEmptyStateRef.current = false;
3964
+ }
3965
+ return;
3966
+ }
2162
3967
  if (messages.length > 0 && !hasEverSentMessage) {
2163
3968
  setHasEverSentMessage(true);
2164
3969
  }
2165
3970
  }, [messages.length, hasEverSentMessage]);
3971
+ useEffect(() => {
3972
+ if (!editingMessageId) return;
3973
+ const editingMessageStillExists = messages.some(
3974
+ (message) => message.id === editingMessageId && message.role === "user"
3975
+ );
3976
+ if (!editingMessageStillExists) {
3977
+ setEditingMessageId(null);
3978
+ }
3979
+ }, [editingMessageId, messages]);
2166
3980
  const userActionState = chat.userActionState ?? DEFAULT_USER_ACTION_STATE;
2167
3981
  const approveUserAction = chat.approveUserAction ?? NOOP_ASYNC;
2168
3982
  const rejectUserAction = chat.rejectUserAction ?? NOOP_ASYNC;
2169
3983
  const resendOtp = chat.resendOtp ?? NOOP_ASYNC;
2170
3984
  const isUserActionSupported = typeof chat.approveUserAction === "function" && typeof chat.rejectUserAction === "function" && typeof chat.resendOtp === "function";
2171
3985
  const {
3986
+ transcribedText,
2172
3987
  isAvailable: voiceAvailable,
2173
3988
  isRecording,
2174
3989
  startRecording,
@@ -2182,7 +3997,9 @@ var PaymanChat = forwardRef(function PaymanChat2({
2182
3997
  },
2183
3998
  {
2184
3999
  onResult: (text) => {
2185
- setInputValue(text);
4000
+ if (!isV2) {
4001
+ setInputValue(text);
4002
+ }
2186
4003
  },
2187
4004
  onEnd: () => {
2188
4005
  },
@@ -2211,17 +4028,46 @@ var PaymanChat = forwardRef(function PaymanChat2({
2211
4028
  isWaitingForResponse
2212
4029
  ]
2213
4030
  );
2214
- const { onExecutionTraceClick, onResetSession } = callbacks;
4031
+ const {
4032
+ onExecutionTraceClick,
4033
+ onResetSession,
4034
+ onUploadImageClick,
4035
+ onAttachFileClick
4036
+ } = callbacks;
4037
+ const performResetSession = useCallback(() => {
4038
+ resetToEmptyStateRef.current = true;
4039
+ setEditingMessageId(null);
4040
+ setIsResetSessionConfirmOpen(false);
4041
+ setInputValue("");
4042
+ setLightboxSrc(null);
4043
+ setLightboxAlt("");
4044
+ chatInputV2Ref.current?.setDraft("");
4045
+ clearTranscript();
4046
+ if (isRecording) {
4047
+ stopRecording();
4048
+ }
4049
+ resetSession();
4050
+ onResetSession?.();
4051
+ }, [
4052
+ clearTranscript,
4053
+ isRecording,
4054
+ onResetSession,
4055
+ resetSession,
4056
+ stopRecording
4057
+ ]);
4058
+ const requestResetSession = useCallback(() => {
4059
+ setIsResetSessionConfirmOpen(true);
4060
+ }, []);
4061
+ const closeResetSessionConfirm = useCallback(() => {
4062
+ setIsResetSessionConfirmOpen(false);
4063
+ }, []);
2215
4064
  useImperativeHandle(ref, () => ({
2216
- resetSession: () => {
2217
- resetSession();
2218
- onResetSession?.();
2219
- },
4065
+ resetSession: performResetSession,
2220
4066
  clearMessages,
2221
4067
  cancelStream,
2222
4068
  getSessionId,
2223
4069
  getMessages
2224
- }), [resetSession, clearMessages, cancelStream, getSessionId, getMessages, onResetSession]);
4070
+ }), [performResetSession, clearMessages, cancelStream, getSessionId, getMessages]);
2225
4071
  const {
2226
4072
  placeholder = "Type your message...",
2227
4073
  emptyStateText = "What can I help with?",
@@ -2245,8 +4091,26 @@ var PaymanChat = forwardRef(function PaymanChat2({
2245
4091
  disabledComponent,
2246
4092
  showEmptyStateIcon = true,
2247
4093
  emptyStateComponent,
2248
- showResetSession = false
4094
+ showResetSession = false,
4095
+ showAttachmentButton = true,
4096
+ showUploadImageButton = true,
4097
+ showAttachFileButton = true,
4098
+ messageActions: messageActionsConfig
2249
4099
  } = config;
4100
+ const messageActions = useMemo(
4101
+ () => ({
4102
+ userMessageActions: {
4103
+ copy: messageActionsConfig?.userMessageActions?.copy ?? true,
4104
+ edit: messageActionsConfig?.userMessageActions?.edit ?? false,
4105
+ retry: messageActionsConfig?.userMessageActions?.retry ?? false
4106
+ },
4107
+ assistantMessageActions: {
4108
+ copy: messageActionsConfig?.assistantMessageActions?.copy ?? true,
4109
+ trace: messageActionsConfig?.assistantMessageActions?.trace ?? true
4110
+ }
4111
+ }),
4112
+ [messageActionsConfig]
4113
+ );
2250
4114
  const isSessionParamsConfigured = useMemo(() => {
2251
4115
  if (!sessionParams) return false;
2252
4116
  return !!(sessionParams.id?.trim() && sessionParams.name?.trim());
@@ -2267,7 +4131,7 @@ var PaymanChat = forwardRef(function PaymanChat2({
2267
4131
  stopRecording();
2268
4132
  }
2269
4133
  if (inputValue.trim() && !disableInput && isSessionParamsConfigured) {
2270
- sendMessage(inputValue.trim());
4134
+ void sendMessage(inputValue.trim());
2271
4135
  setInputValue("");
2272
4136
  }
2273
4137
  };
@@ -2280,6 +4144,7 @@ var PaymanChat = forwardRef(function PaymanChat2({
2280
4144
  stopRecording();
2281
4145
  };
2282
4146
  const isInputDisabled = isWaitingForResponse || !isSessionParamsConfigured || disableInput;
4147
+ const isV2InputDisabled = !isSessionParamsConfigured || disableInput;
2283
4148
  const isEmpty = messages.length === 0;
2284
4149
  if (isChatDisabled) {
2285
4150
  if (disabledComponent) {
@@ -2313,54 +4178,87 @@ var PaymanChat = forwardRef(function PaymanChat2({
2313
4178
  }
2314
4179
  ) });
2315
4180
  }
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
- }
4181
+ const handleImageClick = (src, alt) => {
4182
+ setLightboxSrc(src);
4183
+ setLightboxAlt(alt);
4184
+ };
4185
+ const v2UserAction = useMemo(() => {
4186
+ if (!isUserActionSupported || !userActionState.request) return null;
4187
+ const req = userActionState.request;
4188
+ let status = "pending";
4189
+ if (userActionState.result === "approved") status = "approved";
4190
+ else if (userActionState.result === "rejected") status = "rejected";
4191
+ return {
4192
+ messageId: `ua-${req.userActionId || Date.now()}`,
4193
+ action: {
4194
+ type: req.userActionType || "generic",
4195
+ message: req.message || "Verify this action",
4196
+ amount: req.metadata?.amount,
4197
+ payeeName: req.metadata?.payeeName
4198
+ },
4199
+ status
4200
+ };
4201
+ }, [isUserActionSupported, userActionState.request, userActionState.result]);
4202
+ const handleV2Send = (text) => {
4203
+ if (isRecording) stopRecording();
4204
+ if (text.trim() && !disableInput && isSessionParamsConfigured) {
4205
+ setEditingMessageId(null);
4206
+ void sendMessage(text.trim());
2342
4207
  }
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(
4208
+ };
4209
+ const handleVoicePress = useCallback(async () => {
4210
+ if (!voiceAvailable) return;
4211
+ if (isRecording) {
4212
+ stopRecording();
4213
+ return;
4214
+ }
4215
+ clearTranscript();
4216
+ await startRecording();
4217
+ }, [clearTranscript, isRecording, startRecording, stopRecording, voiceAvailable]);
4218
+ const handleEditMessageDraft = useCallback((messageId) => {
4219
+ const targetMessage = messages.find((message) => message.id === messageId);
4220
+ if (!targetMessage?.content.trim()) return;
4221
+ setEditingMessageId(messageId);
4222
+ chatInputV2Ref.current?.setDraft(targetMessage.content);
4223
+ requestAnimationFrame(() => {
4224
+ messageListV2Ref.current?.scrollToBottom("smooth");
4225
+ });
4226
+ }, [messages]);
4227
+ const handleRetryUserMessage = useCallback((messageId) => {
4228
+ if (isWaitingForResponse) return;
4229
+ const targetMessage = messages.find(
4230
+ (message) => message.id === messageId && message.role === "user"
4231
+ );
4232
+ if (!targetMessage?.content.trim()) return;
4233
+ void sendMessage(targetMessage.content.trim());
4234
+ const bump = () => messageListV2Ref.current?.scrollToBottom("instant");
4235
+ requestAnimationFrame(() => {
4236
+ bump();
4237
+ queueMicrotask(() => {
4238
+ window.setTimeout(bump, 120);
4239
+ });
4240
+ });
4241
+ }, [isWaitingForResponse, messages, sendMessage]);
4242
+ const handleClearEditing = useCallback(() => {
4243
+ setEditingMessageId(null);
4244
+ }, []);
4245
+ if (isV2) {
4246
+ return /* @__PURE__ */ jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
4247
+ "div",
4248
+ {
4249
+ className: cn("payman-v2-root", className),
4250
+ style,
4251
+ children: [
4252
+ children,
4253
+ 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
4254
  motion.div,
2358
4255
  {
2359
4256
  initial: { opacity: 1 },
2360
4257
  exit: { opacity: 0 },
2361
4258
  transition: { duration: 0.3 },
2362
- className: "payman-empty-centered-layout",
2363
- children: /* @__PURE__ */ jsxs("div", { className: "payman-empty-centered-inner", children: [
4259
+ className: "payman-v2-chat-layout",
4260
+ style: { justifyContent: "center", alignItems: "center" },
4261
+ children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", flex: 1, width: "100%" }, children: [
2364
4262
  /* @__PURE__ */ jsx(
2365
4263
  MessageList,
2366
4264
  {
@@ -2394,56 +4292,244 @@ var PaymanChat = forwardRef(function PaymanChat2({
2394
4292
  initial: { opacity: 0, y: 12 },
2395
4293
  animate: { opacity: 1, y: 0 },
2396
4294
  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
4295
+ style: { width: "100%" },
4296
+ children: hasAskPermission && /* @__PURE__ */ jsx(
4297
+ ChatInputV2,
4298
+ {
4299
+ ref: chatInputV2Ref,
4300
+ onSend: handleV2Send,
4301
+ onCancel: cancelStream,
4302
+ disabled: isV2InputDisabled,
4303
+ isStreaming: isWaitingForResponse,
4304
+ placeholder: isRecording ? "Listening..." : placeholder,
4305
+ enableVoice: config.enableVoice === true,
4306
+ transcribedText: config.enableVoice === true ? transcribedText : "",
4307
+ voiceAvailable: config.enableVoice === true && voiceAvailable,
4308
+ isRecording,
4309
+ onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
4310
+ onCancelRecording: handleCancelRecording,
4311
+ onConfirmRecording: handleConfirmRecording,
4312
+ showResetSession,
4313
+ onResetSession: requestResetSession,
4314
+ showAttachmentButton,
4315
+ showUploadImageButton,
4316
+ showAttachFileButton,
4317
+ onUploadImageClick,
4318
+ onAttachFileClick,
4319
+ editingMessageId,
4320
+ onClearEditing: handleClearEditing
4321
+ }
4322
+ )
2399
4323
  }
2400
4324
  )
2401
4325
  ] })
2402
4326
  },
2403
- "empty-centered"
2404
- )
2405
- ) : (
2406
- /* ---- Normal chat layout ---- */
2407
- /* @__PURE__ */ jsxs(
4327
+ "v2-empty"
4328
+ ) : /* @__PURE__ */ jsxs(
2408
4329
  motion.div,
2409
4330
  {
2410
4331
  initial: hasEverSentMessage ? { opacity: 0 } : false,
2411
4332
  animate: { opacity: 1 },
2412
4333
  transition: { duration: 0.3 },
2413
- className: "flex flex-col flex-1 min-h-0",
4334
+ className: "payman-v2-chat-layout",
2414
4335
  children: [
2415
4336
  /* @__PURE__ */ jsx(
2416
- MessageList,
4337
+ MessageListV2,
2417
4338
  {
4339
+ ref: messageListV2Ref,
2418
4340
  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,
4341
+ isStreaming: isWaitingForResponse,
4342
+ onEditUserMessage: handleEditMessageDraft,
4343
+ onRetryUserMessage: handleRetryUserMessage,
4344
+ onImageClick: handleImageClick,
2436
4345
  onExecutionTraceClick,
2437
- onLoadMoreMessages,
2438
- isLoadingMoreMessages,
2439
- hasMoreMessages
4346
+ messageActions,
4347
+ retryDisabled: isWaitingForResponse,
4348
+ userAction: v2UserAction,
4349
+ onApproveAction: isUserActionSupported ? async (_msgId, otp) => {
4350
+ await approveUserAction(otp);
4351
+ } : void 0,
4352
+ onRejectAction: isUserActionSupported ? async () => {
4353
+ await rejectUserAction();
4354
+ } : void 0,
4355
+ onResendAction: isUserActionSupported ? async () => {
4356
+ await resendOtp();
4357
+ } : void 0
2440
4358
  }
2441
4359
  ),
2442
- inputElement
4360
+ hasAskPermission && /* @__PURE__ */ jsx(
4361
+ ChatInputV2,
4362
+ {
4363
+ ref: chatInputV2Ref,
4364
+ onSend: handleV2Send,
4365
+ onCancel: cancelStream,
4366
+ disabled: isV2InputDisabled,
4367
+ isStreaming: isWaitingForResponse,
4368
+ placeholder: isRecording ? "Listening..." : placeholder,
4369
+ enableVoice: config.enableVoice === true,
4370
+ transcribedText: config.enableVoice === true ? transcribedText : "",
4371
+ voiceAvailable: config.enableVoice === true && voiceAvailable,
4372
+ isRecording,
4373
+ onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
4374
+ onCancelRecording: handleCancelRecording,
4375
+ onConfirmRecording: handleConfirmRecording,
4376
+ showResetSession,
4377
+ onResetSession: requestResetSession,
4378
+ showAttachmentButton,
4379
+ showUploadImageButton,
4380
+ showAttachFileButton,
4381
+ onUploadImageClick,
4382
+ onAttachFileClick,
4383
+ editingMessageId,
4384
+ onClearEditing: handleClearEditing
4385
+ }
4386
+ )
2443
4387
  ]
2444
4388
  },
2445
- "chat-layout"
4389
+ "v2-chat"
4390
+ ) }),
4391
+ /* @__PURE__ */ jsx(
4392
+ ImageLightboxV2,
4393
+ {
4394
+ src: lightboxSrc,
4395
+ alt: lightboxAlt,
4396
+ onClose: () => setLightboxSrc(null)
4397
+ }
4398
+ ),
4399
+ /* @__PURE__ */ jsx(
4400
+ ResetSessionConfirmModal,
4401
+ {
4402
+ isOpen: isResetSessionConfirmOpen,
4403
+ onClose: closeResetSessionConfirm,
4404
+ onConfirm: performResetSession
4405
+ }
2446
4406
  )
4407
+ ]
4408
+ }
4409
+ ) });
4410
+ }
4411
+ const inputElement = hasAskPermission && /* @__PURE__ */ jsx(
4412
+ ChatInput,
4413
+ {
4414
+ value: inputValue,
4415
+ onChange: setInputValue,
4416
+ onSend: handleSend,
4417
+ onPause: cancelStream,
4418
+ disabled: isInputDisabled,
4419
+ placeholder: isRecording ? "Listening..." : placeholder,
4420
+ isWaitingForResponse,
4421
+ hasSelectedSession: true,
4422
+ isSessionParamsConfigured,
4423
+ enableVoice: config.enableVoice === true,
4424
+ onVoicePress: config.enableVoice === true ? handleVoicePress : void 0,
4425
+ voiceAvailable: config.enableVoice === true && voiceAvailable,
4426
+ isRecording,
4427
+ transcribedText: inputValue,
4428
+ onCancelRecording: handleCancelRecording,
4429
+ onConfirmRecording: handleConfirmRecording,
4430
+ inputStyle,
4431
+ layout,
4432
+ showResetSession,
4433
+ onResetSession: requestResetSession
4434
+ }
4435
+ );
4436
+ return /* @__PURE__ */ jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
4437
+ "div",
4438
+ {
4439
+ className: cn(
4440
+ "bg-background overflow-hidden flex flex-col flex-[4]",
4441
+ className
4442
+ ),
4443
+ style,
4444
+ children: [
4445
+ children,
4446
+ /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: isEmpty && !hasEverSentMessage ? /* @__PURE__ */ jsx(
4447
+ motion.div,
4448
+ {
4449
+ initial: { opacity: 1 },
4450
+ exit: { opacity: 0 },
4451
+ transition: { duration: 0.3 },
4452
+ className: "payman-empty-centered-layout",
4453
+ children: /* @__PURE__ */ jsxs("div", { className: "payman-empty-centered-inner", children: [
4454
+ /* @__PURE__ */ jsx(
4455
+ MessageList,
4456
+ {
4457
+ messages,
4458
+ isLoading: false,
4459
+ emptyStateText,
4460
+ showEmptyStateIcon,
4461
+ emptyStateComponent,
4462
+ layout,
4463
+ showTimestamps,
4464
+ stage: config.stage || "DEV",
4465
+ animated,
4466
+ showAgentName,
4467
+ agentName,
4468
+ showAvatars,
4469
+ showUserAvatar,
4470
+ showAssistantAvatar,
4471
+ showExecutionSteps,
4472
+ showStreamingDot,
4473
+ streamingStepsText,
4474
+ completedStepsText,
4475
+ onExecutionTraceClick,
4476
+ onLoadMoreMessages,
4477
+ isLoadingMoreMessages,
4478
+ hasMoreMessages
4479
+ }
4480
+ ),
4481
+ /* @__PURE__ */ jsx(
4482
+ motion.div,
4483
+ {
4484
+ initial: { opacity: 0, y: 12 },
4485
+ animate: { opacity: 1, y: 0 },
4486
+ transition: { delay: 0.2, duration: 0.4, ease: [0.25, 0.46, 0.45, 0.94] },
4487
+ className: "payman-empty-centered-input",
4488
+ children: inputElement
4489
+ }
4490
+ )
4491
+ ] })
4492
+ },
4493
+ "empty-centered"
4494
+ ) : /* @__PURE__ */ jsxs(
4495
+ motion.div,
4496
+ {
4497
+ initial: hasEverSentMessage ? { opacity: 0 } : false,
4498
+ animate: { opacity: 1 },
4499
+ transition: { duration: 0.3 },
4500
+ className: "flex flex-col flex-1 min-h-0",
4501
+ children: [
4502
+ /* @__PURE__ */ jsx(
4503
+ MessageList,
4504
+ {
4505
+ messages,
4506
+ isLoading: false,
4507
+ emptyStateText,
4508
+ showEmptyStateIcon,
4509
+ emptyStateComponent,
4510
+ layout,
4511
+ showTimestamps,
4512
+ stage: config.stage || "DEV",
4513
+ animated,
4514
+ showAgentName,
4515
+ agentName,
4516
+ showAvatars,
4517
+ showUserAvatar,
4518
+ showAssistantAvatar,
4519
+ showExecutionSteps,
4520
+ showStreamingDot,
4521
+ streamingStepsText,
4522
+ completedStepsText,
4523
+ onExecutionTraceClick,
4524
+ onLoadMoreMessages,
4525
+ isLoadingMoreMessages,
4526
+ hasMoreMessages
4527
+ }
4528
+ ),
4529
+ inputElement
4530
+ ]
4531
+ },
4532
+ "chat-layout"
2447
4533
  ) }),
2448
4534
  /* @__PURE__ */ jsx(
2449
4535
  UserActionModal,
@@ -2455,12 +4541,40 @@ var PaymanChat = forwardRef(function PaymanChat2({
2455
4541
  onResend: resendOtp,
2456
4542
  clearOtpTrigger: userActionState.clearOtpTrigger
2457
4543
  }
4544
+ ),
4545
+ /* @__PURE__ */ jsx(
4546
+ ResetSessionConfirmModal,
4547
+ {
4548
+ isOpen: isResetSessionConfirmOpen,
4549
+ onClose: closeResetSessionConfirm,
4550
+ onConfirm: performResetSession
4551
+ }
2458
4552
  )
2459
4553
  ]
2460
4554
  }
2461
4555
  ) });
2462
4556
  });
4557
+ var PaymanChatV1Shell = forwardRef(
4558
+ function PaymanChatV1Shell2(props, ref) {
4559
+ const chat = useChat(props.config, props.callbacks);
4560
+ return /* @__PURE__ */ jsx(PaymanChatInner, { ...props, chat, ref });
4561
+ }
4562
+ );
4563
+ var PaymanChatV2Shell = forwardRef(
4564
+ function PaymanChatV2Shell2(props, ref) {
4565
+ const chat = useChatV2(props.config, props.callbacks);
4566
+ return /* @__PURE__ */ jsx(PaymanChatInner, { ...props, chat, ref });
4567
+ }
4568
+ );
4569
+ var PaymanChat = forwardRef(
4570
+ function PaymanChat2(props, ref) {
4571
+ if (props.config.uiVersion !== 1) {
4572
+ return /* @__PURE__ */ jsx(PaymanChatV2Shell, { ...props, ref });
4573
+ }
4574
+ return /* @__PURE__ */ jsx(PaymanChatV1Shell, { ...props, ref });
4575
+ }
4576
+ );
2463
4577
 
2464
- export { PaymanChat, PaymanChatContext, captureSentryError, cn, formatDate, usePaymanChat };
4578
+ export { PaymanChat, PaymanChatContext, cn, formatDate, usePaymanChat };
2465
4579
  //# sourceMappingURL=index.mjs.map
2466
4580
  //# sourceMappingURL=index.mjs.map