@paymanai/payman-ask-sdk 1.2.24 → 1.2.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -10,6 +10,7 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
10
10
  import ReactMarkdown from 'react-markdown';
11
11
  import remarkGfm from 'remark-gfm';
12
12
  import { createPortal } from 'react-dom';
13
+ import { interpolate } from 'flubber';
13
14
 
14
15
  var PaymanChatContext = createContext(void 0);
15
16
  function usePaymanChat() {
@@ -54,6 +55,114 @@ function formatElapsedTime(ms) {
54
55
  if (ms < 1e3) return `${ms}ms`;
55
56
  return `${(ms / 1e3).toFixed(1)}s`;
56
57
  }
58
+ function captureSentryError(error, context) {
59
+ if (!Sentry.getClient()) return;
60
+ const tags = {};
61
+ if (context.executionId) tags.executionId = context.executionId;
62
+ if (context.sessionId) tags.sessionId = context.sessionId;
63
+ if (context.route) tags.route = context.route;
64
+ if (context.cfRay) tags.cfRay = context.cfRay;
65
+ if (context.customerId) tags.customerId = context.customerId;
66
+ if (context.customerEmail) tags.customerEmail = context.customerEmail;
67
+ const contexts = {
68
+ chat_session: {
69
+ sessionId: context.sessionId ?? null,
70
+ sessionOwnerId: context.sessionOwnerId ?? null,
71
+ executionId: context.executionId ?? null,
72
+ workflowName: context.workflowName ?? null,
73
+ cfRay: context.cfRay ?? null,
74
+ customerId: context.customerId ?? null,
75
+ customerEmail: context.customerEmail ?? null
76
+ }
77
+ };
78
+ if (typeof error === "string") {
79
+ Sentry.captureMessage(error, { level: "error", tags, contexts });
80
+ } else {
81
+ Sentry.captureException(error, { tags, contexts });
82
+ }
83
+ }
84
+ var interceptors = /* @__PURE__ */ new Set();
85
+ var originalFetch = null;
86
+ function patchFetch() {
87
+ if (originalFetch !== null) return;
88
+ if (typeof globalThis === "undefined" || typeof globalThis.fetch !== "function")
89
+ return;
90
+ originalFetch = globalThis.fetch;
91
+ globalThis.fetch = async function(input, init2) {
92
+ const response = await originalFetch.call(this, input, init2);
93
+ if (interceptors.size > 0) {
94
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
95
+ try {
96
+ const cfRay = response.headers.get("cf-ray");
97
+ if (cfRay) {
98
+ for (const entry of interceptors) {
99
+ if (url.includes(entry.urlPattern)) {
100
+ entry.listener(cfRay);
101
+ }
102
+ }
103
+ }
104
+ } catch {
105
+ }
106
+ }
107
+ return response;
108
+ };
109
+ }
110
+ function maybeUnpatchFetch() {
111
+ if (interceptors.size > 0 || originalFetch === null) return;
112
+ globalThis.fetch = originalFetch;
113
+ originalFetch = null;
114
+ }
115
+ function subscribeToCfRay(urlPattern, listener) {
116
+ const entry = { urlPattern, listener };
117
+ patchFetch();
118
+ interceptors.add(entry);
119
+ return () => {
120
+ interceptors.delete(entry);
121
+ maybeUnpatchFetch();
122
+ };
123
+ }
124
+
125
+ // src/utils/errorMessages.ts
126
+ var WORKFLOW_FAILED = "WORKFLOW_FAILED";
127
+ var STREAM_NOT_STARTED = "STREAM_NOT_STARTED";
128
+ var HTTP_ERROR_PREFIX = /^HTTP\s+(\d+)\s*:\s*([\s\S]+)$/;
129
+ function isFriendlyWorkflowError(errorDetails) {
130
+ if (!errorDetails) return false;
131
+ return errorDetails === WORKFLOW_FAILED || errorDetails === STREAM_NOT_STARTED || errorDetails.includes(WORKFLOW_FAILED);
132
+ }
133
+ function parseErrorPayload(payload) {
134
+ try {
135
+ const parsed = JSON.parse(payload);
136
+ if (typeof parsed === "string") {
137
+ return { message: parsed.trim() || void 0 };
138
+ }
139
+ if (typeof parsed === "object" && parsed !== null) {
140
+ const record = parsed;
141
+ return {
142
+ status: typeof record.status === "number" ? record.status : void 0,
143
+ message: typeof record.message === "string" && record.message.trim() ? record.message.trim() : void 0
144
+ };
145
+ }
146
+ } catch {
147
+ }
148
+ return {};
149
+ }
150
+ function getConflictErrorMessage(errorDetails) {
151
+ if (!errorDetails) return void 0;
152
+ const trimmedError = errorDetails.trim();
153
+ const httpMatch = trimmedError.match(HTTP_ERROR_PREFIX);
154
+ const httpStatus = httpMatch ? Number(httpMatch[1]) : void 0;
155
+ const rawPayload = (httpMatch ? httpMatch[2] : trimmedError).trim();
156
+ const payload = parseErrorPayload(rawPayload);
157
+ const status = payload.status ?? httpStatus;
158
+ if (status !== 409) {
159
+ return void 0;
160
+ }
161
+ if (payload.message) {
162
+ return payload.message;
163
+ }
164
+ return rawPayload || void 0;
165
+ }
57
166
  function initSentryIfNeeded(dsn) {
58
167
  if (!dsn) return;
59
168
  if (Sentry.getClient()) return;
@@ -578,48 +687,6 @@ function createMarkdownComponents(options = {}) {
578
687
  td: ({ children }) => /* @__PURE__ */ jsx("td", { className: "p-3 align-middle text-sm whitespace-nowrap", children })
579
688
  };
580
689
  }
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
- }
623
690
  function ThinkingBlock({ text }) {
624
691
  const [isOpen, setIsOpen] = useState(false);
625
692
  const hasContent = typeof text === "string" && text.trim().length > 0;
@@ -2185,16 +2252,19 @@ function UserMessageV2({
2185
2252
  toastPortal,
2186
2253
  /* @__PURE__ */ jsx("div", { className: "payman-v2-user-msg payman-v2-fade-in", children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-user-msg-group", children: [
2187
2254
  /* @__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
- ] }),
2255
+ message.isError && message.errorDetails && (() => {
2256
+ const resolvedError = getConflictErrorMessage(message.errorDetails) ?? message.errorDetails;
2257
+ return /* @__PURE__ */ jsxs("div", { className: "payman-v2-user-msg-error", children: [
2258
+ /* @__PURE__ */ jsx(
2259
+ AlertCircle,
2260
+ {
2261
+ className: "h-3.5 w-3.5 shrink-0",
2262
+ style: { color: "rgba(239, 68, 68, 0.7)", marginTop: "2px" }
2263
+ }
2264
+ ),
2265
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-user-msg-error-text", children: resolvedError })
2266
+ ] });
2267
+ })(),
2198
2268
  (timestamp || hasVisibleActions) && /* @__PURE__ */ jsxs("div", { className: "payman-v2-user-msg-actions", children: [
2199
2269
  timestamp ? /* @__PURE__ */ jsx("span", { className: "payman-v2-user-msg-timestamp", children: timestamp }) : null,
2200
2270
  showCopyAction && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Copy", children: /* @__PURE__ */ jsx(
@@ -2435,6 +2505,188 @@ function MarkdownRendererV2({
2435
2505
  }
2436
2506
  );
2437
2507
  }
2508
+ var PAYMAN_PATH = "M174.005 38.1616C159.62 18.4068 138.406 5.43014 114.263 1.62485C90.1187 -2.18045 65.9302 3.63155 46.1599 17.9906C21.9565 35.5752 6.06885 61.5137 1.39776 91.0344C-3.27333 120.555 3.85231 150.135 21.4358 174.305C43.0508 204.004 74.9451 223.506 111.243 229.244L122.415 231.013V171.273C121.968 171.273 121.522 171.302 121.076 171.302C116.955 171.302 112.82 170.975 108.684 170.321C106.795 170.024 104.92 169.638 103.076 169.207V207.839C76.5368 201.031 53.4045 185.364 37.0706 162.934C22.5218 142.941 16.6309 118.474 20.4838 94.037C24.3515 69.6148 37.502 48.1505 57.5103 33.5983C73.1004 22.2715 92.1865 17.6784 111.228 20.6811C130.269 23.6837 147.005 33.9253 158.355 49.5032C167.117 61.5583 170.673 76.2889 168.337 91.0047C166.016 105.72 158.087 118.653 146.038 127.408C136.815 134.112 125.524 136.832 114.248 135.048C102.972 133.264 93.079 127.214 86.355 117.984C81.2823 111.027 79.2443 102.51 80.5831 94.0073C81.922 85.5049 86.5038 78.0429 93.4658 72.9741C98.6129 69.2283 104.92 67.7121 111.213 68.7081C117.506 69.704 123.039 73.0782 126.788 78.2362C129.481 81.9374 130.567 86.4711 129.853 90.9898C129.139 95.5086 126.699 99.4774 122.995 102.183H146.648C147.719 99.5815 148.492 96.8464 148.939 94.0073C150.456 84.39 148.135 74.743 142.408 66.8797C135.625 57.5597 125.613 51.4207 114.218 49.637C102.823 47.8384 91.4129 50.5734 82.0707 57.3665C70.9285 65.4676 63.6095 77.4037 61.4525 91.0047C59.2955 104.606 62.5831 118.221 70.6905 129.355C80.4344 142.748 94.8195 151.548 111.198 154.134C127.577 156.72 143.97 152.781 157.373 143.03C173.603 131.228 184.269 113.822 187.408 94.0073C190.547 74.193 185.757 54.349 173.96 38.117L174.005 38.1616Z";
2509
+ var CIRCLE_PATH = "M95 36C139.183 36 175 71.817 175 116C175 160.183 139.183 196 95 196C50.817 196 15 160.183 15 116C15 71.817 50.817 36 95 36Z";
2510
+ function easeInOut(t) {
2511
+ return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
2512
+ }
2513
+ var TIMINGS = {
2514
+ // Total loop cycle = sum of all phases (ms)
2515
+ holdLogoMs: 900,
2516
+ morphToCircleMs: 550,
2517
+ holdCircleMs: 1100,
2518
+ morphToLogoMs: 550
2519
+ };
2520
+ var TOTAL_CYCLE = TIMINGS.holdLogoMs + TIMINGS.morphToCircleMs + TIMINGS.holdCircleMs + TIMINGS.morphToLogoMs;
2521
+ function phaseAtTime(elapsed) {
2522
+ let t = elapsed % TOTAL_CYCLE;
2523
+ if (t < TIMINGS.holdLogoMs) {
2524
+ return { kind: "hold-logo" };
2525
+ }
2526
+ t -= TIMINGS.holdLogoMs;
2527
+ if (t < TIMINGS.morphToCircleMs) {
2528
+ return {
2529
+ kind: "morph",
2530
+ direction: 1,
2531
+ progress: easeInOut(t / TIMINGS.morphToCircleMs)
2532
+ };
2533
+ }
2534
+ t -= TIMINGS.morphToCircleMs;
2535
+ if (t < TIMINGS.holdCircleMs) {
2536
+ return { kind: "hold-circle", progress: t / TIMINGS.holdCircleMs };
2537
+ }
2538
+ t -= TIMINGS.holdCircleMs;
2539
+ return {
2540
+ kind: "morph",
2541
+ direction: -1,
2542
+ progress: easeInOut(t / TIMINGS.morphToLogoMs)
2543
+ };
2544
+ }
2545
+ var RING_CX = 95;
2546
+ var RING_CY = 116;
2547
+ var RING_R = 65;
2548
+ var RING_STROKE_WIDTH = 22;
2549
+ var RING_CIRCUMFERENCE = 2 * Math.PI * RING_R;
2550
+ var RING_ARC_FRACTION = 0.3;
2551
+ var cachedInterpolators = null;
2552
+ var pendingInterpolators = null;
2553
+ function buildInterpolators() {
2554
+ const opts = { maxSegmentLength: 8 };
2555
+ return {
2556
+ forward: interpolate(PAYMAN_PATH, CIRCLE_PATH, opts),
2557
+ backward: interpolate(CIRCLE_PATH, PAYMAN_PATH, opts)
2558
+ };
2559
+ }
2560
+ function loadInterpolatorsAsync() {
2561
+ if (cachedInterpolators) return Promise.resolve(cachedInterpolators);
2562
+ if (pendingInterpolators) return pendingInterpolators;
2563
+ pendingInterpolators = new Promise((resolve) => {
2564
+ const run = () => {
2565
+ cachedInterpolators = buildInterpolators();
2566
+ resolve(cachedInterpolators);
2567
+ };
2568
+ const ric = globalThis.requestIdleCallback;
2569
+ if (typeof ric === "function") {
2570
+ ric(run, { timeout: 200 });
2571
+ } else {
2572
+ setTimeout(run, 0);
2573
+ }
2574
+ });
2575
+ return pendingInterpolators;
2576
+ }
2577
+ function PaymanMark() {
2578
+ const pathRef = useRef(null);
2579
+ const ringGroupRef = useRef(null);
2580
+ useEffect(() => {
2581
+ const reduced = window.matchMedia(
2582
+ "(prefers-reduced-motion: reduce)"
2583
+ ).matches;
2584
+ if (reduced) {
2585
+ pathRef.current?.setAttribute("d", PAYMAN_PATH);
2586
+ pathRef.current?.setAttribute("fill-opacity", "1");
2587
+ ringGroupRef.current?.setAttribute("opacity", "0");
2588
+ return;
2589
+ }
2590
+ let raf = 0;
2591
+ let cancelled = false;
2592
+ const start = performance.now();
2593
+ let interpolators = cachedInterpolators;
2594
+ const tick = (now) => {
2595
+ const elapsed = now - start;
2596
+ const phase = phaseAtTime(elapsed);
2597
+ let d;
2598
+ let fillOpacity = 1;
2599
+ let ringOpacity = 0;
2600
+ const spin = elapsed / 900 * 360;
2601
+ switch (phase.kind) {
2602
+ case "hold-logo":
2603
+ d = PAYMAN_PATH;
2604
+ fillOpacity = 1;
2605
+ ringOpacity = 0;
2606
+ break;
2607
+ case "morph": {
2608
+ if (!interpolators) {
2609
+ d = PAYMAN_PATH;
2610
+ fillOpacity = 1;
2611
+ ringOpacity = 0;
2612
+ break;
2613
+ }
2614
+ d = phase.direction === 1 ? interpolators.forward(phase.progress) : interpolators.backward(phase.progress);
2615
+ const p = phase.direction === 1 ? phase.progress : 1 - phase.progress;
2616
+ fillOpacity = p < 0.6 ? 1 : 1 - (p - 0.6) / 0.4;
2617
+ ringOpacity = p < 0.55 ? 0 : (p - 0.55) / 0.45;
2618
+ break;
2619
+ }
2620
+ case "hold-circle":
2621
+ d = CIRCLE_PATH;
2622
+ fillOpacity = 0;
2623
+ ringOpacity = 1;
2624
+ break;
2625
+ }
2626
+ if (pathRef.current) {
2627
+ pathRef.current.setAttribute("d", d);
2628
+ pathRef.current.setAttribute("fill-opacity", fillOpacity.toFixed(3));
2629
+ }
2630
+ if (ringGroupRef.current) {
2631
+ ringGroupRef.current.setAttribute("opacity", ringOpacity.toFixed(3));
2632
+ ringGroupRef.current.setAttribute(
2633
+ "transform",
2634
+ `rotate(${spin.toFixed(2)} ${RING_CX} ${RING_CY})`
2635
+ );
2636
+ }
2637
+ raf = requestAnimationFrame(tick);
2638
+ };
2639
+ raf = requestAnimationFrame(tick);
2640
+ if (!interpolators) {
2641
+ void loadInterpolatorsAsync().then((result) => {
2642
+ if (!cancelled) interpolators = result;
2643
+ });
2644
+ }
2645
+ return () => {
2646
+ cancelled = true;
2647
+ cancelAnimationFrame(raf);
2648
+ };
2649
+ }, []);
2650
+ return /* @__PURE__ */ jsxs(
2651
+ "svg",
2652
+ {
2653
+ className: "payman-v2-thinking-mark",
2654
+ viewBox: "0 0 190 232",
2655
+ "aria-hidden": true,
2656
+ focusable: "false",
2657
+ children: [
2658
+ /* @__PURE__ */ jsx("path", { ref: pathRef, d: PAYMAN_PATH, fill: "currentColor" }),
2659
+ /* @__PURE__ */ jsxs("g", { ref: ringGroupRef, opacity: 0, children: [
2660
+ /* @__PURE__ */ jsx(
2661
+ "circle",
2662
+ {
2663
+ cx: RING_CX,
2664
+ cy: RING_CY,
2665
+ r: RING_R,
2666
+ fill: "none",
2667
+ stroke: "currentColor",
2668
+ strokeWidth: RING_STROKE_WIDTH,
2669
+ strokeOpacity: 0.16
2670
+ }
2671
+ ),
2672
+ /* @__PURE__ */ jsx(
2673
+ "circle",
2674
+ {
2675
+ cx: RING_CX,
2676
+ cy: RING_CY,
2677
+ r: RING_R,
2678
+ fill: "none",
2679
+ stroke: "currentColor",
2680
+ strokeWidth: RING_STROKE_WIDTH,
2681
+ strokeLinecap: "round",
2682
+ strokeDasharray: `${RING_CIRCUMFERENCE * RING_ARC_FRACTION} ${RING_CIRCUMFERENCE}`
2683
+ }
2684
+ )
2685
+ ] })
2686
+ ]
2687
+ }
2688
+ );
2689
+ }
2438
2690
  var CURSOR_MESSAGES = [
2439
2691
  "Analyzing",
2440
2692
  "Processing",
@@ -2445,6 +2697,7 @@ var CURSOR_MESSAGES = [
2445
2697
  "Evaluating",
2446
2698
  "Checking",
2447
2699
  "Planning",
2700
+ "Working",
2448
2701
  "Updating",
2449
2702
  "Validating",
2450
2703
  "Monitoring",
@@ -2468,6 +2721,12 @@ var CURSOR_MESSAGES = [
2468
2721
  "Confirming"
2469
2722
  ];
2470
2723
  var FINAL_CURSOR_MESSAGE = "Finishing up";
2724
+ function getMaxDuration(...values) {
2725
+ const defined = values.filter(
2726
+ (value) => typeof value === "number" && Number.isFinite(value)
2727
+ );
2728
+ return defined.length > 0 ? Math.max(...defined) : void 0;
2729
+ }
2471
2730
  function parseThinkingContent(content) {
2472
2731
  const lines = content.split("\n");
2473
2732
  const out = [];
@@ -2499,13 +2758,39 @@ function parseThinkingContent(content) {
2499
2758
  }
2500
2759
  return out;
2501
2760
  }
2761
+ function AnimatedSeconds({
2762
+ value,
2763
+ className,
2764
+ ariaLabel
2765
+ }) {
2766
+ return /* @__PURE__ */ jsxs("span", { className: cn("payman-v2-thinking-seconds", className), "aria-label": ariaLabel, children: [
2767
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-thinking-seconds-track", "aria-hidden": "true", children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: /* @__PURE__ */ jsx(
2768
+ motion.span,
2769
+ {
2770
+ className: "payman-v2-thinking-seconds-value",
2771
+ initial: { opacity: 0, y: 6, filter: "blur(2px)" },
2772
+ animate: { opacity: 1, y: 0, filter: "blur(0px)" },
2773
+ exit: { opacity: 0, y: -6, filter: "blur(2px)" },
2774
+ transition: { duration: 0.2, ease: [0.22, 1, 0.36, 1] },
2775
+ children: value
2776
+ },
2777
+ value
2778
+ ) }) }),
2779
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-thinking-seconds-suffix", "aria-hidden": "true", children: "s" })
2780
+ ] });
2781
+ }
2502
2782
  function ThinkingBlockV2({
2503
2783
  content,
2504
2784
  isStreaming,
2505
- durationSec
2785
+ durationSec,
2786
+ startedAt
2506
2787
  }) {
2507
2788
  const [open, setOpen] = useState(true);
2508
2789
  const [cursorIdx, setCursorIdx] = useState(0);
2790
+ const [elapsedSec, setElapsedSec] = useState(
2791
+ () => startedAt ? Math.max(0, Math.floor((Date.now() - startedAt) / 1e3)) : 0
2792
+ );
2793
+ const frozenSecRef = useRef(null);
2509
2794
  const prevStreaming = useRef(isStreaming);
2510
2795
  const parsed = useMemo(() => parseThinkingContent(content), [content]);
2511
2796
  const isFinalizingPhase = useMemo(() => {
@@ -2517,9 +2802,26 @@ function ThinkingBlockV2({
2517
2802
  useEffect(() => {
2518
2803
  if (prevStreaming.current && !isStreaming) {
2519
2804
  setOpen(false);
2805
+ if (startedAt) {
2806
+ frozenSecRef.current = Math.max(
2807
+ 0,
2808
+ Math.floor((Date.now() - startedAt) / 1e3)
2809
+ );
2810
+ }
2520
2811
  }
2521
2812
  prevStreaming.current = isStreaming;
2522
- }, [isStreaming]);
2813
+ }, [isStreaming, startedAt]);
2814
+ useEffect(() => {
2815
+ if (!isStreaming || !startedAt) return;
2816
+ const tick = () => {
2817
+ setElapsedSec(
2818
+ Math.max(0, Math.floor((Date.now() - startedAt) / 1e3))
2819
+ );
2820
+ };
2821
+ tick();
2822
+ const id = window.setInterval(tick, 1e3);
2823
+ return () => window.clearInterval(id);
2824
+ }, [isStreaming, startedAt]);
2523
2825
  useEffect(() => {
2524
2826
  if (!isStreaming || isFinalizingPhase) return;
2525
2827
  const id = window.setInterval(() => {
@@ -2527,10 +2829,33 @@ function ThinkingBlockV2({
2527
2829
  }, 4e3);
2528
2830
  return () => window.clearInterval(id);
2529
2831
  }, [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 ",
2832
+ const justStoppedSec = !isStreaming && prevStreaming.current && startedAt ? Math.max(0, Math.floor((Date.now() - startedAt) / 1e3)) : void 0;
2833
+ const finalSec = getMaxDuration(
2532
2834
  durationSec,
2533
- "s"
2835
+ frozenSecRef.current,
2836
+ justStoppedSec,
2837
+ !isStreaming ? elapsedSec : void 0
2838
+ );
2839
+ const headerLabel = isStreaming ? /* @__PURE__ */ jsxs("span", { className: "payman-v2-thinking-header-label", children: [
2840
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-thinking-shimmer", children: "Working on it\u2026" }),
2841
+ startedAt !== void 0 && /* @__PURE__ */ jsx(
2842
+ AnimatedSeconds,
2843
+ {
2844
+ className: "payman-v2-thinking-timer",
2845
+ ariaLabel: `Elapsed ${elapsedSec} seconds`,
2846
+ value: elapsedSec
2847
+ }
2848
+ )
2849
+ ] }) : finalSec !== null && finalSec !== void 0 ? /* @__PURE__ */ jsxs("span", { className: "payman-v2-thinking-header-label", children: [
2850
+ /* @__PURE__ */ jsx("span", { children: "Thought for" }),
2851
+ /* @__PURE__ */ jsx(
2852
+ AnimatedSeconds,
2853
+ {
2854
+ className: "payman-v2-thinking-duration",
2855
+ ariaLabel: `Thought for ${finalSec} seconds`,
2856
+ value: finalSec
2857
+ }
2858
+ )
2534
2859
  ] }) : /* @__PURE__ */ jsx("span", { children: "Thought" });
2535
2860
  const cursorKey = isFinalizingPhase ? "finalizing" : String(cursorIdx);
2536
2861
  const cursorText = isFinalizingPhase ? FINAL_CURSOR_MESSAGE : CURSOR_MESSAGES[cursorIdx];
@@ -2600,27 +2925,28 @@ function ThinkingBlockV2({
2600
2925
  i
2601
2926
  );
2602
2927
  }),
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
- ] })
2928
+ isStreaming && /* @__PURE__ */ jsxs(
2929
+ "div",
2930
+ {
2931
+ className: "payman-v2-thinking-cursor",
2932
+ "aria-live": "polite",
2933
+ children: [
2934
+ /* @__PURE__ */ jsx(PaymanMark, {}),
2935
+ /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
2936
+ motion.span,
2937
+ {
2938
+ className: "payman-v2-thinking-cursor-label payman-v2-thinking-shimmer",
2939
+ initial: { opacity: 0, y: 2 },
2940
+ animate: { opacity: 1, y: 0 },
2941
+ exit: { opacity: 0, y: -2 },
2942
+ transition: { duration: 0.24, ease: [0.4, 0, 0.2, 1] },
2943
+ children: cursorText
2944
+ },
2945
+ cursorKey
2946
+ ) })
2947
+ ]
2948
+ }
2949
+ )
2624
2950
  ] })
