@paymanai/payman-ask-sdk 1.2.16 → 1.2.18

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.js CHANGED
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  var paymanTypescriptAskSdk = require('@paymanai/payman-typescript-ask-sdk');
4
+ var framerMotion = require('framer-motion');
4
5
  var react = require('react');
5
6
  var clsx = require('clsx');
6
7
  var tailwindMerge = require('tailwind-merge');
7
- var framerMotion = require('framer-motion');
8
8
  var lucideReact = require('lucide-react');
9
9
  var jsxRuntime = require('react/jsx-runtime');
10
10
  var ReactMarkdown = require('react-markdown');
@@ -58,6 +58,7 @@ function formatElapsedTime(ms) {
58
58
  if (ms < 1e3) return `${ms}ms`;
59
59
  return `${(ms / 1e3).toFixed(1)}s`;
60
60
  }
61
+ var AI_DISCLAIMER_TEXT = "AI can make mistakes. Please double-check responses.";
61
62
  function ChatInput({
62
63
  value,
63
64
  onChange,
@@ -73,20 +74,25 @@ function ChatInput({
73
74
  enableVoice = false,
74
75
  onVoicePress,
75
76
  voiceAvailable = false,
76
- isRecording = false
77
+ isRecording = false,
78
+ transcribedText = "",
79
+ onCancelRecording,
80
+ onConfirmRecording,
81
+ showResetSession = false,
82
+ onResetSession
77
83
  }) {
78
84
  const textareaRef = react.useRef(null);
79
85
  const containerRef = react.useRef(null);
80
86
  const prevWaitingRef = react.useRef(isWaitingForResponse);
87
+ const [recordingSeconds, setRecordingSeconds] = react.useState(0);
88
+ const recordingTimerRef = react.useRef(null);
89
+ const [isFocused, setIsFocused] = react.useState(false);
81
90
  react.useEffect(() => {
82
91
  if (textareaRef.current) {
83
92
  textareaRef.current.style.height = "auto";
84
93
  const scrollHeight = textareaRef.current.scrollHeight;
85
94
  const maxHeight = 160;
86
- textareaRef.current.style.height = `${Math.min(
87
- scrollHeight,
88
- maxHeight
89
- )}px`;
95
+ textareaRef.current.style.height = `${Math.min(scrollHeight, maxHeight)}px`;
90
96
  }
91
97
  }, [value]);
92
98
  react.useEffect(() => {
@@ -104,6 +110,25 @@ function ChatInput({
104
110
  });
105
111
  }
106
112
  }, [isWaitingForResponse]);
113
+ react.useEffect(() => {
114
+ if (isRecording) {
115
+ setRecordingSeconds(0);
116
+ recordingTimerRef.current = setInterval(() => {
117
+ setRecordingSeconds((s) => s + 1);
118
+ }, 1e3);
119
+ } else {
120
+ if (recordingTimerRef.current) {
121
+ clearInterval(recordingTimerRef.current);
122
+ recordingTimerRef.current = null;
123
+ }
124
+ setRecordingSeconds(0);
125
+ }
126
+ return () => {
127
+ if (recordingTimerRef.current) {
128
+ clearInterval(recordingTimerRef.current);
129
+ }
130
+ };
131
+ }, [isRecording]);
107
132
  const handleKeyDown = (e) => {
108
133
  if (e.key === "Enter" && !e.shiftKey) {
109
134
  e.preventDefault();
@@ -119,100 +144,180 @@ function ChatInput({
119
144
  if (!isSessionParamsConfigured) return "Configure session params to begin";
120
145
  return placeholder;
121
146
  };
147
+ const formatTime = react.useCallback((seconds) => {
148
+ const mins = Math.floor(seconds / 60);
149
+ const secs = seconds % 60;
150
+ return `${String(mins).padStart(2, "0")}:${String(secs).padStart(2, "0")}`;
151
+ }, []);
152
+ const handleCancel = () => {
153
+ if (onCancelRecording) {
154
+ onCancelRecording();
155
+ } else if (onVoicePress) {
156
+ onVoicePress();
157
+ }
158
+ };
159
+ const handleConfirm = () => {
160
+ if (onConfirmRecording) {
161
+ onConfirmRecording();
162
+ } else if (onVoicePress) {
163
+ onVoicePress();
164
+ }
165
+ };
122
166
  return /* @__PURE__ */ jsxRuntime.jsx(
123
167
  "div",
124
168
  {
125
169
  ref: containerRef,
126
- className: cn("flex-shrink-0 w-full", className),
127
- style: { flexShrink: 0 },
128
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pb-3 pt-1.5 w-full", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full max-w-2xl mx-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(
129
- framerMotion.motion.div,
130
- {
131
- initial: false,
132
- className: cn(
133
- "flex items-end overflow-hidden",
134
- "payman-chat-input"
135
- ),
136
- children: [
137
- /* @__PURE__ */ jsxRuntime.jsx(
138
- "textarea",
139
- {
140
- ref: textareaRef,
141
- value,
142
- onChange: (e) => onChange(e.target.value),
143
- onKeyDown: handleKeyDown,
144
- onClick,
145
- disabled: isInputDisabled,
146
- placeholder: getPlaceholder(),
147
- className: cn(
148
- "payman-chat-input-field",
149
- "focus:outline-none resize-none overflow-y-auto",
150
- "flex-1 min-w-0 py-3"
151
- ),
152
- style: {
153
- minHeight: "44px",
154
- maxHeight: "160px",
155
- paddingLeft: "18px",
156
- paddingRight: "8px"
157
- },
158
- rows: 1
159
- }
160
- ),
161
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 shrink-0 p-2", children: [
162
- showVoiceButton && /* @__PURE__ */ jsxRuntime.jsxs(
163
- "button",
164
- {
165
- type: "button",
166
- onClick: onVoicePress,
167
- disabled: isVoiceButtonDisabled,
168
- className: cn(
169
- "relative flex items-center justify-center",
170
- "w-8 h-8 rounded-full transition-all duration-200",
171
- "payman-chat-input-btn-voice",
172
- isRecording && "recording"
170
+ className: cn("payman-chat-input-wrapper", className),
171
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-chat-input-container", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-chat-input-inner", children: [
172
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: isRecording ? (
173
+ /* ======== Recording State ======== */
174
+ /* @__PURE__ */ jsxRuntime.jsxs(
175
+ framerMotion.motion.div,
176
+ {
177
+ initial: { opacity: 0, y: 6 },
178
+ animate: { opacity: 1, y: 0 },
179
+ exit: { opacity: 0, y: 6 },
180
+ transition: { duration: 0.25, ease: [0.25, 0.46, 0.45, 0.94] },
181
+ className: "payman-chat-input payman-chat-input--recording",
182
+ children: [
183
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-recording-transcript-area", children: /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: transcribedText ? /* @__PURE__ */ jsxRuntime.jsxs(
184
+ framerMotion.motion.p,
185
+ {
186
+ initial: { opacity: 0 },
187
+ animate: { opacity: 1 },
188
+ exit: { opacity: 0 },
189
+ transition: { duration: 0.15 },
190
+ className: "payman-recording-transcript-text",
191
+ children: [
192
+ transcribedText,
193
+ /* @__PURE__ */ jsxRuntime.jsx(
194
+ framerMotion.motion.span,
195
+ {
196
+ className: "payman-recording-cursor",
197
+ animate: { opacity: [1, 0] },
198
+ transition: { duration: 0.8, repeat: Infinity, repeatType: "reverse" }
199
+ }
200
+ )
201
+ ]
202
+ },
203
+ "text"
204
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
205
+ framerMotion.motion.p,
206
+ {
207
+ initial: { opacity: 0 },
208
+ animate: { opacity: 0.5 },
209
+ className: "payman-recording-transcript-placeholder",
210
+ children: "Listening..."
211
+ },
212
+ "placeholder"
213
+ ) }) }),
214
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-recording-bar", children: [
215
+ /* @__PURE__ */ jsxRuntime.jsx(
216
+ "button",
217
+ {
218
+ type: "button",
219
+ onClick: handleCancel,
220
+ className: "payman-recording-btn-cancel",
221
+ "aria-label": "Cancel recording",
222
+ children: "Cancel"
223
+ }
173
224
  ),
174
- "aria-label": isRecording ? "Stop recording" : "Voice input",
175
- children: [
176
- isRecording && /* @__PURE__ */ jsxRuntime.jsx(
177
- "span",
225
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-recording-indicator", children: [
226
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-recording-dot" }),
227
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-recording-timer", children: formatTime(recordingSeconds) })
228
+ ] }),
229
+ /* @__PURE__ */ jsxRuntime.jsx(
230
+ "button",
231
+ {
232
+ type: "button",
233
+ onClick: handleConfirm,
234
+ className: "payman-recording-btn-confirm",
235
+ "aria-label": "Confirm recording",
236
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4", strokeWidth: 2.5 })
237
+ }
238
+ )
239
+ ] })
240
+ ]
241
+ },
242
+ "recording"
243
+ )
244
+ ) : (
245
+ /* ======== Normal Input State ======== */
246
+ /* @__PURE__ */ jsxRuntime.jsxs(
247
+ framerMotion.motion.div,
248
+ {
249
+ initial: false,
250
+ animate: { opacity: 1, y: 0 },
251
+ exit: { opacity: 0, y: 6 },
252
+ transition: { duration: 0.2 },
253
+ className: cn(
254
+ "payman-chat-input",
255
+ isFocused && "payman-chat-input--focused"
256
+ ),
257
+ children: [
258
+ /* @__PURE__ */ jsxRuntime.jsx(
259
+ "textarea",
260
+ {
261
+ ref: textareaRef,
262
+ value,
263
+ onChange: (e) => onChange(e.target.value),
264
+ onKeyDown: handleKeyDown,
265
+ onFocus: () => setIsFocused(true),
266
+ onBlur: () => setIsFocused(false),
267
+ onClick,
268
+ disabled: isInputDisabled,
269
+ placeholder: getPlaceholder(),
270
+ className: "payman-chat-input-field",
271
+ rows: 1
272
+ }
273
+ ),
274
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-chat-input-bottom", children: [
275
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-chat-input-actions-left", children: showResetSession && onResetSession && /* @__PURE__ */ jsxRuntime.jsxs(
276
+ "button",
277
+ {
278
+ type: "button",
279
+ onClick: onResetSession,
280
+ disabled: isWaitingForResponse,
281
+ className: "payman-chat-input-btn-reset",
282
+ "aria-label": "New Session",
283
+ children: [
284
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { className: "w-3.5 h-3.5", strokeWidth: 2.5 }),
285
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-chat-input-btn-reset-tooltip", children: "New Session" })
286
+ ]
287
+ }
288
+ ) }),
289
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-chat-input-actions", children: [
290
+ showVoiceButton && /* @__PURE__ */ jsxRuntime.jsx(
291
+ "button",
178
292
  {
179
- className: "absolute inset-0 rounded-full border-2 animate-ping opacity-40",
180
- style: {
181
- borderColor: "var(--payman-input-btn-voice-recording-ring)"
182
- }
293
+ type: "button",
294
+ onClick: onVoicePress,
295
+ disabled: isVoiceButtonDisabled,
296
+ className: "payman-chat-input-btn-voice",
297
+ "aria-label": "Voice input",
298
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Mic, { className: "w-[18px] h-[18px]" })
183
299
  }
184
300
  ),
185
- isRecording ? /* @__PURE__ */ jsxRuntime.jsx(
186
- lucideReact.Square,
301
+ /* @__PURE__ */ jsxRuntime.jsx(
302
+ "button",
187
303
  {
188
- className: "w-3 h-3 relative z-10",
189
- fill: "currentColor"
304
+ type: "button",
305
+ onClick: onSend,
306
+ disabled: !canSend,
307
+ className: "payman-chat-input-btn-send",
308
+ "aria-label": "Send message",
309
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "w-4 h-4", strokeWidth: 2.5 })
190
310
  }
191
- ) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Mic, { className: "w-4 h-4" })
192
- ]
193
- }
194
- ),
195
- /* @__PURE__ */ jsxRuntime.jsx(
196
- "button",
197
- {
198
- type: "button",
199
- onClick: onSend,
200
- disabled: !canSend,
201
- className: cn(
202
- "flex items-center justify-center",
203
- "w-8 h-8 rounded-full",
204
- "payman-chat-input-btn-send",
205
- "hover:opacity-90 active:scale-95",
206
- "transition-all duration-150"
207
- ),
208
- "aria-label": "Send message",
209
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "w-4 h-4", strokeWidth: 2.5 })
210
- }
211
- )
212
- ] })
213
- ]
214
- }
215
- ) }) })
311
+ )
312
+ ] })
313
+ ] })
314
+ ]
315
+ },
316
+ "input"
317
+ )
318
+ ) }),
319
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-chat-input-disclaimer", children: AI_DISCLAIMER_TEXT })
320
+ ] }) })
216
321
  }
