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