2625
2951
  },
2626
2952
  "thinking-content"
@@ -2770,16 +3096,52 @@ function AssistantMessageV2({
2770
3096
  const showLegacyThinkingPhase = !!message.isStreaming && !message.isError && !rawResponseContent && message.streamProgress === "started";
2771
3097
  const responseTypingEnabled = hasEverStreamed.current && Boolean(rawResponseContent) && !message.isError;
2772
3098
  const { displayedText: displayContent, isTyping: isResponseTyping } = useTypingEffect(rawResponseContent, responseTypingEnabled, RESPONSE_SPEED);
3099
+ const resolvedErrorText = (() => {
3100
+ const conflictErrorMessage2 = getConflictErrorMessage(message.errorDetails);
3101
+ if (conflictErrorMessage2) {
3102
+ return conflictErrorMessage2;
3103
+ }
3104
+ if (isFriendlyWorkflowError(message.errorDetails) && !message.errorDetails) {
3105
+ return "Oops, something went wrong. Please try again.";
3106
+ }
3107
+ return message.errorDetails;
3108
+ })();
3109
+ const requestStartedAt = useMemo(() => {
3110
+ if (!message.timestamp) return void 0;
3111
+ const t = Date.parse(message.timestamp);
3112
+ return Number.isFinite(t) ? t : void 0;
3113
+ }, [message.timestamp]);
2773
3114
  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];
3115
+ const steps = message.steps;
3116
+ if (!steps || steps.length === 0) return void 0;
3117
+ const last = steps[steps.length - 1];
3118
+ if (requestStartedAt && last.timestamp) {
3119
+ return Math.max(
3120
+ 0,
3121
+ Math.round((last.timestamp - requestStartedAt) / 1e3)
3122
+ );
3123
+ }
3124
+ const first = steps[0];
2777
3125
  if (first.timestamp && last.timestamp) {
2778
3126
  return Math.round((last.timestamp - first.timestamp) / 1e3);
2779
3127
  }
2780
- const total = message.steps.reduce((sum, s) => sum + (s.elapsedMs || 0), 0);
3128
+ const total = steps.reduce((sum, s) => sum + (s.elapsedMs || 0), 0);
2781
3129
  return total > 0 ? Math.round(total / 1e3) : void 0;
2782
3130
  })();