217
322
  );
218
323
  }
@@ -779,6 +884,7 @@ function MessageList({
779
884
  isLoading = false,
780
885
  emptyStateText = "What can I help with?",
781
886
  showEmptyStateIcon = true,
887
+ emptyStateComponent,
782
888
  layout = "full-width",
783
889
  showTimestamps = false,
784
890
  stage = "DEV",
@@ -903,7 +1009,7 @@ function MessageList({
903
1009
  }
904
1010
  if (messages.length === 0) {
905
1011
  const lines = emptyStateText.split("\n").map((l) => l.trim()).filter(Boolean);
906
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("payman-empty-root p-8", className), children: /* @__PURE__ */ jsxRuntime.jsxs(
1012
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("payman-empty-root", className), children: /* @__PURE__ */ jsxRuntime.jsxs(
907
1013
  framerMotion.motion.div,
908
1014
  {
909
1015
  initial: { opacity: 0, y: 20 },
@@ -911,17 +1017,17 @@ function MessageList({
911
1017
  transition: { duration: 0.5, ease: [0.25, 0.46, 0.45, 0.94] },
912
1018
  className: "payman-empty-content",
913
1019
  children: [
914
- showEmptyStateIcon && /* @__PURE__ */ jsxRuntime.jsx(
1020
+ emptyStateComponent && /* @__PURE__ */ jsxRuntime.jsx(
915
1021
  framerMotion.motion.div,
916
1022
  {
917
- initial: { scale: 0.85, opacity: 0 },
1023
+ initial: { scale: 0.9, opacity: 0 },
918
1024
  animate: { scale: 1, opacity: 1 },
919
- transition: { delay: 0.08, duration: 0.45, ease: [0.25, 0.46, 0.45, 0.94] },
920
- className: "payman-empty-icon-wrap",
921
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageCircle, { className: "h-7 w-7 payman-empty-icon", strokeWidth: 1.5 })
1025
+ transition: { delay: 0.05, duration: 0.45, ease: [0.25, 0.46, 0.45, 0.94] },
1026
+ className: "payman-empty-custom-component",
1027
+ children: emptyStateComponent
922
1028
  }
923
1029
  ),
924
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1.5", children: lines.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx(
1030
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-empty-text-group", children: lines.map((line, i) => /* @__PURE__ */ jsxRuntime.jsx(
925
1031
  framerMotion.motion.p,
926
1032
  {
927
1033
  initial: { opacity: 0, y: 6 },
@@ -1463,6 +1569,7 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
1463
1569
  }, ref) {
1464
1570
  const [inputValue, setInputValue] = react.useState("");
1465
1571
  const prevInputValueRef = react.useRef(inputValue);
1572
+ const [hasEverSentMessage, setHasEverSentMessage] = react.useState(false);
1466
1573
  const chat = paymanTypescriptAskSdk.useChat(config, callbacks);
1467
1574
  const {
1468
1575
  messages,
@@ -1475,6 +1582,11 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
1475
1582
  getSessionId,
1476
1583
  getMessages
1477
1584
  } = chat;
1585
+ react.useEffect(() => {
1586
+ if (messages.length > 0 && !hasEverSentMessage) {
1587
+ setHasEverSentMessage(true);
1588
+ }
1589
+ }, [messages.length, hasEverSentMessage]);
1478
1590
  const userActionState = chat.userActionState ?? DEFAULT_USER_ACTION_STATE;
1479
1591
  const approveUserAction = chat.approveUserAction ?? NOOP_ASYNC;
1480
1592
  const rejectUserAction = chat.rejectUserAction ?? NOOP_ASYNC;
@@ -1523,14 +1635,17 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
1523
1635
  isWaitingForResponse
1524
1636
  ]
1525
1637
  );
1638
+ const { onExecutionTraceClick, onResetSession } = callbacks;
1526
1639
  react.useImperativeHandle(ref, () => ({
1527
- resetSession,
1640
+ resetSession: () => {
1641
+ resetSession();
1642
+ onResetSession?.();
1643
+ },
1528
1644
  clearMessages,
1529
1645
  cancelStream,
1530
1646
  getSessionId,
1531
1647
  getMessages
1532
- }), [resetSession, clearMessages, cancelStream, getSessionId, getMessages]);
1533
- const { onExecutionTraceClick } = callbacks;
1648
+ }), [resetSession, clearMessages, cancelStream, getSessionId, getMessages, onResetSession]);
1534
1649
  const {
1535
1650
  placeholder = "Type your message...",
1536
1651
  emptyStateText = "What can I help with?",
@@ -1552,7 +1667,9 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
1552
1667
  animated = true,
1553
1668
  isChatDisabled = false,
1554
1669
  disabledComponent,
1555
- showEmptyStateIcon = true
1670
+ showEmptyStateIcon = true,
1671
+ emptyStateComponent,
1672
+ showResetSession = false
1556
1673
  } = config;
1557
1674
  const isSessionParamsConfigured = react.useMemo(() => {
1558
1675
  if (!sessionParams) return false;
@@ -1560,9 +1677,9 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
1560
1677
  }, [sessionParams?.id, sessionParams?.name]);
1561
1678
  react.useEffect(() => {
1562
1679
  const wasEmpty = prevInputValueRef.current.trim() === "";
1563
- const isEmpty = inputValue.trim() === "";
1680
+ const isEmpty2 = inputValue.trim() === "";
1564
1681
  prevInputValueRef.current = inputValue;
1565
- if (!wasEmpty && isEmpty) {
1682
+ if (!wasEmpty && isEmpty2) {
1566
1683
  clearTranscript();
1567
1684
  if (isRecording) {
1568
1685
  stopRecording();
@@ -1578,14 +1695,23 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
1578
1695
  setInputValue("");
1579
1696
  }
1580
1697
  };
1698
+ const handleCancelRecording = () => {
1699
+ stopRecording();
1700
+ clearTranscript();
1701
+ setInputValue("");
1702
+ };
1703
+ const handleConfirmRecording = () => {
1704
+ stopRecording();
1705
+ };
1581
1706
  const isInputDisabled = isWaitingForResponse || !isSessionParamsConfigured || disableInput;
1707
+ const isEmpty = messages.length === 0;
1582
1708
  if (isChatDisabled) {
1583
1709
  if (disabledComponent) {
1584
1710
  return /* @__PURE__ */ jsxRuntime.jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
1585
1711
  "div",
1586
1712
  {
1587
1713
  className: cn(
1588
- "bg-card overflow-hidden flex flex-col flex-[4]",
1714
+ "bg-background overflow-hidden flex flex-col flex-[4]",
1589
1715
  className
1590
1716
  ),
1591
1717
  style,
@@ -1600,7 +1726,7 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
1600
1726
  "div",
1601
1727
  {
1602
1728
  className: cn(
1603
- "bg-card overflow-hidden flex flex-col flex-[4]",
1729
+ "bg-background overflow-hidden flex flex-col flex-[4]",
1604
1730
  className
1605
1731
  ),
1606
1732
  style,
@@ -1611,62 +1737,138 @@ var PaymanChat = react.forwardRef(function PaymanChat2({
1611
1737
  }
1612
1738
  ) });
1613
1739
  }
1740
+ const inputElement = hasAskPermission && /* @__PURE__ */ jsxRuntime.jsx(
1741
+ ChatInput,
1742
+ {
1743
+ value: inputValue,
1744
+ onChange: setInputValue,
1745
+ onSend: handleSend,
1746
+ onPause: cancelStream,
1747
+ disabled: isInputDisabled,
1748
+ placeholder: isRecording ? "Listening..." : placeholder,
1749
+ isWaitingForResponse,
1750
+ hasSelectedSession: true,
1751
+ isSessionParamsConfigured,
1752
+ enableVoice: config.enableVoice === true,
1753
+ onVoicePress: isRecording ? stopRecording : startRecording,
1754
+ voiceAvailable: config.enableVoice === true && voiceAvailable,
1755
+ isRecording,
1756
+ transcribedText: inputValue,
1757
+ onCancelRecording: handleCancelRecording,
1758
+ onConfirmRecording: handleConfirmRecording,
1759
+ inputStyle,
1760
+ layout,
1761
+ showResetSession,
1762
+ onResetSession: () => {
1763
+ resetSession();
1764
+ onResetSession?.();
1765
+ }
1766
+ }
1767
+ );
1614
1768
  return /* @__PURE__ */ jsxRuntime.jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
1615
1769
  "div",
1616
1770
  {
1617
1771
  className: cn(
1618
- "bg-card overflow-hidden flex flex-col flex-[4]",
1772
+ "bg-background overflow-hidden flex flex-col flex-[4]",
1619
1773
  className
1620
1774
  ),
1621
1775
  style,
1622
1776
  children: [
1623
1777
  children,
1624
- /* @__PURE__ */ jsxRuntime.jsx(
1625
- MessageList,
1626
- {
1627
- messages,
1628
- isLoading: false,
1629
- emptyStateText,
1630
- showEmptyStateIcon,
1631
- layout,
1632
- showTimestamps,
1633
- stage: config.stage || "DEV",
1634
- animated,
1635
- showAgentName,
1636
- agentName,
1637
- showAvatars,
1638
- showUserAvatar,
1639
- showAssistantAvatar,
1640
- showExecutionSteps,
1641
- showStreamingDot,
1642
- streamingStepsText,
1643
- completedStepsText,
1644
- onExecutionTraceClick,
1645
- onLoadMoreMessages,
1646
- isLoadingMoreMessages,
1647
- hasMoreMessages
1648
- }
1649
- ),
1650
- hasAskPermission && /* @__PURE__ */ jsxRuntime.jsx(
1651
- ChatInput,
1652
- {
1653
- value: inputValue,
1654
- onChange: setInputValue,
1655
- onSend: handleSend,
1656
- onPause: cancelStream,
1657
- disabled: isInputDisabled,
1658
- placeholder: isRecording ? "Listening..." : placeholder,
1659
- isWaitingForResponse,
1660
- hasSelectedSession: true,
1661
- isSessionParamsConfigured,
1662
- enableVoice: config.enableVoice === true,
1663
- onVoicePress: isRecording ? stopRecording : startRecording,
1664
- voiceAvailable: config.enableVoice === true && voiceAvailable,
1665
- isRecording,
1666
- inputStyle,
1667
- layout
1668
- }
1669
- ),
1778
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { mode: "wait", children: isEmpty && !hasEverSentMessage ? (
1779
+ /* ---- Centered empty state with input ---- */
1780
+ /* @__PURE__ */ jsxRuntime.jsx(
1781
+ framerMotion.motion.div,
1782
+ {
1783
+ initial: { opacity: 1 },
1784
+ exit: { opacity: 0 },
1785
+ transition: { duration: 0.3 },
1786
+ className: "payman-empty-centered-layout",
1787
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-empty-centered-inner", children: [
1788
+ /* @__PURE__ */ jsxRuntime.jsx(
1789
+ MessageList,
1790
+ {
1791
+ messages,
1792
+ isLoading: false,
1793
+ emptyStateText,
1794
+ showEmptyStateIcon,
1795
+ emptyStateComponent,
1796
+ layout,
1797
+ showTimestamps,
1798
+ stage: config.stage || "DEV",
1799
+ animated,
1800
+ showAgentName,
1801
+ agentName,
1802
+ showAvatars,
1803
+ showUserAvatar,
1804
+ showAssistantAvatar,
1805
+ showExecutionSteps,
1806
+ showStreamingDot,
1807
+ streamingStepsText,
1808
+ completedStepsText,
1809
+ onExecutionTraceClick,
1810
+ onLoadMoreMessages,
1811
+ isLoadingMoreMessages,
1812
+ hasMoreMessages
1813
+ }
1814
+ ),
1815
+ /* @__PURE__ */ jsxRuntime.jsx(
1816
+ framerMotion.motion.div,
1817
+ {
1818
+ initial: { opacity: 0, y: 12 },
1819
+ animate: { opacity: 1, y: 0 },
1820
+ transition: { delay: 0.2, duration: 0.4, ease: [0.25, 0.46, 0.45, 0.94] },
1821
+ className: "payman-empty-centered-input",
1822
+ children: inputElement
1823
+ }
1824
+ )
1825
+ ] })
1826
+ },
1827
+ "empty-centered"
1828
+ )
1829
+ ) : (
1830
+ /* ---- Normal chat layout ---- */
1831
+ /* @__PURE__ */ jsxRuntime.jsxs(
1832
+ framerMotion.motion.div,
1833
+ {
1834
+ initial: hasEverSentMessage ? { opacity: 0 } : false,
1835
+ animate: { opacity: 1 },
1836
+ transition: { duration: 0.3 },
1837
+ className: "flex flex-col flex-1 min-h-0",
1838
+ children: [
1839
+ /* @__PURE__ */ jsxRuntime.jsx(
1840
+ MessageList,
1841
+ {
1842
+ messages,
1843
+ isLoading: false,
1844
+ emptyStateText,
1845
+ showEmptyStateIcon,
1846
+ emptyStateComponent,
1847
+ layout,
1848
+ showTimestamps,
1849
+ stage: config.stage || "DEV",
1850
+ animated,
1851
+ showAgentName,
1852
+ agentName,
1853
+ showAvatars,
1854
+ showUserAvatar,
1855
+ showAssistantAvatar,
1856
+ showExecutionSteps,
1857
+ showStreamingDot,
1858
+ streamingStepsText,
1859
+ completedStepsText,
1860
+ onExecutionTraceClick,
1861
+ onLoadMoreMessages,
1862
+ isLoadingMoreMessages,
1863
+ hasMoreMessages
1864
+ }
1865
+ ),
1866
+ inputElement
1867
+ ]
1868
+ },
1869
+ "chat-layout"
1870
+ )
1871
+ ) }),
1670
1872
  /* @__PURE__ */ jsxRuntime.jsx(
1671
1873
  UserActionModal,
1672
1874
  {