@paymanai/payman-ask-sdk 4.0.25 → 4.0.26

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,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var react = require('react');
3
+ var React = require('react');
4
4
  var framerMotion = require('framer-motion');
5
5
  var clsx = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
@@ -33,6 +33,7 @@ function _interopNamespace(e) {
33
33
  return Object.freeze(n);
34
34
  }
35
35
 
36
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
36
37
  var Sentry__namespace = /*#__PURE__*/_interopNamespace(Sentry);
37
38
  var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
38
39
  var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
@@ -300,6 +301,8 @@ function getEventMessage(event) {
300
301
  }
301
302
  case "RUN_IN_PROGRESS":
302
303
  return event.partialText || "Thinking...";
304
+ case "LLM_CALL_STARTED":
305
+ return event.description || "";
303
306
  case "RUN_COMPLETED":
304
307
  return "Agent run completed";
305
308
  case "RUN_FAILED":
@@ -437,7 +440,8 @@ function createInitialV2State() {
437
440
  finalData: void 0,
438
441
  steps: [],
439
442
  stepCounter: 0,
440
- currentExecutingStepId: void 0
443
+ currentExecutingStepId: void 0,
444
+ trailingActivity: false
441
445
  };
442
446
  }
443
447
  function upsertUserAction(state, req) {
@@ -459,6 +463,7 @@ function processStreamEventV2(rawEvent, state) {
459
463
  if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
460
464
  if (event.executionId) state.executionId = event.executionId;
461
465
  if (event.sessionId) state.sessionId = event.sessionId;
466
+ if (state.finalResponse) state.trailingActivity = true;
462
467
  const description = typeof event.description === "string" ? event.description : "";
463
468
  if (description) {
464
469
  for (let i = state.steps.length - 1; i >= 0; i--) {
@@ -493,7 +498,12 @@ function processStreamEventV2(rawEvent, state) {
493
498
  state.lastEventType = eventType;
494
499
  break;
495
500
  }
501
+ case "LLM_CALL_STARTED":
502
+ if (state.finalResponse) state.trailingActivity = true;
503
+ state.lastEventType = eventType;
504
+ break;
496
505
  case "INTENT_STARTED": {
506
+ if (state.finalResponse) state.trailingActivity = true;
497
507
  const stepId = `step-${state.stepCounter++}`;
498
508
  state.steps.push({
499
509
  id: stepId,
@@ -509,6 +519,7 @@ function processStreamEventV2(rawEvent, state) {
509
519
  break;
510
520
  }
511
521
  case "INTENT_COMPLETED": {
522
+ if (state.finalResponse) state.trailingActivity = true;
512
523
  const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
513
524
  if (intentStep) {
514
525
  intentStep.status = "completed";
@@ -540,6 +551,7 @@ function processStreamEventV2(rawEvent, state) {
540
551
  step2.status = "completed";
541
552
  }
542
553
  });
554
+ state.trailingActivity = false;
543
555
  state.lastEventType = eventType;
544
556
  break;
545
557
  }
@@ -611,6 +623,7 @@ function processStreamEventV2(rawEvent, state) {
611
623
  case "WORKFLOW_ERROR":
612
624
  state.hasError = true;
613
625
  state.errorMessage = event.errorMessage || event.message || "Workflow error";
626
+ state.trailingActivity = false;
614
627
  state.lastEventType = eventType;
615
628
  break;
616
629
  // ---- K2 pipeline stage lifecycle events ----
@@ -853,12 +866,12 @@ async function resolveRagImageUrls(config, content, signal) {
853
866
  }
854
867
  var FRIENDLY_ERROR_MESSAGE = "Oops, something went wrong. Please try again.";
855
868
  function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForResponse) {
856
- const abortControllerRef = react.useRef(null);
857
- const configRef = react.useRef(config);
869
+ const abortControllerRef = React.useRef(null);
870
+ const configRef = React.useRef(config);
858
871
  configRef.current = config;
859
- const callbacksRef = react.useRef(callbacks);
872
+ const callbacksRef = React.useRef(callbacks);
860
873
  callbacksRef.current = callbacks;
861
- const startStream = react.useCallback(
874
+ const startStream = React.useCallback(
862
875
  async (userMessage, streamingId, sessionId, externalAbortController, options) => {
863
876
  abortControllerRef.current?.abort();
864
877
  const abortController = externalAbortController ?? new AbortController();
@@ -899,7 +912,9 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
899
912
  const latestUsefulStep = [...state.steps].reverse().find(
900
913
  (s) => s.message && !isBlandStatus(s.message)
901
914
  );
902
- const currentMessage = useful(activeStep?.message) ?? useful(lastInProgressStep?.message) ?? latestUsefulStep?.message ?? useful(getEventMessage(event)) ?? // Last-resort: every candidate is bland (very first event,
915
+ const eventTypeUpper = typeof event.eventType === "string" ? event.eventType.toUpperCase() : "";
916
+ const liveEventLabel = eventTypeUpper === "KEEP_ALIVE" || eventTypeUpper === "LLM_CALL_STARTED" ? useful(getEventMessage(event)) : void 0;
917
+ const currentMessage = useful(activeStep?.message) ?? useful(lastInProgressStep?.message) ?? liveEventLabel ?? latestUsefulStep?.message ?? useful(getEventMessage(event)) ?? // Last-resort: every candidate is bland (very first event,
903
918
  // nothing useful seen yet). Render the bland label so the
904
919
  // bubble isn't blank.
905
920
  activeStep?.message ?? lastInProgressStep?.message ?? getEventMessage(event);
@@ -924,6 +939,7 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
924
939
  streamingContent: state.finalResponse,
925
940
  content: "",
926
941
  currentMessage,
942
+ hasTrailingActivity: state.trailingActivity,
927
943
  streamProgress: "processing",
928
944
  isError: false,
929
945
  steps: [...state.steps],
@@ -1057,7 +1073,7 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
1057
1073
  },
1058
1074
  [setMessages, setIsWaitingForResponse]
1059
1075
  );
1060
- const cancelStream = react.useCallback(() => {
1076
+ const cancelStream = React.useCallback(() => {
1061
1077
  abortControllerRef.current?.abort();
1062
1078
  }, []);
1063
1079
  return {
@@ -1168,24 +1184,24 @@ function getSessionIdFromMessages(messages) {
1168
1184
  return messages.find((message) => message.sessionId)?.sessionId;
1169
1185
  }
1170
1186
  function useChatV2(config, callbacks = {}) {
1171
- const [messages, setMessages] = react.useState(() => getStoredOrInitialMessages(config));
1172
- const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(() => {
1187
+ const [messages, setMessages] = React.useState(() => getStoredOrInitialMessages(config));
1188
+ const [isWaitingForResponse, setIsWaitingForResponse] = React.useState(() => {
1173
1189
  if (!config.userId) return false;
1174
1190
  return activeStreamStore.get(config.userId)?.isWaiting ?? false;
1175
1191
  });
1176
- const sessionIdRef = react.useRef(
1192
+ const sessionIdRef = React.useRef(
1177
1193
  getSessionIdFromMessages(getStoredOrInitialMessages(config)) ?? config.initialSessionId ?? void 0
1178
1194
  );
1179
- const prevUserIdRef = react.useRef(config.userId);
1180
- const streamUserIdRef = react.useRef(void 0);
1181
- const subscriptionPrevUserIdRef = react.useRef(config.userId);
1182
- const callbacksRef = react.useRef(callbacks);
1195
+ const prevUserIdRef = React.useRef(config.userId);
1196
+ const streamUserIdRef = React.useRef(void 0);
1197
+ const subscriptionPrevUserIdRef = React.useRef(config.userId);
1198
+ const callbacksRef = React.useRef(callbacks);
1183
1199
  callbacksRef.current = callbacks;
1184
- const configRef = react.useRef(config);
1200
+ const configRef = React.useRef(config);
1185
1201
  configRef.current = config;
1186
- const messagesRef = react.useRef(messages);
1202
+ const messagesRef = React.useRef(messages);
1187
1203
  messagesRef.current = messages;
1188
- const storeAwareSetMessages = react.useCallback(
1204
+ const storeAwareSetMessages = React.useCallback(
1189
1205
  (updater) => {
1190
1206
  const streamUserId = streamUserIdRef.current;
1191
1207
  const currentUserId = configRef.current.userId;
@@ -1200,7 +1216,7 @@ function useChatV2(config, callbacks = {}) {
1200
1216
  // eslint-disable-next-line react-hooks/exhaustive-deps
1201
1217
  []
1202
1218
  );
1203
- const storeAwareSetIsWaiting = react.useCallback(
1219
+ const storeAwareSetIsWaiting = React.useCallback(
1204
1220
  (waiting) => {
1205
1221
  const streamUserId = streamUserIdRef.current;
1206
1222
  const currentUserId = configRef.current.userId;
@@ -1215,11 +1231,11 @@ function useChatV2(config, callbacks = {}) {
1215
1231
  // eslint-disable-next-line react-hooks/exhaustive-deps
1216
1232
  []
1217
1233
  );
1218
- const [userActionState, setUserActionState] = react.useState(() => {
1234
+ const [userActionState, setUserActionState] = React.useState(() => {
1219
1235
  if (!config.userId) return EMPTY_USER_ACTION_STATE2;
1220
1236
  return activeStreamStore.get(config.userId)?.userActionState ?? EMPTY_USER_ACTION_STATE2;
1221
1237
  });
1222
- const storeAwareSetUserActionState = react.useCallback(
1238
+ const storeAwareSetUserActionState = React.useCallback(
1223
1239
  (updater) => {
1224
1240
  const streamUserId = streamUserIdRef.current;
1225
1241
  const currentUserId = configRef.current.userId;
@@ -1237,7 +1253,7 @@ function useChatV2(config, callbacks = {}) {
1237
1253
  // eslint-disable-next-line react-hooks/exhaustive-deps
1238
1254
  []
1239
1255
  );
1240
- const wrappedCallbacks = react.useMemo(() => ({
1256
+ const wrappedCallbacks = React.useMemo(() => ({
1241
1257
  ...callbacksRef.current,
1242
1258
  onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
1243
1259
  onStreamStart: () => callbacksRef.current.onStreamStart?.(),
@@ -1266,7 +1282,7 @@ function useChatV2(config, callbacks = {}) {
1266
1282
  storeAwareSetMessages,
1267
1283
  storeAwareSetIsWaiting
1268
1284
  );
1269
- const sendMessage = react.useCallback(
1285
+ const sendMessage = React.useCallback(
1270
1286
  async (userMessage, options) => {
1271
1287
  if (!userMessage.trim()) return;
1272
1288
  if (!sessionIdRef.current && configRef.current.autoGenerateSessionId !== false) {
@@ -1326,16 +1342,16 @@ function useChatV2(config, callbacks = {}) {
1326
1342
  },
1327
1343
  [startStream]
1328
1344
  );
1329
- const clearMessages = react.useCallback(() => {
1345
+ const clearMessages = React.useCallback(() => {
1330
1346
  if (configRef.current.userId) {
1331
1347
  chatStore.delete(configRef.current.userId);
1332
1348
  }
1333
1349
  setMessages([]);
1334
1350
  }, []);
1335
- const prependMessages = react.useCallback((msgs) => {
1351
+ const prependMessages = React.useCallback((msgs) => {
1336
1352
  setMessages((prev) => [...msgs, ...prev]);
1337
1353
  }, []);
1338
- const cancelStream = react.useCallback(() => {
1354
+ const cancelStream = React.useCallback(() => {
1339
1355
  const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
1340
1356
  if (streamUserId) {
1341
1357
  activeStreamStore.abort(streamUserId);
@@ -1359,7 +1375,7 @@ function useChatV2(config, callbacks = {}) {
1359
1375
  })
1360
1376
  );
1361
1377
  }, [cancelStreamManager, storeAwareSetUserActionState]);
1362
- const resetSession = react.useCallback(() => {
1378
+ const resetSession = React.useCallback(() => {
1363
1379
  const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
1364
1380
  if (streamUserId) {
1365
1381
  activeStreamStore.abort(streamUserId);
@@ -1374,13 +1390,13 @@ function useChatV2(config, callbacks = {}) {
1374
1390
  setIsWaitingForResponse(false);
1375
1391
  storeAwareSetUserActionState(EMPTY_USER_ACTION_STATE2);
1376
1392
  }, []);
1377
- const getSessionId = react.useCallback(() => {
1393
+ const getSessionId = React.useCallback(() => {
1378
1394
  return sessionIdRef.current;
1379
1395
  }, []);
1380
- const getMessages = react.useCallback(() => {
1396
+ const getMessages = React.useCallback(() => {
1381
1397
  return messages;
1382
1398
  }, [messages]);
1383
- const setPromptStatus = react.useCallback(
1399
+ const setPromptStatus = React.useCallback(
1384
1400
  (userActionId, status) => {
1385
1401
  storeAwareSetUserActionState((prev) => ({
1386
1402
  ...prev,
@@ -1391,13 +1407,13 @@ function useChatV2(config, callbacks = {}) {
1391
1407
  },
1392
1408
  [storeAwareSetUserActionState]
1393
1409
  );
1394
- const removePrompt = react.useCallback((userActionId) => {
1410
+ const removePrompt = React.useCallback((userActionId) => {
1395
1411
  storeAwareSetUserActionState((prev) => ({
1396
1412
  ...prev,
1397
1413
  prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
1398
1414
  }));
1399
1415
  }, [storeAwareSetUserActionState]);
1400
- const submitUserAction2 = react.useCallback(
1416
+ const submitUserAction2 = React.useCallback(
1401
1417
  async (userActionId, content) => {
1402
1418
  setPromptStatus(userActionId, "submitting");
1403
1419
  try {
@@ -1415,7 +1431,7 @@ function useChatV2(config, callbacks = {}) {
1415
1431
  },
1416
1432
  [removePrompt, setPromptStatus]
1417
1433
  );
1418
- const cancelUserAction2 = react.useCallback(
1434
+ const cancelUserAction2 = React.useCallback(
1419
1435
  async (userActionId) => {
1420
1436
  setPromptStatus(userActionId, "submitting");
1421
1437
  try {
@@ -1433,7 +1449,7 @@ function useChatV2(config, callbacks = {}) {
1433
1449
  },
1434
1450
  [removePrompt, setPromptStatus]
1435
1451
  );
1436
- const resendUserAction2 = react.useCallback(
1452
+ const resendUserAction2 = React.useCallback(
1437
1453
  async (userActionId) => {
1438
1454
  setPromptStatus(userActionId, "submitting");
1439
1455
  try {
@@ -1451,7 +1467,7 @@ function useChatV2(config, callbacks = {}) {
1451
1467
  },
1452
1468
  [setPromptStatus]
1453
1469
  );
1454
- const expireUserAction2 = react.useCallback(
1470
+ const expireUserAction2 = React.useCallback(
1455
1471
  async (userActionId) => {
1456
1472
  setPromptStatus(userActionId, "expired");
1457
1473
  try {
@@ -1464,13 +1480,13 @@ function useChatV2(config, callbacks = {}) {
1464
1480
  },
1465
1481
  [setPromptStatus]
1466
1482
  );
1467
- const dismissNotification = react.useCallback((id) => {
1483
+ const dismissNotification = React.useCallback((id) => {
1468
1484
  storeAwareSetUserActionState((prev) => ({
1469
1485
  ...prev,
1470
1486
  notifications: prev.notifications.filter((n) => n.id !== id)
1471
1487
  }));
1472
1488
  }, [storeAwareSetUserActionState]);
1473
- react.useEffect(() => {
1489
+ React.useEffect(() => {
1474
1490
  const prevSubscriptionUserId = subscriptionPrevUserIdRef.current;
1475
1491
  subscriptionPrevUserIdRef.current = config.userId;
1476
1492
  const { userId } = config;
@@ -1492,7 +1508,7 @@ function useChatV2(config, callbacks = {}) {
1492
1508
  }
1493
1509
  return unsubscribe;
1494
1510
  }, [config.userId]);
1495
- react.useEffect(() => {
1511
+ React.useEffect(() => {
1496
1512
  if (!config.userId) return;
1497
1513
  if (prevUserIdRef.current !== config.userId) return;
1498
1514
  const toSave = messages.filter((m) => !m.isStreaming);
@@ -1500,14 +1516,14 @@ function useChatV2(config, callbacks = {}) {
1500
1516
  chatStore.set(config.userId, toSave);
1501
1517
  }
1502
1518
  }, [messages, config.userId]);
1503
- react.useEffect(() => {
1519
+ React.useEffect(() => {
1504
1520
  if (!config.userId || activeStreamStore.has(config.userId)) return;
1505
1521
  if (!config.initialMessages?.length || messagesRef.current.length > 0) return;
1506
1522
  chatStore.set(config.userId, config.initialMessages);
1507
1523
  setMessages(config.initialMessages);
1508
1524
  sessionIdRef.current = getSessionIdFromMessages(config.initialMessages) ?? config.initialSessionId;
1509
1525
  }, [config.initialMessages, config.initialSessionId, config.userId]);
1510
- react.useEffect(() => {
1526
+ React.useEffect(() => {
1511
1527
  const prevUserId = prevUserIdRef.current;
1512
1528
  prevUserIdRef.current = config.userId;
1513
1529
  if (prevUserId === config.userId) return;
@@ -1557,12 +1573,12 @@ function getSpeechRecognition() {
1557
1573
  return window.SpeechRecognition || window.webkitSpeechRecognition || null;
1558
1574
  }
1559
1575
  function useVoice(config = {}, callbacks = {}) {
1560
- const [voiceState, setVoiceState] = react.useState("idle");
1561
- const [transcribedText, setTranscribedText] = react.useState("");
1562
- const [isAvailable, setIsAvailable] = react.useState(false);
1563
- const [isRecording, setIsRecording] = react.useState(false);
1564
- const recognitionRef = react.useRef(null);
1565
- const autoStopTimerRef = react.useRef(null);
1576
+ const [voiceState, setVoiceState] = React.useState("idle");
1577
+ const [transcribedText, setTranscribedText] = React.useState("");
1578
+ const [isAvailable, setIsAvailable] = React.useState(false);
1579
+ const [isRecording, setIsRecording] = React.useState(false);
1580
+ const recognitionRef = React.useRef(null);
1581
+ const autoStopTimerRef = React.useRef(null);
1566
1582
  const {
1567
1583
  lang = "en-US",
1568
1584
  interimResults = true,
@@ -1571,14 +1587,14 @@ function useVoice(config = {}, callbacks = {}) {
1571
1587
  autoStopAfterSilence
1572
1588
  } = config;
1573
1589
  const { onStart, onEnd, onResult, onError, onStateChange } = callbacks;
1574
- react.useEffect(() => {
1590
+ React.useEffect(() => {
1575
1591
  const SpeechRecognitionAPI = getSpeechRecognition();
1576
1592
  setIsAvailable(SpeechRecognitionAPI !== null);
1577
1593
  }, []);
1578
- react.useEffect(() => {
1594
+ React.useEffect(() => {
1579
1595
  onStateChange?.(voiceState);
1580
1596
  }, [voiceState, onStateChange]);
1581
- const requestPermissions = react.useCallback(async () => {
1597
+ const requestPermissions = React.useCallback(async () => {
1582
1598
  try {
1583
1599
  const result = await navigator.mediaDevices.getUserMedia({
1584
1600
  audio: true
@@ -1595,7 +1611,7 @@ function useVoice(config = {}, callbacks = {}) {
1595
1611
  };
1596
1612
  }
1597
1613
  }, []);
1598
- const getPermissions = react.useCallback(async () => {
1614
+ const getPermissions = React.useCallback(async () => {
1599
1615
  if (typeof navigator === "undefined" || !navigator.permissions) {
1600
1616
  return {
1601
1617
  granted: false,
@@ -1617,13 +1633,13 @@ function useVoice(config = {}, callbacks = {}) {
1617
1633
  };
1618
1634
  }
1619
1635
  }, []);
1620
- const clearAutoStopTimer = react.useCallback(() => {
1636
+ const clearAutoStopTimer = React.useCallback(() => {
1621
1637
  if (autoStopTimerRef.current) {
1622
1638
  clearTimeout(autoStopTimerRef.current);
1623
1639
  autoStopTimerRef.current = null;
1624
1640
  }
1625
1641
  }, []);
1626
- const resetAutoStopTimer = react.useCallback(() => {
1642
+ const resetAutoStopTimer = React.useCallback(() => {
1627
1643
  clearAutoStopTimer();
1628
1644
  if (autoStopAfterSilence && autoStopAfterSilence > 0) {
1629
1645
  autoStopTimerRef.current = setTimeout(() => {
@@ -1633,7 +1649,7 @@ function useVoice(config = {}, callbacks = {}) {
1633
1649
  }, autoStopAfterSilence);
1634
1650
  }
1635
1651
  }, [autoStopAfterSilence, clearAutoStopTimer, isRecording]);
1636
- const stopRecording = react.useCallback(() => {
1652
+ const stopRecording = React.useCallback(() => {
1637
1653
  if (recognitionRef.current) {
1638
1654
  try {
1639
1655
  recognitionRef.current.stop();
@@ -1645,7 +1661,7 @@ function useVoice(config = {}, callbacks = {}) {
1645
1661
  setIsRecording(false);
1646
1662
  setVoiceState("idle");
1647
1663
  }, [clearAutoStopTimer]);
1648
- const startRecording = react.useCallback(async () => {
1664
+ const startRecording = React.useCallback(async () => {
1649
1665
  const SpeechRecognitionAPI = getSpeechRecognition();
1650
1666
  if (!SpeechRecognitionAPI) {
1651
1667
  onError?.("Speech recognition not supported in this browser");
@@ -1735,15 +1751,15 @@ function useVoice(config = {}, callbacks = {}) {
1735
1751
  resetAutoStopTimer,
1736
1752
  clearAutoStopTimer
1737
1753
  ]);
1738
- const clearTranscript = react.useCallback(() => {
1754
+ const clearTranscript = React.useCallback(() => {
1739
1755
  setTranscribedText("");
1740
1756
  }, []);
1741
- const reset = react.useCallback(() => {
1757
+ const reset = React.useCallback(() => {
1742
1758
  stopRecording();
1743
1759
  setTranscribedText("");
1744
1760
  setVoiceState("idle");
1745
1761
  }, [stopRecording]);
1746
- react.useEffect(() => {
1762
+ React.useEffect(() => {
1747
1763
  return () => {
1748
1764
  if (recognitionRef.current) {
1749
1765
  try {
@@ -1883,9 +1899,9 @@ function buildContent(schema, values) {
1883
1899
  }
1884
1900
  return content;
1885
1901
  }
1886
- var PaymanChatContext = react.createContext(void 0);
1902
+ var PaymanChatContext = React.createContext(void 0);
1887
1903
  function usePaymanChat() {
1888
- const context = react.useContext(PaymanChatContext);
1904
+ const context = React.useContext(PaymanChatContext);
1889
1905
  if (!context) {
1890
1906
  throw new Error("usePaymanChat must be used within a PaymanChat component");
1891
1907
  }
@@ -2082,6 +2098,9 @@ function getConflictErrorMessage(errorDetails) {
2082
2098
  }
2083
2099
  function initSentryIfNeeded(dsn) {
2084
2100
  if (!dsn) return;
2101
+ if (typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1")) {
2102
+ return;
2103
+ }
2085
2104
  if (Sentry__namespace.getClient()) return;
2086
2105
  Sentry__namespace.init({
2087
2106
  dsn,
@@ -2143,8 +2162,8 @@ function ImageLightbox({
2143
2162
  alt = "",
2144
2163
  onClose
2145
2164
  }) {
2146
- const [isMounted, setIsMounted] = react.useState(false);
2147
- const [isImageLoaded, setIsImageLoaded] = react.useState(false);
2165
+ const [isMounted, setIsMounted] = React.useState(false);
2166
+ const [isImageLoaded, setIsImageLoaded] = React.useState(false);
2148
2167
  const overlayStyle = {
2149
2168
  position: "fixed",
2150
2169
  inset: 0,
@@ -2165,14 +2184,14 @@ function ImageLightbox({
2165
2184
  justifyContent: "center",
2166
2185
  overflow: "hidden"
2167
2186
  };
2168
- react.useEffect(() => {
2187
+ React.useEffect(() => {
2169
2188
  setIsMounted(true);
2170
2189
  return () => setIsMounted(false);
2171
2190
  }, []);
2172
- react.useEffect(() => {
2191
+ React.useEffect(() => {
2173
2192
  setIsImageLoaded(false);
2174
2193
  }, [src]);
2175
- react.useEffect(() => {
2194
+ React.useEffect(() => {
2176
2195
  if (typeof document === "undefined") return;
2177
2196
  const previousOverflow = document.body.style.overflow;
2178
2197
  document.body.style.overflow = "hidden";
@@ -2180,7 +2199,7 @@ function ImageLightbox({
2180
2199
  document.body.style.overflow = previousOverflow;
2181
2200
  };
2182
2201
  }, []);
2183
- react.useEffect(() => {
2202
+ React.useEffect(() => {
2184
2203
  if (typeof document === "undefined") return;
2185
2204
  const handleKeyDown = (event) => {
2186
2205
  if (event.key === "Escape") {
@@ -2276,15 +2295,15 @@ function MarkdownImage({
2276
2295
  maxHeight: "18rem",
2277
2296
  objectFit: "contain"
2278
2297
  };
2279
- const [isLoaded, setIsLoaded] = react.useState(false);
2280
- const [hasError, setHasError] = react.useState(false);
2281
- const [isLightboxOpen, setIsLightboxOpen] = react.useState(false);
2282
- const isUnresolvedRagImage = react.useMemo(
2298
+ const [isLoaded, setIsLoaded] = React.useState(false);
2299
+ const [hasError, setHasError] = React.useState(false);
2300
+ const [isLightboxOpen, setIsLightboxOpen] = React.useState(false);
2301
+ const isUnresolvedRagImage = React.useMemo(
2283
2302
  () => src ? isUnresolvedRagImageSource(src) : false,
2284
2303
  [src]
2285
2304
  );
2286
2305
  const isResolvingRagImage = isResolving && isUnresolvedRagImage;
2287
- react.useEffect(() => {
2306
+ React.useEffect(() => {
2288
2307
  setIsLoaded(false);
2289
2308
  setHasError(false);
2290
2309
  setIsLightboxOpen(false);
@@ -2411,9 +2430,9 @@ function AgentMessage({
2411
2430
  const hasTraceData = !!(message.tracingData || message.executionId) && !isStreaming;
2412
2431
  const isCancelled = message.isCancelled ?? false;
2413
2432
  const currentExecutingStepId = message.currentExecutingStepId;
2414
- const [isStepsExpanded, setIsStepsExpanded] = react.useState(false);
2415
- const wasStreamingRef = react.useRef(isStreaming);
2416
- react.useEffect(() => {
2433
+ const [isStepsExpanded, setIsStepsExpanded] = React.useState(false);
2434
+ const wasStreamingRef = React.useRef(isStreaming);
2435
+ React.useEffect(() => {
2417
2436
  if (isStreaming && hasSteps) {
2418
2437
  setIsStepsExpanded(true);
2419
2438
  }
@@ -2430,13 +2449,13 @@ function AgentMessage({
2430
2449
  const completedWithNoContent = !isStreaming && !isCancelled && content.length === 0 && (message.streamProgress === "completed" || message.streamProgress === "error");
2431
2450
  const conflictErrorMessage = getConflictErrorMessage(message.errorDetails);
2432
2451
  const isError = !!conflictErrorMessage || (isFriendlyWorkflowError(message.errorDetails) || looksLikeRawError(content)) && !hasMeaningfulContent || completedWithNoContent;
2433
- const currentStep = react.useMemo(
2452
+ const currentStep = React.useMemo(
2434
2453
  () => message.steps?.find(
2435
2454
  (s) => s.id === currentExecutingStepId && s.status === "in_progress"
2436
2455
  ),
2437
2456
  [message.steps, currentExecutingStepId]
2438
2457
  );
2439
- const markdownRenderers = react.useMemo(
2458
+ const markdownRenderers = React.useMemo(
2440
2459
  () => createMarkdownComponents({
2441
2460
  isResolvingImages: message.isResolvingImages
2442
2461
  }),
@@ -2510,8 +2529,8 @@ function AgentMessage({
2510
2529
  }) })
2511
2530
  }
2512
2531
  ) });
2513
- const stepsToggleRef = react.useRef(null);
2514
- const handleStepsToggle = react.useCallback(() => {
2532
+ const stepsToggleRef = React.useRef(null);
2533
+ const handleStepsToggle = React.useCallback(() => {
2515
2534
  setIsStepsExpanded((prev) => {
2516
2535
  const next = !prev;
2517
2536
  if (next) {
@@ -2839,23 +2858,23 @@ function MessageList({
2839
2858
  isLoadingMoreMessages = false,
2840
2859
  hasMoreMessages = false
2841
2860
  }) {
2842
- const scrollRef = react.useRef(null);
2843
- const isNearBottomRef = react.useRef(true);
2844
- const [showScrollBtn, setShowScrollBtn] = react.useState(false);
2845
- const prevMessageCountRef = react.useRef(messages.length);
2846
- const scrollHeightBeforePrependRef = react.useRef(null);
2847
- const firstMessageIdRef = react.useRef(messages[0]?.id);
2848
- const getDistanceFromBottom = react.useCallback(() => {
2861
+ const scrollRef = React.useRef(null);
2862
+ const isNearBottomRef = React.useRef(true);
2863
+ const [showScrollBtn, setShowScrollBtn] = React.useState(false);
2864
+ const prevMessageCountRef = React.useRef(messages.length);
2865
+ const scrollHeightBeforePrependRef = React.useRef(null);
2866
+ const firstMessageIdRef = React.useRef(messages[0]?.id);
2867
+ const getDistanceFromBottom = React.useCallback(() => {
2849
2868
  const el = scrollRef.current;
2850
2869
  if (!el) return 0;
2851
2870
  return el.scrollHeight - el.scrollTop - el.clientHeight;
2852
2871
  }, []);
2853
- const scrollToBottom = react.useCallback((behavior = "smooth") => {
2872
+ const scrollToBottom = React.useCallback((behavior = "smooth") => {
2854
2873
  const el = scrollRef.current;
2855
2874
  if (!el) return;
2856
2875
  el.scrollTo({ top: el.scrollHeight, behavior });
2857
2876
  }, []);
2858
- const handleScroll = react.useCallback(() => {
2877
+ const handleScroll = React.useCallback(() => {
2859
2878
  const el = scrollRef.current;
2860
2879
  if (!el) return;
2861
2880
  const distance = getDistanceFromBottom();
@@ -2867,7 +2886,7 @@ function MessageList({
2867
2886
  onLoadMoreMessages();
2868
2887
  }
2869
2888
  }, [getDistanceFromBottom, hasMoreMessages, isLoadingMoreMessages, onLoadMoreMessages]);
2870
- react.useLayoutEffect(() => {
2889
+ React.useLayoutEffect(() => {
2871
2890
  const el = scrollRef.current;
2872
2891
  const prevHeight = scrollHeightBeforePrependRef.current;
2873
2892
  const newFirstId = messages[0]?.id;
@@ -2877,25 +2896,25 @@ function MessageList({
2877
2896
  }
2878
2897
  firstMessageIdRef.current = newFirstId;
2879
2898
  }, [messages]);
2880
- react.useEffect(() => {
2899
+ React.useEffect(() => {
2881
2900
  const prevCount = prevMessageCountRef.current;
2882
2901
  prevMessageCountRef.current = messages.length;
2883
2902
  if (messages.length > prevCount && isNearBottomRef.current) {
2884
2903
  requestAnimationFrame(() => scrollToBottom());
2885
2904
  }
2886
2905
  }, [messages.length, scrollToBottom]);
2887
- react.useEffect(() => {
2906
+ React.useEffect(() => {
2888
2907
  const lastMsg = messages[messages.length - 1];
2889
2908
  if (!lastMsg?.isStreaming) return;
2890
2909
  if (!isNearBottomRef.current) return;
2891
2910
  requestAnimationFrame(() => scrollToBottom());
2892
2911
  });
2893
- react.useEffect(() => {
2912
+ React.useEffect(() => {
2894
2913
  if (messages.length > 0) {
2895
2914
  setTimeout(() => scrollToBottom("instant"), 50);
2896
2915
  }
2897
2916
  }, []);
2898
- react.useEffect(() => {
2917
+ React.useEffect(() => {
2899
2918
  const handleStepsToggle = () => {
2900
2919
  requestAnimationFrame(() => {
2901
2920
  requestAnimationFrame(() => {
@@ -2912,7 +2931,7 @@ function MessageList({
2912
2931
  return () => el.removeEventListener("payman-steps-toggle", handleStepsToggle);
2913
2932
  }
2914
2933
  }, [getDistanceFromBottom, scrollToBottom]);
2915
- const handleScrollToBottom = react.useCallback(() => {
2934
+ const handleScrollToBottom = React.useCallback(() => {
2916
2935
  scrollToBottom();
2917
2936
  }, [scrollToBottom]);
2918
2937
  if (isLoading) {
@@ -3045,7 +3064,7 @@ function ResetSessionConfirmModal({
3045
3064
  onClose,
3046
3065
  onConfirm
3047
3066
  }) {
3048
- const handleKeyDown = react.useCallback(
3067
+ const handleKeyDown = React.useCallback(
3049
3068
  (event) => {
3050
3069
  if (event.key === "Escape") {
3051
3070
  onClose();
@@ -3053,7 +3072,7 @@ function ResetSessionConfirmModal({
3053
3072
  },
3054
3073
  [onClose]
3055
3074
  );
3056
- react.useEffect(() => {
3075
+ React.useEffect(() => {
3057
3076
  if (!isOpen || typeof document === "undefined") return;
3058
3077
  document.addEventListener("keydown", handleKeyDown);
3059
3078
  const previousOverflow = document.body.style.overflow;
@@ -3159,14 +3178,14 @@ function UserMessageV2({
3159
3178
  retryDisabled = false,
3160
3179
  actions
3161
3180
  }) {
3162
- const [copied, setCopied] = react.useState(false);
3163
- const [toast, setToast] = react.useState(null);
3164
- const copyResetTimerRef = react.useRef(null);
3165
- const toastTimerRef = react.useRef(null);
3181
+ const [copied, setCopied] = React.useState(false);
3182
+ const [toast, setToast] = React.useState(null);
3183
+ const copyResetTimerRef = React.useRef(null);
3184
+ const toastTimerRef = React.useRef(null);
3166
3185
  const showCopyAction = actions?.copy ?? true;
3167
3186
  const showEditAction = actions?.edit ?? false;
3168
3187
  const showRetryAction = actions?.retry ?? false;
3169
- react.useEffect(() => {
3188
+ React.useEffect(() => {
3170
3189
  return () => {
3171
3190
  if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
3172
3191
  if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
@@ -3322,18 +3341,18 @@ function MarkdownImageV2({
3322
3341
  onImageClick
3323
3342
  }) {
3324
3343
  const cachedAlready = src ? loadedImageCache.has(src) : false;
3325
- const [isVisible, setIsVisible] = react.useState(cachedAlready);
3326
- const [isLoaded, setIsLoaded] = react.useState(cachedAlready);
3327
- const [hasError, setHasError] = react.useState(false);
3328
- const [retryCount, setRetryCount] = react.useState(0);
3329
- const sentinelRef = react.useRef(null);
3330
- const prevLoadedRef = react.useRef(cachedAlready);
3331
- const isUnresolvedRag = react.useMemo(
3344
+ const [isVisible, setIsVisible] = React.useState(cachedAlready);
3345
+ const [isLoaded, setIsLoaded] = React.useState(cachedAlready);
3346
+ const [hasError, setHasError] = React.useState(false);
3347
+ const [retryCount, setRetryCount] = React.useState(0);
3348
+ const sentinelRef = React.useRef(null);
3349
+ const prevLoadedRef = React.useRef(cachedAlready);
3350
+ const isUnresolvedRag = React.useMemo(
3332
3351
  () => src ? isUnresolvedRagImageSource2(src) : false,
3333
3352
  [src]
3334
3353
  );
3335
3354
  const isResolvingRag = Boolean(isResolving && isUnresolvedRag);
3336
- react.useEffect(() => {
3355
+ React.useEffect(() => {
3337
3356
  if (src && loadedImageCache.has(src)) {
3338
3357
  setIsLoaded(true);
3339
3358
  setIsVisible(true);
@@ -3342,7 +3361,7 @@ function MarkdownImageV2({
3342
3361
  setHasError(false);
3343
3362
  setRetryCount(0);
3344
3363
  }, [src]);
3345
- react.useEffect(() => {
3364
+ React.useEffect(() => {
3346
3365
  const el = sentinelRef.current;
3347
3366
  if (!el || !src) return;
3348
3367
  const rect = el.getBoundingClientRect();
@@ -3463,9 +3482,88 @@ function MarkdownImageV2({
3463
3482
  }
3464
3483
  ) });
3465
3484
  }
3466
- function buildComponents(onImageClick, isResolvingRef) {
3485
+ var RAG_SOURCE_CLASS = "payman-v2-rag-source";
3486
+ var RAG_FOLLOW_UP_CLASS = "payman-v2-rag-follow-up";
3487
+ var SOURCE_PATTERN = /^Sources?:\s*\S/i;
3488
+ var MAX_FOLLOW_UP_LENGTH = 320;
3489
+ var HR_PATTERN = /^-{3,}$|^_{3,}$|^\*{3,}$/;
3490
+ function normalizeRagParagraphText(text) {
3491
+ return text.replace(/\s+/g, " ").trim();
3492
+ }
3493
+ function isRagSourceParagraph(text) {
3494
+ return SOURCE_PATTERN.test(normalizeRagParagraphText(text));
3495
+ }
3496
+ function isRagFollowUpCandidate(text) {
3497
+ const normalized = normalizeRagParagraphText(text);
3498
+ return normalized.length > 0 && normalized.length <= MAX_FOLLOW_UP_LENGTH && normalized.endsWith("?");
3499
+ }
3500
+ function extractRagParagraphTexts(content) {
3501
+ const paragraphs = [];
3502
+ const currentParagraph = [];
3503
+ const flushParagraph = () => {
3504
+ const paragraph = normalizeRagParagraphText(currentParagraph.join(" "));
3505
+ currentParagraph.length = 0;
3506
+ if (paragraph) paragraphs.push(paragraph);
3507
+ };
3508
+ content.replace(/\\n/g, "\n").split(/\r?\n/).forEach((line) => {
3509
+ const trimmedLine = line.trim();
3510
+ if (!trimmedLine) {
3511
+ flushParagraph();
3512
+ return;
3513
+ }
3514
+ if (HR_PATTERN.test(trimmedLine)) {
3515
+ flushParagraph();
3516
+ return;
3517
+ }
3518
+ currentParagraph.push(trimmedLine);
3519
+ });
3520
+ flushParagraph();
3521
+ return paragraphs;
3522
+ }
3523
+ function getRagAnswerParagraphRoles(paragraphs) {
3524
+ const normalized = paragraphs.map(normalizeRagParagraphText);
3525
+ const roles = normalized.map(() => null);
3526
+ const sourceIndexes = normalized.map((paragraph, index) => isRagSourceParagraph(paragraph) ? index : -1).filter((index) => index >= 0);
3527
+ for (const sourceIndex of sourceIndexes) {
3528
+ roles[sourceIndex] = "source";
3529
+ for (const candidateIndex of [sourceIndex - 1, sourceIndex + 1]) {
3530
+ if (candidateIndex >= 0 && candidateIndex < normalized.length && roles[candidateIndex] == null && isRagFollowUpCandidate(normalized[candidateIndex] ?? "")) {
3531
+ roles[candidateIndex] = "follow-up";
3532
+ }
3533
+ }
3534
+ }
3535
+ return roles;
3536
+ }
3537
+ function getRagAnswerParagraphRole(paragraph, paragraphs) {
3538
+ const normalizedParagraph = normalizeRagParagraphText(paragraph);
3539
+ if (isRagSourceParagraph(normalizedParagraph)) return "source";
3540
+ const roles = getRagAnswerParagraphRoles(paragraphs);
3541
+ return paragraphs.map(normalizeRagParagraphText).some((candidate, index) => {
3542
+ return candidate === normalizedParagraph && roles[index] === "follow-up";
3543
+ }) ? "follow-up" : null;
3544
+ }
3545
+ function ragAnswerRoleClassName(role) {
3546
+ if (role === "source") return RAG_SOURCE_CLASS;
3547
+ if (role === "follow-up") return RAG_FOLLOW_UP_CLASS;
3548
+ return void 0;
3549
+ }
3550
+ function reactNodeText(node) {
3551
+ if (typeof node === "string" || typeof node === "number") return String(node);
3552
+ if (Array.isArray(node)) return node.map(reactNodeText).join("");
3553
+ if (React__namespace.isValidElement(node)) {
3554
+ return reactNodeText(node.props.children);
3555
+ }
3556
+ return "";
3557
+ }
3558
+ function buildComponents(onImageClick, isResolvingRef, ragParagraphsRef) {
3467
3559
  return {
3468
- p: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("p", { children }),
3560
+ p: ({ children }) => {
3561
+ const role = getRagAnswerParagraphRole(
3562
+ reactNodeText(children),
3563
+ ragParagraphsRef?.current ?? []
3564
+ );
3565
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: ragAnswerRoleClassName(role), children });
3566
+ },
3469
3567
  code: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("code", { children }),
3470
3568
  pre: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-markdown-pre", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { children }) }),
3471
3569
  ul: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { children }),
@@ -3501,10 +3599,15 @@ function MarkdownRendererV2({
3501
3599
  isResolvingImages,
3502
3600
  onImageClick
3503
3601
  }) {
3504
- const isResolvingRef = react.useRef(isResolvingImages);
3602
+ const isResolvingRef = React.useRef(isResolvingImages);
3505
3603
  isResolvingRef.current = isResolvingImages;
3506
- const components = react.useMemo(
3507
- () => buildComponents(onImageClick, isResolvingRef),
3604
+ const ragParagraphsRef = React.useRef([]);
3605
+ ragParagraphsRef.current = React.useMemo(
3606
+ () => extractRagParagraphTexts(content),
3607
+ [content]
3608
+ );
3609
+ const components = React.useMemo(
3610
+ () => buildComponents(onImageClick, isResolvingRef, ragParagraphsRef),
3508
3611
  [onImageClick]
3509
3612
  );
3510
3613
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -3561,14 +3664,14 @@ function FeedbackReasonModal({
3561
3664
  onClose,
3562
3665
  onSubmit
3563
3666
  }) {
3564
- const [reason, setReason] = react.useState(
3667
+ const [reason, setReason] = React.useState(
3565
3668
  NEGATIVE_FEEDBACK_REASONS[0].value
3566
3669
  );
3567
- const [details, setDetails] = react.useState("");
3568
- const [submitting, setSubmitting] = react.useState(false);
3569
- const [error, setError] = react.useState(null);
3570
- const [reasonOpen, setReasonOpen] = react.useState(false);
3571
- react.useEffect(() => {
3670
+ const [details, setDetails] = React.useState("");
3671
+ const [submitting, setSubmitting] = React.useState(false);
3672
+ const [error, setError] = React.useState(null);
3673
+ const [reasonOpen, setReasonOpen] = React.useState(false);
3674
+ React.useEffect(() => {
3572
3675
  if (open) {
3573
3676
  setReason(NEGATIVE_FEEDBACK_REASONS[0].value);
3574
3677
  setDetails("");
@@ -3577,7 +3680,7 @@ function FeedbackReasonModal({
3577
3680
  setReasonOpen(false);
3578
3681
  }
3579
3682
  }, [open]);
3580
- const handleKeyDown = react.useCallback(
3683
+ const handleKeyDown = React.useCallback(
3581
3684
  (event) => {
3582
3685
  if (event.key !== "Escape") return;
3583
3686
  if (reasonOpen) {
@@ -3588,7 +3691,7 @@ function FeedbackReasonModal({
3588
3691
  },
3589
3692
  [onClose, reasonOpen]
3590
3693
  );
3591
- react.useEffect(() => {
3694
+ React.useEffect(() => {
3592
3695
  if (!open || typeof document === "undefined") return;
3593
3696
  document.addEventListener("keydown", handleKeyDown);
3594
3697
  const previousOverflow = document.body.style.overflow;
@@ -3872,17 +3975,17 @@ function charDelay(char, speed, multiplier) {
3872
3975
  function useTypingEffect(targetText, enabled, speed = RESPONSE_SPEED, initialDisplayedText, speedMultiplier = 1) {
3873
3976
  const instant = speedMultiplier === 0;
3874
3977
  const multiplier = instant ? 1 : Math.max(speedMultiplier, 0.1);
3875
- const [displayedText, setDisplayedText] = react.useState("");
3876
- const displayedRef = react.useRef("");
3877
- const targetRef = react.useRef(targetText);
3878
- const enabledRef = react.useRef(enabled);
3879
- const initialDisplayedRef = react.useRef(initialDisplayedText);
3880
- const timerRef = react.useRef(null);
3881
- const runningRef = react.useRef(false);
3978
+ const [displayedText, setDisplayedText] = React.useState("");
3979
+ const displayedRef = React.useRef("");
3980
+ const targetRef = React.useRef(targetText);
3981
+ const enabledRef = React.useRef(enabled);
3982
+ const initialDisplayedRef = React.useRef(initialDisplayedText);
3983
+ const timerRef = React.useRef(null);
3984
+ const runningRef = React.useRef(false);
3882
3985
  targetRef.current = targetText;
3883
3986
  enabledRef.current = enabled;
3884
3987
  initialDisplayedRef.current = initialDisplayedText;
3885
- react.useEffect(() => {
3988
+ React.useEffect(() => {
3886
3989
  if (!enabled || instant) {
3887
3990
  if (timerRef.current) {
3888
3991
  clearTimeout(timerRef.current);
@@ -3965,26 +4068,26 @@ function AssistantMessageV2({
3965
4068
  actions,
3966
4069
  typingSpeed = 4
3967
4070
  }) {
3968
- const [copied, setCopied] = react.useState(false);
3969
- const [activeFeedback, setActiveFeedback] = react.useState(
4071
+ const [copied, setCopied] = React.useState(false);
4072
+ const [activeFeedback, setActiveFeedback] = React.useState(
3970
4073
  () => getFeedbackState(message)
3971
4074
  );
3972
- const [reasonModalOpen, setReasonModalOpen] = react.useState(false);
4075
+ const [reasonModalOpen, setReasonModalOpen] = React.useState(false);
3973
4076
  const canSubmitFeedback = !!onSubmitFeedback && !!message.executionId;
3974
- const [toast, setToast] = react.useState(null);
3975
- const copyResetTimerRef = react.useRef(null);
3976
- const toastTimerRef = react.useRef(null);
4077
+ const [toast, setToast] = React.useState(null);
4078
+ const copyResetTimerRef = React.useRef(null);
4079
+ const toastTimerRef = React.useRef(null);
3977
4080
  const showCopyAction = actions?.copy ?? true;
3978
4081
  const showTraceAction = (actions?.trace ?? true) && !!onExecutionTraceClick;
3979
4082
  const showThumbsUp = actions?.thumbsUp ?? true;
3980
4083
  const showThumbsDown = actions?.thumbsDown ?? true;
3981
4084
  const hydratedFeedback = message.feedback;
3982
- const hasEverStreamed = react.useRef(!!message.isStreaming);
4085
+ const hasEverStreamed = React.useRef(!!message.isStreaming);
3983
4086
  if (message.isStreaming) hasEverStreamed.current = true;
3984
- react.useEffect(() => {
4087
+ React.useEffect(() => {
3985
4088
  setActiveFeedback(getFeedbackState(message));
3986
4089
  }, [hydratedFeedback, message.id]);
3987
- react.useEffect(() => {
4090
+ React.useEffect(() => {
3988
4091
  return () => {
3989
4092
  if (copyResetTimerRef.current) clearTimeout(copyResetTimerRef.current);
3990
4093
  if (toastTimerRef.current) clearTimeout(toastTimerRef.current);
@@ -3997,6 +4100,7 @@ function AssistantMessageV2({
3997
4100
  return message.isStreaming ? stripIncompleteImageToken(normalized) : normalized;
3998
4101
  })();
3999
4102
  const isThinkingStreaming = !!message.isStreaming && !rawResponseContent && !message.isError;
4103
+ const showTrailingProgress = !!message.isStreaming && !!rawResponseContent && !message.isError && !message.isCancelled && !!message.hasTrailingActivity;
4000
4104
  const responseTypingEnabled = hasEverStreamed.current && Boolean(rawResponseContent) && !message.isError;
4001
4105
  const { displayedText: displayContent, isTyping: isResponseTyping } = useTypingEffect(
4002
4106
  rawResponseContent,
@@ -4155,7 +4259,7 @@ function AssistantMessageV2({
4155
4259
  {
4156
4260
  isStreaming: isThinkingStreaming,
4157
4261
  stickyLabel,
4158
- currentStepLabel
4262
+ currentStepLabel: currentStepLabel ?? message.currentMessage
4159
4263
  }
4160
4264
  )
4161
4265
  },
@@ -4170,6 +4274,27 @@ function AssistantMessageV2({
4170
4274
  onImageClick
4171
4275
  }
4172
4276
  ) : !isThinkingStreaming ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-assistant-msg-placeholder", children: "..." }) : null }),
4277
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: showTrailingProgress && /* @__PURE__ */ jsxRuntime.jsx(
4278
+ framerMotion.motion.div,
4279
+ {
4280
+ initial: { opacity: 0, height: 0 },
4281
+ animate: { opacity: 1, height: "auto" },
4282
+ exit: { opacity: 0, height: 0 },
4283
+ transition: {
4284
+ duration: 0.32,
4285
+ ease: [0.2, 0, 0, 1]
4286
+ },
4287
+ style: { overflow: "hidden" },
4288
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4289
+ ThinkingBlockV2,
4290
+ {
4291
+ isStreaming: true,
4292
+ currentStepLabel: message.currentMessage ?? currentStepLabel
4293
+ }
4294
+ )
4295
+ },
4296
+ "trailing-progress"
4297
+ ) }),
4173
4298
  isCancelled && message.isStreaming && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-assistant-msg-paused", children: [
4174
4299
  /* @__PURE__ */ jsxRuntime.jsx(
4175
4300
  lucideReact.WifiOff,
@@ -4278,10 +4403,10 @@ function OtpInputV2({
4278
4403
  disabled = false,
4279
4404
  error = false
4280
4405
  }) {
4281
- const inputRefs = react.useRef([]);
4406
+ const inputRefs = React.useRef([]);
4282
4407
  const safeMaxLength = Number.isInteger(maxLength) && maxLength > 0 ? Math.min(maxLength, MAX_SUPPORTED_LENGTH) : DEFAULT_MAX_LENGTH;
4283
4408
  const digits = value.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
4284
- react.useEffect(() => {
4409
+ React.useEffect(() => {
4285
4410
  if (disabled) return;
4286
4411
  const timer = window.setTimeout(() => {
4287
4412
  inputRefs.current[0]?.focus();
@@ -4380,31 +4505,31 @@ function VerificationInline({
4380
4505
  onResend
4381
4506
  }) {
4382
4507
  const isNumeric = prompt.verificationType !== "ALPHANUMERIC_CODE";
4383
- const codeLen = react.useMemo(() => codeLengthFromSchema(prompt), [prompt]);
4384
- const [code, setCode] = react.useState("");
4385
- const [errored, setErrored] = react.useState(false);
4386
- const [resendSec, setResendSec] = react.useState(0);
4387
- const [hiddenAfterResend, setHiddenAfterResend] = react.useState(false);
4388
- const lastSubmittedRef = react.useRef(null);
4389
- const resendTimerRef = react.useRef(void 0);
4508
+ const codeLen = React.useMemo(() => codeLengthFromSchema(prompt), [prompt]);
4509
+ const [code, setCode] = React.useState("");
4510
+ const [errored, setErrored] = React.useState(false);
4511
+ const [resendSec, setResendSec] = React.useState(0);
4512
+ const [hiddenAfterResend, setHiddenAfterResend] = React.useState(false);
4513
+ const lastSubmittedRef = React.useRef(null);
4514
+ const resendTimerRef = React.useRef(void 0);
4390
4515
  const status = prompt.status;
4391
4516
  const busy = status === "submitting";
4392
4517
  const stale = status === "stale";
4393
4518
  const locked = busy || stale || expired;
4394
- react.useEffect(() => {
4519
+ React.useEffect(() => {
4395
4520
  if (prompt.subAction === "SubmissionInvalid") {
4396
4521
  setErrored(true);
4397
4522
  setCode("");
4398
4523
  lastSubmittedRef.current = null;
4399
4524
  }
4400
4525
  }, [prompt.subAction, prompt.userActionId]);
4401
- react.useEffect(() => {
4526
+ React.useEffect(() => {
4402
4527
  setHiddenAfterResend(false);
4403
4528
  }, [prompt.expirySeconds, prompt.message, prompt.subAction, prompt.userActionId]);
4404
- react.useEffect(() => {
4529
+ React.useEffect(() => {
4405
4530
  if (code.length < codeLen) lastSubmittedRef.current = null;
4406
4531
  }, [code, codeLen]);
4407
- const doSubmit = react.useCallback(
4532
+ const doSubmit = React.useCallback(
4408
4533
  (value) => {
4409
4534
  if (locked || !value) return;
4410
4535
  if (lastSubmittedRef.current === value) return;
@@ -4416,20 +4541,20 @@ function VerificationInline({
4416
4541
  },
4417
4542
  [locked, onSubmit, prompt.userActionId]
4418
4543
  );
4419
- react.useEffect(() => {
4544
+ React.useEffect(() => {
4420
4545
  if (!isNumeric || locked) return;
4421
4546
  if (code.length === codeLen && /^\d+$/.test(code)) {
4422
4547
  doSubmit(code);
4423
4548
  }
4424
4549
  }, [code, codeLen, doSubmit, isNumeric, locked]);
4425
- react.useEffect(() => {
4550
+ React.useEffect(() => {
4426
4551
  return () => {
4427
4552
  if (typeof resendTimerRef.current === "number") {
4428
4553
  window.clearInterval(resendTimerRef.current);
4429
4554
  }
4430
4555
  };
4431
4556
  }, []);
4432
- const startResendCooldown = react.useCallback(() => {
4557
+ const startResendCooldown = React.useCallback(() => {
4433
4558
  setResendSec(RESEND_COOLDOWN_S);
4434
4559
  if (typeof resendTimerRef.current === "number") {
4435
4560
  window.clearInterval(resendTimerRef.current);
@@ -4447,7 +4572,7 @@ function VerificationInline({
4447
4572
  });
4448
4573
  }, 1e3);
4449
4574
  }, []);
4450
- const handleResend = react.useCallback(async () => {
4575
+ const handleResend = React.useCallback(async () => {
4451
4576
  if (locked || resendSec > 0) return;
4452
4577
  setErrored(false);
4453
4578
  setCode("");
@@ -4460,11 +4585,14 @@ function VerificationInline({
4460
4585
  setHiddenAfterResend(false);
4461
4586
  }
4462
4587
  }, [locked, onResend, prompt.userActionId, resendSec, startResendCooldown]);
4463
- const handleCancel = react.useCallback(() => {
4588
+ const handleCancel = React.useCallback(() => {
4464
4589
  if (busy) return;
4465
4590
  void onCancel(prompt.userActionId);
4466
4591
  }, [busy, onCancel, prompt.userActionId]);
4467
- const description = prompt.message?.trim() || (isNumeric ? `Enter the ${codeLen}-digit code to continue` : "Enter the verification code to continue");
4592
+ const promptMessage = prompt.message?.trim();
4593
+ const description = promptMessage || (isNumeric ? `Enter the ${codeLen}-digit code to continue` : "Enter the verification code to continue");
4594
+ const messageFormat = prompt.metadata?.["payman/messageFormat"];
4595
+ const renderMarkdown = !!promptMessage && messageFormat === "markdown";
4468
4596
  if (hiddenAfterResend) return null;
4469
4597
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-ua", role: "group", "aria-label": "Verification required", children: [
4470
4598
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "payman-v2-ua-head", children: [
@@ -4472,7 +4600,7 @@ function VerificationInline({
4472
4600
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-title", children: "Verification required" }),
4473
4601
  typeof secondsLeft === "number" && !stale && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "payman-v2-ua-timer", children: expired ? "Expired" : `${secondsLeft}s` })
4474
4602
  ] }),
4475
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-desc", children: description }),
4603
+ renderMarkdown ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-markdown", children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownRendererV2, { content: description }) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-desc", children: description }),
4476
4604
  stale ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "payman-v2-ua-stale", children: "This request is no longer available." }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4477
4605
  isNumeric ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-v2-ua-field", children: /* @__PURE__ */ jsxRuntime.jsx(
4478
4606
  OtpInputV2,
@@ -4550,13 +4678,13 @@ function SchemaFormInline({
4550
4678
  onCancel
4551
4679
  }) {
4552
4680
  const schema = prompt.requestedSchema;
4553
- const fields = react.useMemo(() => renderableFields(schema), [schema]);
4554
- const [values, setValues] = react.useState(() => {
4681
+ const fields = React.useMemo(() => renderableFields(schema), [schema]);
4682
+ const [values, setValues] = React.useState(() => {
4555
4683
  const init2 = {};
4556
4684
  for (const [key, field] of fields) init2[key] = defaultValueFor(field);
4557
4685
  return init2;
4558
4686
  });
4559
- const [errors, setErrors] = react.useState({});
4687
+ const [errors, setErrors] = React.useState({});
4560
4688
  const status = prompt.status;
4561
4689
  const busy = status === "submitting";
4562
4690
  const stale = status === "stale";
@@ -4697,10 +4825,10 @@ function NotificationInline({ notification, onDismiss }) {
4697
4825
  }
4698
4826
  function useExpiryCountdown(prompt) {
4699
4827
  const deadlineMs = typeof prompt.expiresAt === "number" && prompt.expiresAt > 0 ? prompt.expiresAt : typeof prompt.expirySeconds === "number" && prompt.expirySeconds > 0 ? Date.now() + Math.floor(prompt.expirySeconds) * 1e3 : void 0;
4700
- const [secondsLeft, setSecondsLeft] = react.useState(
4828
+ const [secondsLeft, setSecondsLeft] = React.useState(
4701
4829
  () => deadlineMs !== void 0 ? Math.max(0, Math.ceil((deadlineMs - Date.now()) / 1e3)) : void 0
4702
4830
  );
4703
- react.useEffect(() => {
4831
+ React.useEffect(() => {
4704
4832
  if (deadlineMs === void 0) {
4705
4833
  setSecondsLeft(void 0);
4706
4834
  return;
@@ -4738,7 +4866,7 @@ function UserActionInline({
4738
4866
  onExpired
4739
4867
  }) {
4740
4868
  const [secondsLeft, expired] = useExpiryCountdown(prompt);
4741
- react.useEffect(() => {
4869
+ React.useEffect(() => {
4742
4870
  if (expired && prompt.kind !== "notification") onExpired?.();
4743
4871
  }, [expired, onExpired, prompt.kind]);
4744
4872
  let body;
@@ -4801,7 +4929,7 @@ function getPromptViewKey(prompt) {
4801
4929
  prompt.message ?? ""
4802
4930
  ].join(PROMPT_KEY_SEPARATOR);
4803
4931
  }
4804
- var MessageListV2 = react.forwardRef(
4932
+ var MessageListV2 = React.forwardRef(
4805
4933
  function MessageListV22({
4806
4934
  messages,
4807
4935
  isStreaming = false,
@@ -4821,25 +4949,25 @@ var MessageListV2 = react.forwardRef(
4821
4949
  onSubmitFeedback,
4822
4950
  typingSpeed = 4
4823
4951
  }, ref) {
4824
- const noop = react.useCallback(async () => {
4952
+ const noop = React.useCallback(async () => {
4825
4953
  }, []);
4826
- const scrollRef = react.useRef(null);
4827
- const scrollInnerRef = react.useRef(null);
4828
- const isNearBottomRef = react.useRef(true);
4829
- const [showScrollBtn, setShowScrollBtn] = react.useState(false);
4830
- const [expiredPromptViewState, setExpiredPromptViewState] = react.useState({});
4831
- const expiredUserActionIdsRef = react.useRef(/* @__PURE__ */ new Set());
4832
- const prevCountRef = react.useRef(messages.length);
4833
- const pauseStickUntilUserMessageRef = react.useRef(false);
4834
- const followingBottomRef = react.useRef(true);
4835
- const lastPinAtRef = react.useRef(0);
4836
- const prevScrollTopRef = react.useRef(0);
4837
- const getDistanceFromBottom = react.useCallback(() => {
4954
+ const scrollRef = React.useRef(null);
4955
+ const scrollInnerRef = React.useRef(null);
4956
+ const isNearBottomRef = React.useRef(true);
4957
+ const [showScrollBtn, setShowScrollBtn] = React.useState(false);
4958
+ const [expiredPromptViewState, setExpiredPromptViewState] = React.useState({});
4959
+ const expiredUserActionIdsRef = React.useRef(/* @__PURE__ */ new Set());
4960
+ const prevCountRef = React.useRef(messages.length);
4961
+ const pauseStickUntilUserMessageRef = React.useRef(false);
4962
+ const followingBottomRef = React.useRef(true);
4963
+ const lastPinAtRef = React.useRef(0);
4964
+ const prevScrollTopRef = React.useRef(0);
4965
+ const getDistanceFromBottom = React.useCallback(() => {
4838
4966
  const el = scrollRef.current;
4839
4967
  if (!el) return 0;
4840
4968
  return el.scrollHeight - el.scrollTop - el.clientHeight;
4841
4969
  }, []);
4842
- const messageActivityFingerprint = react.useMemo(() => {
4970
+ const messageActivityFingerprint = React.useMemo(() => {
4843
4971
  const last = messages[messages.length - 1];
4844
4972
  const promptFingerprint = (userActionPrompts ?? []).map((prompt) => `${getPromptViewKey(prompt)}:${prompt.status}`).join(PROMPT_KEY_SEPARATOR);
4845
4973
  const notificationFingerprint = (notifications ?? []).map((notification) => notification.id).join(PROMPT_KEY_SEPARATOR);
@@ -4865,7 +4993,7 @@ var MessageListV2 = react.forwardRef(
4865
4993
  notificationFingerprint
4866
4994
  ].join(PROMPT_KEY_SEPARATOR);
4867
4995
  }, [isStreaming, messages, notifications, userActionPrompts]);
4868
- const handleUserActionExpired = react.useCallback(
4996
+ const handleUserActionExpired = React.useCallback(
4869
4997
  (promptKey, userActionId) => {
4870
4998
  setExpiredPromptViewState((prev) => {
4871
4999
  if (prev[promptKey]) return prev;
@@ -4882,7 +5010,7 @@ var MessageListV2 = react.forwardRef(
4882
5010
  },
4883
5011
  [messageActivityFingerprint, onExpireUserAction]
4884
5012
  );
4885
- react.useEffect(() => {
5013
+ React.useEffect(() => {
4886
5014
  setExpiredPromptViewState((prev) => {
4887
5015
  let changed = false;
4888
5016
  const next = {};
@@ -4897,7 +5025,7 @@ var MessageListV2 = react.forwardRef(
4897
5025
  return changed ? next : prev;
4898
5026
  });
4899
5027
  }, [messageActivityFingerprint]);
4900
- react.useEffect(() => {
5028
+ React.useEffect(() => {
4901
5029
  const livePromptKeys = new Set((userActionPrompts ?? []).map(getPromptViewKey));
4902
5030
  const liveUserActionIds = new Set((userActionPrompts ?? []).map((p) => p.userActionId));
4903
5031
  for (const userActionId of expiredUserActionIdsRef.current) {
@@ -4918,21 +5046,21 @@ var MessageListV2 = react.forwardRef(
4918
5046
  return changed ? next : prev;
4919
5047
  });
4920
5048
  }, [userActionPrompts]);
4921
- const visibleUserActionPrompts = react.useMemo(
5049
+ const visibleUserActionPrompts = React.useMemo(
4922
5050
  () => userActionPrompts?.filter((prompt) => {
4923
5051
  const promptKey = getPromptViewKey(prompt);
4924
5052
  return !expiredPromptViewState[promptKey]?.hidden;
4925
5053
  }),
4926
5054
  [expiredPromptViewState, userActionPrompts]
4927
5055
  );
4928
- const pinToBottom = react.useCallback((behavior = "instant") => {
5056
+ const pinToBottom = React.useCallback((behavior = "instant") => {
4929
5057
  const el = scrollRef.current;
4930
5058
  if (!el) return;
4931
5059
  lastPinAtRef.current = performance.now();
4932
5060
  el.scrollTo({ top: el.scrollHeight, behavior });
4933
5061
  prevScrollTopRef.current = el.scrollHeight;
4934
5062
  }, []);
4935
- const scrollToBottom = react.useCallback(
5063
+ const scrollToBottom = React.useCallback(
4936
5064
  (behavior = "smooth") => {
4937
5065
  const el = scrollRef.current;
4938
5066
  if (!el) return;
@@ -4942,7 +5070,7 @@ var MessageListV2 = react.forwardRef(
4942
5070
  },
4943
5071
  [pinToBottom]
4944
5072
  );
4945
- react.useImperativeHandle(
5073
+ React.useImperativeHandle(
4946
5074
  ref,
4947
5075
  () => ({
4948
5076
  scrollToBottom: (behavior = "smooth") => {
@@ -4955,7 +5083,7 @@ var MessageListV2 = react.forwardRef(
4955
5083
  }),
4956
5084
  [scrollToBottom]
4957
5085
  );
4958
- const handleScroll = react.useCallback(() => {
5086
+ const handleScroll = React.useCallback(() => {
4959
5087
  const el = scrollRef.current;
4960
5088
  if (!el) return;
4961
5089
  const currentScrollTop = el.scrollTop;
@@ -4976,7 +5104,7 @@ var MessageListV2 = react.forwardRef(
4976
5104
  pauseStickUntilUserMessageRef.current = false;
4977
5105
  }
4978
5106
  }, [getDistanceFromBottom]);
4979
- react.useEffect(() => {
5107
+ React.useEffect(() => {
4980
5108
  const prevCount = prevCountRef.current;
4981
5109
  prevCountRef.current = messages.length;
4982
5110
  if (messages.length > prevCount) {
@@ -4990,7 +5118,7 @@ var MessageListV2 = react.forwardRef(
4990
5118
  }
4991
5119
  }
4992
5120
  }, [messages.length, scrollToBottom]);
4993
- react.useEffect(() => {
5121
+ React.useEffect(() => {
4994
5122
  const inner = scrollInnerRef.current;
4995
5123
  if (!inner) return;
4996
5124
  const pinIfFollowing = () => {
@@ -5015,7 +5143,7 @@ var MessageListV2 = react.forwardRef(
5015
5143
  mo.disconnect();
5016
5144
  };
5017
5145
  }, [pinToBottom]);
5018
- react.useEffect(() => {
5146
+ React.useEffect(() => {
5019
5147
  if (messages.length > 0) {
5020
5148
  setTimeout(() => scrollToBottom("instant"), 50);
5021
5149
  }
@@ -5104,7 +5232,7 @@ var MessageListV2 = react.forwardRef(
5104
5232
  ] });
5105
5233
  }
5106
5234
  );
5107
- var ChatInputV2 = react.forwardRef(
5235
+ var ChatInputV2 = React.forwardRef(
5108
5236
  function ChatInputV22({
5109
5237
  onSend,
5110
5238
  disabled = false,
@@ -5128,20 +5256,20 @@ var ChatInputV2 = react.forwardRef(
5128
5256
  onAnalysisModeChange,
5129
5257
  slashCommands = []
5130
5258
  }, ref) {
5131
- const [value, setValue] = react.useState("");
5132
- const [isFocused, setIsFocused] = react.useState(false);
5133
- const [showActions, setShowActions] = react.useState(false);
5134
- const [showVoiceTooltip, setShowVoiceTooltip] = react.useState(false);
5135
- const [selectedCommandIndex, setSelectedCommandIndex] = react.useState(0);
5136
- const [inlineHint, setInlineHint] = react.useState(null);
5137
- const [commandMenuDismissed, setCommandMenuDismissed] = react.useState(false);
5138
- const textareaRef = react.useRef(null);
5139
- const actionsRef = react.useRef(null);
5140
- const preRecordTextRef = react.useRef("");
5141
- const voiceTooltipTimerRef = react.useRef(
5259
+ const [value, setValue] = React.useState("");
5260
+ const [isFocused, setIsFocused] = React.useState(false);
5261
+ const [showActions, setShowActions] = React.useState(false);
5262
+ const [showVoiceTooltip, setShowVoiceTooltip] = React.useState(false);
5263
+ const [selectedCommandIndex, setSelectedCommandIndex] = React.useState(0);
5264
+ const [inlineHint, setInlineHint] = React.useState(null);
5265
+ const [commandMenuDismissed, setCommandMenuDismissed] = React.useState(false);
5266
+ const textareaRef = React.useRef(null);
5267
+ const actionsRef = React.useRef(null);
5268
+ const preRecordTextRef = React.useRef("");
5269
+ const voiceTooltipTimerRef = React.useRef(
5142
5270
  null
5143
5271
  );
5144
- const voiceDraftSyncActiveRef = react.useRef(false);
5272
+ const voiceDraftSyncActiveRef = React.useRef(false);
5145
5273
  const isInputLocked = disabled || isRecording;
5146
5274
  const hasAttachmentOptions = showUploadImageButton || showAttachFileButton;
5147
5275
  const showAttachmentMenuButton = showAttachmentButton && hasAttachmentOptions;
@@ -5152,14 +5280,14 @@ var ChatInputV2 = react.forwardRef(
5152
5280
  (command) => command.name.toLowerCase().startsWith(commandQuery)
5153
5281
  );
5154
5282
  const showCommandSuggestions = !commandMenuDismissed && !isRecording && !disabled && commandSuggestions.length > 0;
5155
- react.useEffect(() => {
5283
+ React.useEffect(() => {
5156
5284
  if (textareaRef.current) {
5157
5285
  textareaRef.current.style.height = "auto";
5158
5286
  const scrollHeight = textareaRef.current.scrollHeight;
5159
5287
  textareaRef.current.style.height = `${Math.min(scrollHeight, 200)}px`;
5160
5288
  }
5161
5289
  }, [value]);
5162
- react.useEffect(() => {
5290
+ React.useEffect(() => {
5163
5291
  if (disabled) {
5164
5292
  setIsFocused(false);
5165
5293
  setShowActions(false);
@@ -5169,7 +5297,7 @@ var ChatInputV2 = react.forwardRef(
5169
5297
  const frameId = requestAnimationFrame(() => textareaRef.current?.focus());
5170
5298
  return () => cancelAnimationFrame(frameId);
5171
5299
  }, [disabled]);
5172
- react.useImperativeHandle(
5300
+ React.useImperativeHandle(
5173
5301
  ref,
5174
5302
  () => ({
5175
5303
  setDraft: (message) => {
@@ -5186,7 +5314,7 @@ var ChatInputV2 = react.forwardRef(
5186
5314
  }),
5187
5315
  [disabled]
5188
5316
  );
5189
- react.useEffect(() => {
5317
+ React.useEffect(() => {
5190
5318
  if (!showActions) return;
5191
5319
  const handleClickOutside = (e) => {
5192
5320
  if (actionsRef.current && !actionsRef.current.contains(e.target)) {
@@ -5196,29 +5324,29 @@ var ChatInputV2 = react.forwardRef(
5196
5324
  document.addEventListener("mousedown", handleClickOutside);
5197
5325
  return () => document.removeEventListener("mousedown", handleClickOutside);
5198
5326
  }, [showActions]);
5199
- react.useEffect(() => {
5327
+ React.useEffect(() => {
5200
5328
  if (!showAttachmentMenuButton) {
5201
5329
  setShowActions(false);
5202
5330
  }
5203
5331
  }, [showAttachmentMenuButton]);
5204
- react.useEffect(() => {
5332
+ React.useEffect(() => {
5205
5333
  setSelectedCommandIndex(0);
5206
5334
  setCommandMenuDismissed(false);
5207
5335
  }, [commandQuery]);
5208
- react.useEffect(() => {
5336
+ React.useEffect(() => {
5209
5337
  return () => {
5210
5338
  if (voiceTooltipTimerRef.current) {
5211
5339
  clearTimeout(voiceTooltipTimerRef.current);
5212
5340
  }
5213
5341
  };
5214
5342
  }, []);
5215
- react.useEffect(() => {
5343
+ React.useEffect(() => {
5216
5344
  if (!voiceDraftSyncActiveRef.current) return;
5217
5345
  const base = preRecordTextRef.current;
5218
5346
  const separator = base && !base.endsWith(" ") && transcribedText ? " " : "";
5219
5347
  setValue(`${base}${separator}${transcribedText}`);
5220
5348
  }, [isRecording, transcribedText]);
5221
- const handleSend = react.useCallback(() => {
5349
+ const handleSend = React.useCallback(() => {
5222
5350
  if (!value.trim() || disabled) return;
5223
5351
  const commandHint = getSlashCommandValidationHint(value);
5224
5352
  if (commandHint) {
@@ -5238,7 +5366,7 @@ var ChatInputV2 = react.forwardRef(
5238
5366
  }
5239
5367
  });
5240
5368
  }, [value, disabled, onClearEditing, onSend]);
5241
- const selectCommand = react.useCallback(
5369
+ const selectCommand = React.useCallback(
5242
5370
  (command) => {
5243
5371
  const insertText = command.insertText ?? `${command.name} `;
5244
5372
  setValue(insertText);
@@ -5294,14 +5422,14 @@ var ChatInputV2 = react.forwardRef(
5294
5422
  onAttachFileClick?.();
5295
5423
  setShowActions(false);
5296
5424
  };
5297
- const hideVoiceTooltip = react.useCallback(() => {
5425
+ const hideVoiceTooltip = React.useCallback(() => {
5298
5426
  if (voiceTooltipTimerRef.current) {
5299
5427
  clearTimeout(voiceTooltipTimerRef.current);
5300
5428
  voiceTooltipTimerRef.current = null;
5301
5429
  }
5302
5430
  setShowVoiceTooltip(false);
5303
5431
  }, []);
5304
- const startVoiceTooltipTimer = react.useCallback(() => {
5432
+ const startVoiceTooltipTimer = React.useCallback(() => {
5305
5433
  if (isVoiceButtonDisabled || isRecording) return;
5306
5434
  if (voiceTooltipTimerRef.current) {
5307
5435
  clearTimeout(voiceTooltipTimerRef.current);
@@ -5623,9 +5751,9 @@ var ChatInputV2 = react.forwardRef(
5623
5751
  var thinking_atom_default = "data:application/zip;base64,UEsDBBQAAAAIAMWrkFzFrMWzUgAAAF4AAAANAAAAbWFuaWZlc3QuanNvbqtWKkstKs7Mz1OyUjJS0lFKT81LLUosyS8C8h1S8kty8ktKMlP14SzdrGIHQz0zPZDaxLzM3MQSoN5iJavoaqXMFKAe38TMPIXgZKApSrWxtQBQSwMEFAAAAAgAxauQXLRghFpXBAAA1RwAABEAAABhL01haW4gU2NlbmUuanNvbu1YWW/jNhD+KwafJVWkqMtPbdEDfdiiQIq+GMZCcei1GvmApLRdGP7v/YYiddqbGNumR4wcomZGHM7B76N0ZLstm7N3Wb6b3a3UTjGHPTw8sLnvsA2bCx/X3811q+qMzY/sAx74stjXda7WeaGqL1alyup9OeNeEnmcnRxWZB9VWbH54sjqj2weOI2bH5+KYibhoirZnONSa0f7AzykGOQYkGP4X2dFpbq13ONx0mTVu6x6bNXZXosf4erI9OLwjwRw7Tv4WWLSP+ALa7I2Rs0RkvkzRhEZQdWz8iHCms48Z54RMEAs2gABkcGRYVFHBqXv8Sh2GBKgRzDNW00SIClag1GzugVNShk5OUd9zxMj4cI/2UhoSdUwVBJpn53EGPMTOd0hh8hAUwuodC1UoVZ1ud+9UjWog+jvb6hIv9D9egxT8aK8kfte5tD5kiTYCfpaqvUPyABb7beH9/57zlUi4zBwE+FnrsyUdDOfC/c+iNVqzVOVKoH06vwLLDsr1Y6q+VZLgX7+dxQDW29SDGmKsVNPr1iLSyB1Bkui0CDGAEdkEmmpeXghQwe/Td0slnRzyDQ5NwdH8L05htXHLGFqIWk0fQ+YPhc9P3+3VpvsoDrSYR9KFNHWpKvWdgfdV998/e3sF2w70Nb35f7pAFNdfn0z49QpNLHDVnqh0FL9IUXU1kG1eZmDO1rYzB06+imrN30/hNG9JmkiPLIVm9flE2ZFuRZoFzf0hIyXzkJfqXcgtLJGCSHyi1SR/URF9pNJYP8b2adeaEwwoqc6AQ2XS+obXTi7bdi6eGmWs8MmXyEN3+UFPaOzQGOdBcQ52BeeDGXqgB3jRNIlirBe7Vs2TYNkXeiGsFtcTS0w3XLPAp8x0MQ86uluEVPse66t9R4ZdbVd88Vw4tNpqTcZIZekEUrFQi/2fAS3hqPIwBMXSIqBp6yqVN1shjHH5NejpvUyOtdZzNyX93lNVfwPn+vGrHjDpiuxSXAvFIHDhSdFRNghvcSPnMQLhKRbo3dbg0bvNgYWsZ4xcz7txuIYrGOfOzz0/JiTUZB4acwdVwiNa43abfVGrbVnMA79fCXG3WGvPdLLlM5nc6czWiBpKFXxq07ptqBOudg7hDI49vRUOAJYuJggZiQDrqFSxA6CMgj2/8PCNqDty6oCjqlViaL8XOb0iC4JjWfU51Xb6CiLunz8CiPop0cnnIb6Ryd7YGpf4bqTUmhPSpSSYXxuSsBtk3ztGkQwPAJS7QevkWdOa2SLNLSn378smfqMTZF0yRzV8Ez4SToNf4i5drmWByfHdk1B5PxGQW+Xgix5jMlhTB5jchlS0CeNOiK74GREQROOGVLQhKFuFHSjoH+CgkSELwM3CrqCgjDJGQoKbhT0pikIH0oE+CAMgOmpF3HAof580grxHaWRdt9opjr9wWUyj6UWHnvSD4yZ1N9pBiIXshuF3Cjktd9izmHo61CIxeSAPpWd/gRQSwECFAAUAAAACADFq5BcxazFs1IAAABeAAAADQAAAAAAAAAAAAAAAAAAAAAAbWFuaWZlc3QuanNvblBLAQIUABQAAAAIAMWrkFy0YIRaVwQAANUcAAARAAAAAAAAAAAAAAAAAH0AAABhL01haW4gU2NlbmUuanNvblBLBQYAAAAAAgACAHoAAAADBQAAAAA=";
5624
5752
  var DEFAULT_SIZE = 36;
5625
5753
  function useElapsedSeconds(isStreaming) {
5626
- const [elapsed, setElapsed] = react.useState(0);
5627
- const startRef = react.useRef(null);
5628
- react.useEffect(() => {
5754
+ const [elapsed, setElapsed] = React.useState(0);
5755
+ const startRef = React.useRef(null);
5756
+ React.useEffect(() => {
5629
5757
  if (!isStreaming) {
5630
5758
  startRef.current = null;
5631
5759
  setElapsed(0);
@@ -5684,22 +5812,22 @@ function StreamingIndicatorV2({
5684
5812
  ) });
5685
5813
  }
5686
5814
  function ImageLightboxV2({ src, alt, onClose }) {
5687
- const [isMounted, setIsMounted] = react.useState(false);
5688
- const [isImageLoaded, setIsImageLoaded] = react.useState(false);
5689
- react.useEffect(() => {
5815
+ const [isMounted, setIsMounted] = React.useState(false);
5816
+ const [isImageLoaded, setIsImageLoaded] = React.useState(false);
5817
+ React.useEffect(() => {
5690
5818
  setIsMounted(true);
5691
5819
  return () => setIsMounted(false);
5692
5820
  }, []);
5693
- react.useEffect(() => {
5821
+ React.useEffect(() => {
5694
5822
  setIsImageLoaded(false);
5695
5823
  }, [src]);
5696
- const handleKeyDown = react.useCallback(
5824
+ const handleKeyDown = React.useCallback(
5697
5825
  (e) => {
5698
5826
  if (e.key === "Escape") onClose();
5699
5827
  },
5700
5828
  [onClose]
5701
5829
  );
5702
- react.useEffect(() => {
5830
+ React.useEffect(() => {
5703
5831
  if (!src || typeof document === "undefined") return;
5704
5832
  document.addEventListener("keydown", handleKeyDown);
5705
5833
  const previousOverflow = document.body.style.overflow;
@@ -5848,10 +5976,10 @@ function TraceTimelineModal({
5848
5976
  apiBaseUrl,
5849
5977
  apiHeaders
5850
5978
  }) {
5851
- const [trace, setTrace] = react.useState(null);
5852
- const [loading, setLoading] = react.useState(false);
5853
- const [error, setError] = react.useState(null);
5854
- react.useEffect(() => {
5979
+ const [trace, setTrace] = React.useState(null);
5980
+ const [loading, setLoading] = React.useState(false);
5981
+ const [error, setError] = React.useState(null);
5982
+ React.useEffect(() => {
5855
5983
  if (!open || !executionId) return;
5856
5984
  const ctrl = new AbortController();
5857
5985
  setLoading(true);
@@ -5873,7 +6001,7 @@ function TraceTimelineModal({
5873
6001
  }).finally(() => setLoading(false));
5874
6002
  return () => ctrl.abort();
5875
6003
  }, [open, executionId, apiBaseUrl, apiHeaders]);
5876
- const totalMs = react.useMemo(() => {
6004
+ const totalMs = React.useMemo(() => {
5877
6005
  if (!trace) return 0;
5878
6006
  const meta = trace.runMetadata?.totalTimeMs;
5879
6007
  if (typeof meta === "number" && meta > 0) return meta;
@@ -5882,7 +6010,7 @@ function TraceTimelineModal({
5882
6010
  if (starts.length === 0 || ends.length === 0) return 0;
5883
6011
  return Math.max(...ends) - Math.min(...starts);
5884
6012
  }, [trace]);
5885
- const accountedMs = react.useMemo(
6013
+ const accountedMs = React.useMemo(
5886
6014
  () => (trace?.pipelineSteps ?? []).reduce(
5887
6015
  (sum, s) => sum + (s.durationMs ?? 0),
5888
6016
  0
@@ -6143,12 +6271,12 @@ var NOOP_ASYNC = async () => {
6143
6271
  var NOOP = () => {
6144
6272
  };
6145
6273
  function useSentryChatCallbacks(callbacks, config) {
6146
- const sentryCtxRef = react.useRef({});
6147
- const callbacksRef = react.useRef(callbacks);
6274
+ const sentryCtxRef = React.useRef({});
6275
+ const callbacksRef = React.useRef(callbacks);
6148
6276
  callbacksRef.current = callbacks;
6149
6277
  const initialSessionId = config.initialSessionId;
6150
6278
  const apiHeaders = config.api.headers;
6151
- react.useEffect(() => {
6279
+ React.useEffect(() => {
6152
6280
  sentryCtxRef.current.agentId = config.agentId;
6153
6281
  sentryCtxRef.current.sessionOwnerId = config.sessionParams?.id;
6154
6282
  if (initialSessionId) {
@@ -6164,13 +6292,13 @@ function useSentryChatCallbacks(callbacks, config) {
6164
6292
  initialSessionId,
6165
6293
  apiHeaders
6166
6294
  ]);
6167
- react.useEffect(() => {
6295
+ React.useEffect(() => {
6168
6296
  const endpoint = config.api.streamEndpoint || "/api/playground/ask/stream";
6169
6297
  return subscribeToCfRay(endpoint, (cfRay) => {
6170
6298
  sentryCtxRef.current.cfRay = cfRay;
6171
6299
  });
6172
6300
  }, [config.api.streamEndpoint]);
6173
- return react.useMemo(
6301
+ return React.useMemo(
6174
6302
  () => ({
6175
6303
  onMessageSent: (msg) => callbacksRef.current?.onMessageSent?.(msg),
6176
6304
  onStreamStart: () => callbacksRef.current?.onStreamStart?.(),
@@ -6219,7 +6347,7 @@ function useSentryChatCallbacks(callbacks, config) {
6219
6347
  []
6220
6348
  );
6221
6349
  }
6222
- var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6350
+ var PaymanChatInner = React.forwardRef(function PaymanChatInner2({
6223
6351
  config,
6224
6352
  callbacks = {},
6225
6353
  className,
@@ -6230,18 +6358,18 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6230
6358
  hasMoreMessages = false,
6231
6359
  chat
6232
6360
  }, ref) {
6233
- const [inputValue, setInputValue] = react.useState("");
6234
- const prevInputValueRef = react.useRef(inputValue);
6235
- const [hasEverSentMessage, setHasEverSentMessage] = react.useState(false);
6236
- const [lightboxSrc, setLightboxSrc] = react.useState(null);
6237
- const [lightboxAlt, setLightboxAlt] = react.useState("");
6238
- const [editingMessageId, setEditingMessageId] = react.useState(null);
6239
- const [isResetSessionConfirmOpen, setIsResetSessionConfirmOpen] = react.useState(false);
6240
- const [analysisMode, setAnalysisMode] = react.useState("fast");
6241
- const chatInputV2Ref = react.useRef(null);
6242
- const messageListV2Ref = react.useRef(null);
6243
- const resetToEmptyStateRef = react.useRef(false);
6244
- react.useEffect(() => {
6361
+ const [inputValue, setInputValue] = React.useState("");
6362
+ const prevInputValueRef = React.useRef(inputValue);
6363
+ const [hasEverSentMessage, setHasEverSentMessage] = React.useState(false);
6364
+ const [lightboxSrc, setLightboxSrc] = React.useState(null);
6365
+ const [lightboxAlt, setLightboxAlt] = React.useState("");
6366
+ const [editingMessageId, setEditingMessageId] = React.useState(null);
6367
+ const [isResetSessionConfirmOpen, setIsResetSessionConfirmOpen] = React.useState(false);
6368
+ const [analysisMode, setAnalysisMode] = React.useState("fast");
6369
+ const chatInputV2Ref = React.useRef(null);
6370
+ const messageListV2Ref = React.useRef(null);
6371
+ const resetToEmptyStateRef = React.useRef(false);
6372
+ React.useEffect(() => {
6245
6373
  if (config.sentryDsn) {
6246
6374
  initSentryIfNeeded(config.sentryDsn);
6247
6375
  }
@@ -6257,7 +6385,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6257
6385
  getSessionId,
6258
6386
  getMessages
6259
6387
  } = chat;
6260
- react.useEffect(() => {
6388
+ React.useEffect(() => {
6261
6389
  if (resetToEmptyStateRef.current) {
6262
6390
  if (messages.length === 0) {
6263
6391
  setHasEverSentMessage(false);
@@ -6269,7 +6397,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6269
6397
  setHasEverSentMessage(true);
6270
6398
  }
6271
6399
  }, [messages.length, hasEverSentMessage]);
6272
- react.useEffect(() => {
6400
+ React.useEffect(() => {
6273
6401
  if (!editingMessageId) return;
6274
6402
  const editingMessageStillExists = messages.some(
6275
6403
  (message) => message.id === editingMessageId && message.role === "user"
@@ -6308,7 +6436,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6308
6436
  }
6309
6437
  }
6310
6438
  );
6311
- const contextValue = react.useMemo(
6439
+ const contextValue = React.useMemo(
6312
6440
  () => ({
6313
6441
  resetSession,
6314
6442
  clearMessages,
@@ -6335,8 +6463,8 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6335
6463
  onAttachFileClick,
6336
6464
  onMessageFeedback
6337
6465
  } = callbacks;
6338
- const [debugTraceExecutionId, setDebugTraceExecutionId] = react.useState(null);
6339
- const handleSubmitFeedback = react.useCallback(
6466
+ const [debugTraceExecutionId, setDebugTraceExecutionId] = React.useState(null);
6467
+ const handleSubmitFeedback = React.useCallback(
6340
6468
  async ({ messageId, executionId, feedback, details }) => {
6341
6469
  if (!executionId) {
6342
6470
  throw new Error("Cannot submit feedback before the response completes");
@@ -6367,14 +6495,14 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6367
6495
  onMessageFeedback
6368
6496
  ]
6369
6497
  );
6370
- const onExecutionTraceClick = react.useMemo(() => {
6498
+ const onExecutionTraceClick = React.useMemo(() => {
6371
6499
  if (!config.debug) return rawOnExecutionTraceClick;
6372
6500
  return (data) => {
6373
6501
  rawOnExecutionTraceClick?.(data);
6374
6502
  if (data.executionId) setDebugTraceExecutionId(data.executionId);
6375
6503
  };
6376
6504
  }, [config.debug, rawOnExecutionTraceClick]);
6377
- const performResetSession = react.useCallback(() => {
6505
+ const performResetSession = React.useCallback(() => {
6378
6506
  resetToEmptyStateRef.current = true;
6379
6507
  setEditingMessageId(null);
6380
6508
  setIsResetSessionConfirmOpen(false);
@@ -6395,13 +6523,13 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6395
6523
  resetSession,
6396
6524
  stopRecording
6397
6525
  ]);
6398
- const requestResetSession = react.useCallback(() => {
6526
+ const requestResetSession = React.useCallback(() => {
6399
6527
  setIsResetSessionConfirmOpen(true);
6400
6528
  }, []);
6401
- const closeResetSessionConfirm = react.useCallback(() => {
6529
+ const closeResetSessionConfirm = React.useCallback(() => {
6402
6530
  setIsResetSessionConfirmOpen(false);
6403
6531
  }, []);
6404
- react.useImperativeHandle(ref, () => ({
6532
+ React.useImperativeHandle(ref, () => ({
6405
6533
  resetSession: performResetSession,
6406
6534
  clearMessages,
6407
6535
  cancelStream,
@@ -6440,7 +6568,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6440
6568
  slashCommands: slashCommandsConfig,
6441
6569
  commandPermissions
6442
6570
  } = config;
6443
- const messageActions = react.useMemo(
6571
+ const messageActions = React.useMemo(
6444
6572
  () => ({
6445
6573
  userMessageActions: {
6446
6574
  copy: messageActionsConfig?.userMessageActions?.copy ?? true,
@@ -6456,18 +6584,18 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6456
6584
  }),
6457
6585
  [messageActionsConfig]
6458
6586
  );
6459
- const slashCommands = react.useMemo(
6587
+ const slashCommands = React.useMemo(
6460
6588
  () => enableSlashCommands ? filterSlashCommands(
6461
6589
  slashCommandsConfig ?? DEFAULT_SLASH_COMMANDS,
6462
6590
  commandPermissions
6463
6591
  ) : [],
6464
6592
  [commandPermissions, enableSlashCommands, slashCommandsConfig]
6465
6593
  );
6466
- const isSessionParamsConfigured = react.useMemo(() => {
6594
+ const isSessionParamsConfigured = React.useMemo(() => {
6467
6595
  if (!sessionParams) return false;
6468
6596
  return !!(sessionParams.id?.trim() && sessionParams.name?.trim());
6469
6597
  }, [sessionParams?.id, sessionParams?.name]);
6470
- react.useEffect(() => {
6598
+ React.useEffect(() => {
6471
6599
  const wasEmpty = prevInputValueRef.current.trim() === "";
6472
6600
  const isEmpty2 = inputValue.trim() === "";
6473
6601
  prevInputValueRef.current = inputValue;
@@ -6534,7 +6662,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6534
6662
  void sendMessage(text.trim(), { analysisMode: effectiveAnalysisMode });
6535
6663
  }
6536
6664
  };
6537
- const handleVoicePress = react.useCallback(async () => {
6665
+ const handleVoicePress = React.useCallback(async () => {
6538
6666
  if (!voiceAvailable) return;
6539
6667
  if (isRecording) {
6540
6668
  stopRecording();
@@ -6543,7 +6671,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6543
6671
  clearTranscript();
6544
6672
  await startRecording();
6545
6673
  }, [clearTranscript, isRecording, startRecording, stopRecording, voiceAvailable]);
6546
- const handleEditMessageDraft = react.useCallback((messageId) => {
6674
+ const handleEditMessageDraft = React.useCallback((messageId) => {
6547
6675
  const targetMessage = messages.find((message) => message.id === messageId);
6548
6676
  if (!targetMessage?.content.trim()) return;
6549
6677
  setEditingMessageId(messageId);
@@ -6552,7 +6680,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6552
6680
  messageListV2Ref.current?.scrollToBottom("smooth");
6553
6681
  });
6554
6682
  }, [messages]);
6555
- const handleRetryUserMessage = react.useCallback((messageId) => {
6683
+ const handleRetryUserMessage = React.useCallback((messageId) => {
6556
6684
  if (isWaitingForResponse) return;
6557
6685
  const targetMessage = messages.find(
6558
6686
  (message) => message.id === messageId && message.role === "user"
@@ -6569,7 +6697,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6569
6697
  });
6570
6698
  });
6571
6699
  }, [isWaitingForResponse, messages, sendMessage, effectiveAnalysisMode]);
6572
- const handleClearEditing = react.useCallback(() => {
6700
+ const handleClearEditing = React.useCallback(() => {
6573
6701
  setEditingMessageId(null);
6574
6702
  }, []);
6575
6703
  return /* @__PURE__ */ jsxRuntime.jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
@@ -6759,7 +6887,7 @@ var PaymanChatInner = react.forwardRef(function PaymanChatInner2({
6759
6887
  }
6760
6888
  ) });
6761
6889
  });
6762
- var PaymanChat = react.forwardRef(
6890
+ var PaymanChat = React.forwardRef(
6763
6891
  function PaymanChat2(props, ref) {
6764
6892
  const mergedCallbacks = useSentryChatCallbacks(props.callbacks, props.config);
6765
6893
  const chat = useChatV2(props.config, mergedCallbacks);