3131
+ const conflictErrorMessage = getConflictErrorMessage(message.errorDetails);
3132
+ const isConflictError = Boolean(conflictErrorMessage);
3133
+ if (isConflictError) {
3134
+ return /* @__PURE__ */ jsx("div", { className: "payman-v2-assistant-msg payman-v2-fade-in", children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-error", children: [
3135
+ /* @__PURE__ */ jsx(
3136
+ AlertCircle,
3137
+ {
3138
+ className: "payman-v2-assistant-msg-error-icon",
3139
+ style: { width: 16, height: 16 }
3140
+ }
3141
+ ),
3142
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-error-text", children: conflictErrorMessage }) })
3143
+ ] }) });
3144
+ }
2783
3145
  if (message.isError && !displayContent && !hasThinkingContent) {
2784
3146
  return /* @__PURE__ */ jsx("div", { className: "payman-v2-assistant-msg payman-v2-fade-in", children: /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-error", children: [
2785
3147
  /* @__PURE__ */ jsx(
@@ -2789,7 +3151,7 @@ function AssistantMessageV2({
2789
3151
  style: { width: 16, height: 16 }
2790
3152
  }
2791
3153
  ),
2792
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-error-text", children: message.errorDetails || "Something went wrong. Please try again." }) })
3154
+ /* @__PURE__ */ jsx("div", { children: resolvedErrorText ? /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-error-text", children: resolvedErrorText }) : null })
2793
3155
  ] }) });
2794
3156
  }
2795
3157
  if (showLegacyThinkingPhase) {
@@ -2822,7 +3184,7 @@ function AssistantMessageV2({
2822
3184
  executionId: message.executionId
2823
3185
  });
2824
3186
  };
2825
- const hasPartialError = message.isError && displayContent;
3187
+ const hasPartialError = message.isError && displayContent && !isConflictError;
2826
3188
  const isDone = !message.isStreaming && displayContent && !hasPartialError && !isResponseTyping;
2827
3189
  const hasVisibleDoneActions = showCopyAction || showTraceAction;
2828
3190
  const isCancelled = message.isCancelled;
@@ -2879,7 +3241,8 @@ function AssistantMessageV2({
2879
3241
  {
2880
3242
  content: thinkingContent,
2881
3243
  isStreaming: isThinkingStreaming,
2882
- durationSec: thinkingDuration
3244
+ durationSec: thinkingDuration,
3245
+ startedAt: requestStartedAt
2883
3246
  }
2884
3247
  ),
2885
3248
  /* @__PURE__ */ jsx("div", { className: "payman-v2-assistant-msg-content-area", children: displayContent ? /* @__PURE__ */ jsx(
@@ -2908,7 +3271,7 @@ function AssistantMessageV2({
2908
3271
  style: { width: 16, height: 16 }
2909
3272
  }
2910
3273
  ),
2911
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-error-text", children: message.errorDetails || "The response was interrupted." }) })
3274
+ /* @__PURE__ */ jsx("div", { children: resolvedErrorText ? /* @__PURE__ */ jsx("p", { className: "payman-v2-assistant-msg-error-text", children: resolvedErrorText }) : null })
2912
3275
  ] }),
2913
3276
  isDone && hasVisibleDoneActions && /* @__PURE__ */ jsxs("div", { className: "payman-v2-assistant-msg-actions", children: [
2914
3277
  showCopyAction && /* @__PURE__ */ jsx(ActionTooltipV2, { label: "Copy", children: /* @__PURE__ */ jsx(
@@ -3105,76 +3468,72 @@ function VerificationCardV2({
3105
3468
  const handleCancel = useCallback(async () => {
3106
3469
  await onReject(messageId);
3107
3470
  }, [messageId, onReject]);
3471
+ useCallback(async () => {
3472
+ if (otp.length !== OTP_LEN || !/^\d+$/.test(otp) || status !== "pending") {
3473
+ return;
3474
+ }
3475
+ if (lastSubmittedRef.current === otp) return;
3476
+ lastSubmittedRef.current = otp;
3477
+ await onApprove(messageId, otp);
3478
+ }, [messageId, onApprove, otp, status]);
3108
3479
  const busy = status === "verifying";
3480
+ status === "pending" && otp.length === OTP_LEN && /^\d+$/.test(otp);
3109
3481
  if (status === "approved" || status === "rejected") {
3110
3482
  return null;
3111
3483
  }
3112
- return /* @__PURE__ */ jsx(
3484
+ return /* @__PURE__ */ jsxs(
3113
3485
  motion.div,
3114
3486
  {
3115
3487
  className: "payman-v2-verification",
3116
3488
  initial: { opacity: 0, y: 10 },
3117
3489
  animate: { opacity: 1, y: 0 },
3118
3490
  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: [
3491
+ children: [
3492
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-card", children: [
3493
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-header", children: [
3494
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-header-row", children: [
3495
+ /* @__PURE__ */ jsx(
3496
+ ShieldCheck,
3497
+ {
3498
+ className: "payman-v2-verification-icon",
3499
+ size: 18,
3500
+ strokeWidth: 1.75,
3501
+ "aria-hidden": true
3502
+ }
3503
+ ),
3504
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-verification-title", children: "Verify" }),
3505
+ action.amount != null ? /* @__PURE__ */ jsx("span", { className: "payman-v2-verification-amount", children: action.amount }) : action.payeeName ? /* @__PURE__ */ jsx("span", { className: "payman-v2-verification-payee", children: action.payeeName }) : null
3506
+ ] }),
3507
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-verification-description", children: "Enter the 6-digit code sent to your phone" }),
3122
3508
  /* @__PURE__ */ jsx(
3123
- ShieldCheck,
3509
+ OtpInputV2,
3124
3510
  {
3125
- className: "payman-v2-verification-icon",
3126
- size: 18,
3127
- strokeWidth: 1.75,
3128
- "aria-hidden": true
3511
+ value: otp,
3512
+ onChange: setOtp,
3513
+ maxLength: OTP_LEN,
3514
+ disabled: busy,
3515
+ error: otpErrored
3129
3516
  }
3130
3517
  ),
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
3518
+ busy ? /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-submitting", children: [
3519
+ /* @__PURE__ */ jsx(
3520
+ motion.span,
3521
+ {
3522
+ "aria-hidden": true,
3523
+ style: { display: "inline-flex" },
3524
+ animate: { rotate: 360 },
3525
+ transition: {
3526
+ repeat: Infinity,
3527
+ duration: 0.7,
3528
+ ease: "linear"
3529
+ },
3530
+ children: /* @__PURE__ */ jsx(Loader2, { size: 14, strokeWidth: 2 })
3531
+ }
3532
+ ),
3533
+ /* @__PURE__ */ jsx("span", { className: "payman-v2-verification-submitting-text", children: "Verifying..." })
3534
+ ] }) : null
3133
3535
  ] }),
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(
3536
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-verification-actions", children: /* @__PURE__ */ jsx(
3178
3537
  "button",
3179
3538
  {
3180
3539
  type: "button",
@@ -3183,9 +3542,19 @@ function VerificationCardV2({
3183
3542
  onClick: () => void handleCancel(),
3184
3543
  children: "Cancel"
3185
3544
  }
3186
- )
3187
- ] })
3188
- ] })
3545
+ ) })
3546
+ ] }),
3547
+ /* @__PURE__ */ jsx(
3548
+ "button",
3549
+ {
3550
+ type: "button",
3551
+ className: "payman-v2-verification-resend-link",
3552
+ disabled: busy || resendSec > 0,
3553
+ onClick: () => void handleResend(),
3554
+ children: resendSec > 0 ? `Resend (${resendSec}s)` : "Resend"
3555
+ }
3556
+ )
3557
+ ]
3189
3558
  }
3190
3559
  );
3191
3560
  }
@@ -3407,7 +3776,8 @@ var ChatInputV2 = forwardRef(
3407
3776
  onUploadImageClick,
3408
3777
  onAttachFileClick,
3409
3778
  editingMessageId = null,
3410
- onClearEditing
3779
+ onClearEditing,
3780
+ hideSendButton = false
3411
3781
  }, ref) {
3412
3782
  const [value, setValue] = useState("");
3413
3783
  const [isFocused, setIsFocused] = useState(false);
@@ -3504,7 +3874,7 @@ var ChatInputV2 = forwardRef(
3504
3874
  const handleKeyDown = (e) => {
3505
3875
  if (e.key === "Enter" && !e.shiftKey) {
3506
3876
  e.preventDefault();
3507
- if (isStreaming) return;
3877
+ if (isStreaming || hideSendButton) return;
3508
3878
  handleSend();
3509
3879
  }
3510
3880
  };
@@ -3742,7 +4112,7 @@ var ChatInputV2 = forwardRef(
3742
4112
  )
3743
4113
  ] })
3744
4114
  ] }),
3745
- /* @__PURE__ */ jsx("div", { className: "payman-v2-input-controls-right", children: /* @__PURE__ */ jsx(
4115
+ !hideSendButton && /* @__PURE__ */ jsx("div", { className: "payman-v2-input-controls-right", children: /* @__PURE__ */ jsx(
3746
4116
  "button",
3747
4117
  {
3748
4118
  type: "button",
@@ -3918,6 +4288,80 @@ var DEFAULT_USER_ACTION_STATE = {
3918
4288
  };
3919
4289
  var NOOP_ASYNC = async () => {
3920
4290
  };
4291
+ function useSentryChatCallbacks(callbacks, config) {
4292
+ const sentryCtxRef = useRef({});
4293
+ const callbacksRef = useRef(callbacks);
4294
+ callbacksRef.current = callbacks;
4295
+ const initialSessionId = config.initialSessionId;
4296
+ const apiHeaders = config.api.headers;
4297
+ useEffect(() => {
4298
+ sentryCtxRef.current.workflowName = config.workflowName;
4299
+ sentryCtxRef.current.sessionOwnerId = config.sessionParams?.id;
4300
+ if (initialSessionId) {
4301
+ sentryCtxRef.current.sessionId = initialSessionId;
4302
+ }
4303
+ if (apiHeaders) {
4304
+ sentryCtxRef.current.customerId = apiHeaders["x-paygent-wf-mcp-customer-id"] ?? sentryCtxRef.current.customerId;
4305
+ sentryCtxRef.current.customerEmail = apiHeaders["x-paygent-wf-mcp-customer-email"] ?? sentryCtxRef.current.customerEmail;
4306
+ }
4307
+ }, [
4308
+ config.workflowName,
4309
+ config.sessionParams?.id,
4310
+ initialSessionId,
4311
+ apiHeaders
4312
+ ]);
4313
+ useEffect(() => {
4314
+ const endpoint = config.api.streamEndpoint || "/api/workflows/ask/stream";
4315
+ return subscribeToCfRay(endpoint, (cfRay) => {
4316
+ sentryCtxRef.current.cfRay = cfRay;
4317
+ });
4318
+ }, [config.api.streamEndpoint]);
4319
+ return useMemo(
4320
+ () => ({
4321
+ onMessageSent: (msg) => callbacksRef.current?.onMessageSent?.(msg),
4322
+ onStreamStart: () => callbacksRef.current?.onStreamStart?.(),
4323
+ onStreamComplete: (message) => {
4324
+ if (message.executionId) {
4325
+ sentryCtxRef.current.executionId = message.executionId;
4326
+ }
4327
+ if (message.sessionId) {
4328
+ sentryCtxRef.current.sessionId = message.sessionId;
4329
+ }
4330
+ const content = message.content ?? "";
4331
+ const looksLikeRawErr = content.length >= 10 && (content.includes("errorType=") || /failed:\s*\{/.test(content));
4332
+ const completedEmpty = !message.isStreaming && !message.isCancelled && content.length === 0 && (message.streamProgress === "completed" || message.streamProgress === "error");
4333
+ const hasConflict = !!getConflictErrorMessage(message.errorDetails);
4334
+ const hasFriendlyErr = isFriendlyWorkflowError(message.errorDetails);
4335
+ const shouldCapture = message.isError || hasConflict || hasFriendlyErr || looksLikeRawErr || completedEmpty;
4336
+ if (shouldCapture) {
4337
+ sentryCtxRef.current.route = typeof window !== "undefined" ? window.location.pathname : void 0;
4338
+ captureSentryError(
4339
+ `Workflow error: ${message.errorDetails || content || "Unknown error"}`,
4340
+ { ...sentryCtxRef.current }
4341
+ );
4342
+ }
4343
+ callbacksRef.current?.onStreamComplete?.(message);
4344
+ },
4345
+ onError: (error) => {
4346
+ sentryCtxRef.current.route = typeof window !== "undefined" ? window.location.pathname : void 0;
4347
+ captureSentryError(error, { ...sentryCtxRef.current });
4348
+ callbacksRef.current?.onError?.(error);
4349
+ },
4350
+ onSessionIdChange: (sessionId) => {
4351
+ sentryCtxRef.current.sessionId = sessionId;
4352
+ callbacksRef.current?.onSessionIdChange?.(sessionId);
4353
+ },
4354
+ onExecutionTraceClick: (data) => callbacksRef.current?.onExecutionTraceClick?.(data),
4355
+ onResetSession: () => callbacksRef.current?.onResetSession?.(),
4356
+ onUploadImageClick: () => callbacksRef.current?.onUploadImageClick?.(),
4357
+ onAttachFileClick: () => callbacksRef.current?.onAttachFileClick?.(),
4358
+ onUserActionRequired: (req) => callbacksRef.current?.onUserActionRequired?.(req),
4359
+ onUserActionEvent: (evType, msg) => callbacksRef.current?.onUserActionEvent?.(evType, msg)
4360
+ }),
4361
+ // eslint-disable-next-line react-hooks/exhaustive-deps
4362
+ []
4363
+ );
4364
+ }
3921
4365
  var PaymanChatInner = forwardRef(function PaymanChatInner2({
3922
4366
  config,
3923
4367
  callbacks = {},
@@ -4199,6 +4643,7 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
4199
4643
  status
4200
4644
  };
4201
4645
  }, [isUserActionSupported, userActionState.request, userActionState.result]);
4646
+ const hideV2SendDuringVerification = v2UserAction != null && v2UserAction.status !== "approved" && v2UserAction.status !== "rejected";
4202
4647
  const handleV2Send = (text) => {
4203
4648
  if (isRecording) stopRecording();
4204
4649
  if (text.trim() && !disableInput && isSessionParamsConfigured) {
@@ -4317,7 +4762,8 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
4317
4762
  onUploadImageClick,
4318
4763
  onAttachFileClick,
4319
4764
  editingMessageId,
4320
- onClearEditing: handleClearEditing
4765
+ onClearEditing: handleClearEditing,
4766
+ hideSendButton: hideV2SendDuringVerification
4321
4767
  }
4322
4768
  )
4323
4769
  }
@@ -4381,7 +4827,8 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
4381
4827
  onUploadImageClick,
4382
4828
  onAttachFileClick,
4383
4829
  editingMessageId,
4384
- onClearEditing: handleClearEditing
4830
+ onClearEditing: handleClearEditing,
4831
+ hideSendButton: hideV2SendDuringVerification
4385
4832
  }
4386
4833
  )
4387
4834
  ]
@@ -4556,13 +5003,15 @@ var PaymanChatInner = forwardRef(function PaymanChatInner2({
4556
5003
  });
4557
5004
  var PaymanChatV1Shell = forwardRef(
4558
5005
  function PaymanChatV1Shell2(props, ref) {
4559
- const chat = useChat(props.config, props.callbacks);
5006
+ const mergedCallbacks = useSentryChatCallbacks(props.callbacks, props.config);
5007
+ const chat = useChat(props.config, mergedCallbacks);
4560
5008
  return /* @__PURE__ */ jsx(PaymanChatInner, { ...props, chat, ref });
4561
5009
  }
4562
5010
  );
4563
5011
  var PaymanChatV2Shell = forwardRef(
4564
5012
  function PaymanChatV2Shell2(props, ref) {
4565
- const chat = useChatV2(props.config, props.callbacks);
5013
+ const mergedCallbacks = useSentryChatCallbacks(props.callbacks, props.config);
5014
+ const chat = useChatV2(props.config, mergedCallbacks);
4566
5015
  return /* @__PURE__ */ jsx(PaymanChatInner, { ...props, chat, ref });
4567
5016
  }
4568
5017
  );
@@ -4575,6 +5024,6 @@ var PaymanChat = forwardRef(
4575
5024
  }
4576
5025
  );
4577
5026
 
4578
- export { PaymanChat, PaymanChatContext, cn, formatDate, usePaymanChat };
5027
+ export { PaymanChat, PaymanChatContext, captureSentryError, cn, formatDate, usePaymanChat };
4579
5028
  //# sourceMappingURL=index.mjs.map
4580
5029
  //# sourceMappingURL=index.mjs.map